Modules

For updating existing modules from OXID eShop 4.10/5.3 to OXID eShop 6, either

  • get an OXID eShop 6 compatible version of your modules or

  • update the modules by yourself. Please have a look at the following sections on how to update by yourself.

Overview about the steps to port a module to the OXID eShop version 6.0

In the table below you can find an overview what steps you can, and at least have to do, to port your module to the OXID eShop version 6.0. Every line of the table represents a step or an adaption. As you see, there are two columns named “Minimal” and “Full”. Your absolute to-dos for now are marked as “Minimal” with a “x”. They tell you, that you have to do them in order to end up with a module which works with the OXID eShop version 6.0. All to-dos are marked as “Full”. This tells you, that you are not done after the “Minimal” porting of your module. There are more steps to make to be fully aligned with the version 6.0. We strongly recommend you to do the “Full” steps now, or as soon as possible. We do so, cause

  • you will fit better in OXIDs long term stable investment strategy and

  • with the next (major) versions there will be more changes, which will add up to a bigger amount of open to-dos.

Topic

Minimal

Full

Assure test coverage for your code

x

x

Convert all files to UTF-8

x

x

Adjust PHP version

x

x

Adjust removed functionality

x

x

Adjust your database code to the new DB Layer

x

x

Adjust the code style of your modules code

x

Exchange BC Layer classes

x

Remove deprecated code

x

Installable via composer*

x

Introduce a namespace in your module

x

(*) If you are maintaining a module which is part of the OXID eShop Compilation the installation has to work via composer!

Minimal steps

This section describes the minimum changes, which are necessary to make an existing module compatible with OXID eShop version 6.0.

Cover your code with tests

Make sure that you have all important logic covered by tests - Unit, Integration and Acceptance. Let them run once after every step in this guide.

UTF-8 only

Starting with the 6.0 the OXID eShop is UTF-8 only. This means all your modules
  • Translation files,

  • SQL files,

  • Code files,

  • Test files,

  • and all other files

have to be UTF-8 encoded.

Required PHP version

The code must work with PHP 5.6 and higher. Check the official PHP migration documentation on php.net what you have to do.

Removed functionality in OXID eShop

Make sure your module does not use any of the functionality that was deprecated in 5.3 and has been removed in OXID eShop 6.0. You can find a list of changes in OXID Forge.

Stick to database interfaces

Especially have an eye on the changes in database layer. ADOdb Lite (OXID eShop 5.x) was exchanged in favour of Doctrine/DBAL which leads to some slightly different behaviour in some cases. We had to introduce some backwards compatibility breaks there.

Check 5.3 code for what will be deprecated:

New equivalents:

In ADOdb Lite there was not such a thing as a ResultSetInterface, it was introduced in v5.3.0 to be able to have an upgrade path to the version 6.0.

IMPORTANT: Return values of e.g. oxDb::getDb()->select() and oxDb::getDb()->selectLimit() have changed, now an instance of ResultSet (implementing ResultSetInterface) is returned.

Deprecated (5.3) logic, does not work in 6.0 and higher any more:

$rs = oxDb::getDb()->select($sQuery);
if ($rs != false && $rs->recordCount() > 0) {
    while (!$rs->EOF) {
        //do something
        $rs->moveNext();
    }
}

Example: new logic (since 6.0)

$resultSet = \OxidEsales\Eshop\Core\DatabaseProvider::getDb()->select($query);
//Fetch the results row by row
if ($resultSet != false && $resultSet->count() > 0) {
    while (!$resultSet->EOF) {
        $row = $resultSet->getFields();
        //do something
        $resultSet->fetchRow();
    }
}

Another example: new logic (since 6.0)

$resultSet = \OxidEsales\Eshop\Core\DatabaseProvider::getDb()->select($query);
//Fetch all at once (beware of big arrays)
$allResults = $resultSet->fetchAll()
foreach($allResults as $row) {
   //do something
};

IMPORTANT NOTE: do not try something like this, you will lose the first result row:

$resultSet = \OxidEsales\Eshop\Core\DatabaseProvider::getDb()->select($query);
while ($row = $resultSet->fetchRow()) {
       //do something
};

What will happen: the ResultSet immediately executes the first call to ResultSet::fetchRow() in its constructor and each following call to ResultSet::fetchRow() advances the content of ResultSet::fields to the next row. Always access ResultSet::fields before calling ResultSet::fetchRow() again.

Full steps

On top of the minimal steps we recommend you to take the following steps to completely move your module to the version 6.0 of the OXID eShop.

Code style

From OXID eShop version 6.0 on PSR-0 and PSR-4 standards will be used in OXID eShop core code. Our Codesniffer can help you achieving this goal.

Backwards compatibility layer and Unified Namespace

Mind that from version 6.0 on the OXID eShop is using namespaces. Therefore nearly all classes known from 5.3 (e.g. oxArticle) and previous versions are deprecated now. They exist only as aliases in which we call the Backwards Compatibility Layer (from now on abbreviated with BC Layer).

As long as the BC Layer is in place, you can use the backwards compatibility classes (e.g. oxArticle) equivalent to the actual classes from the Unified Namespace (e.g. \OxidEsales\Eshop\Application\Model\Article). The Unified Namespace is an abstraction for classes which exist in several Editions of the OXID eShop. As soon as the BC Layer is dropped in a future release of OXID eShop, you will have to fully port your module to the new Unified Namespaced classes (see Unified Namespace).

Replace all OXID eShop backwards compatibility classes (e.g. oxArticle) in your module by the equivalent fully qualified Unified Namespace classes.

  • check usages in oxNew and new
    // Old style (using BC Layer)
    $article = oxNew('oxarticle');
    $field = new oxField();
    
    // New style:
    $article = oxNew(\OxidEsales\Eshop\Application\Model\Article::class);
    $field   = new \OxidEsales\Eshop\Core\Field();
    
  • Use the Unified Namespace class names for calls to Registry::set() and Registry::get().
    // Old style:
    oxRegistry::get('oxSeoEncoderVendor');
    
    // New style:
    \OxidEsales\Eshop\Core\Registry::get(\OxidEsales\Eshop\Application\Model\SeoEncoderVendor::class);
    

Remove deprecated code

Besides the usage of backwards compatibility classes there might exist more usages of deprecated code in your modules. Choose your favourite IDE (integrated development environment) and do a code analysis on deprecations. Additionally you can have a look to a list of all deprecations in the source code documentation <http://docu.oxid-esales.com/CE/sourcecodedocumentation>.

Make module installable via composer

We recommend that the module is made installable via composer. Modules that will go to the (OXID eShop Compilation) MUST be installable via composer. Information what needs to be done (the keyword is composer.json) can be found here. Verify that composer correctly installs it.

Important

if you made changes to the file modules/composer.json in OXID eShop 4.10 / 5.3, port those changes into the root composer.json file in OXID eShop 6 or into a modules composer.json file

Move the module under a module namespace

  • Introduce the module namespace in the module’s composer.json file’s autoload section.

    "autoload": {
        "psr-4": {
            "MyVendor\\MyModuleNamespace\\": "../../../source/modules/myvendor/mymoduleid"
        }
    }
    

    NOTE: we recommend to point the namespace to the module’s installation path in the shop’s module directory. See for example OXID eShop Extension PayPal.

    "autoload": {
        "psr-4": {
            "OxidEsales\\PayPalModule\\": "../../../source/modules/oe/oepaypal"
        }
    }
    

    Use the following pattern for your module namespace: <vendor of the module>`\<module ID> (e.g. OxidEsales\PayPalModule)

    You can find more about the Vendor Id in the Glossary.

  • Move all the module classes under namespace.

    //before:
    class oePayPalIPNHandler extends oePayPalController
    {
        //...
    }
    
    $handler = oxNew('oepaypalipnhandler');
    
    //after:
    namespace OxidEsales\PayPalModule\Controller;
    class IPNHandler extends \OxidEsales\PayPalModule\Controller\FrontendController
    {
         //...
    }
    
    $handler = oxNew(\OxidEsales\PayPalModule\Controller\IPNHandler::class);
    

    While this step you should exchange all occurrences of the files name. Especially in the metadata.php the ‘extends’ section should not be forgotten! Remove the entry from the ‘files’ section, after you moved the class into the namespace. It is not longer needed, cause the namespaces get autoloaded via composer.

  • Update metadata.php to version 2.0, see here. In case the module uses it’s own controllers that do not simply chain extend shop controllers, you need to register a controller key in the metadata.php ‘controller’ section like described here.

    'controllers' => array(
        ...
        'oepaypalipnhandler' => \OxidEsales\PayPalModule\Controller\IPNHandler::class,
        ...
    ),
    

    Your Controller Keys have to be lowercase and have to follow this pattern: <vendor of the module><module ID><controller name> (e.g. oepaypalipnhandler)