Using namespaces

Topics to be covered
  • the Unified Namespace

  • how we marked classes that are not intended to be extended by a module

  • Module installation

  • How to extend the OXID eShop’s namespaced classes

  • Use your own namespaces in a module with OXID eShop
    • Install the module via composer

    • Use own module classes

    • Add new module controllers

Introduction

The following part of the documentation will cover the namespaces and what this means for a module developer.

In order to use composer autoload, folder structure and class files needs to match the namespace (UpperCamelCase).

The Unified Namespace (OxidEsales\Eshop)

The Unified Namespace (OxidEsales\Eshop) provides an edition independent namespace for module and core developers.

Important

Please do not use the shop classes from the edition namespaces in your code!

If you want to refer to a class name, always use the ::class notation instead of using a plain string.

Example:

$articleFromUnifiedNamespace = oxNew(\OxidEsales\Eshop\Application\Model\Article::class);

Classes that are not to be extended by a module

We mark all classes that are not to be overwritten by a module with @internal but apart from that there is currently no mechanism that prevents a module developer from trying to extend such a shop class. We do not guarantee that the shop will work as expected if you try to do that though. What can definitely not be extended by a module is the OxidEsales\Eshop\Core\UtilsObject class.

Module installation

Go to the shop’s root directory and configure/require the module:

composer config repositories.myvendor/mymodule vcs https://github.com/myvendor/mymodule
composer require myvendor/mymodule:dev-main

Extend an OXID eShop class with a module

If you want to adjust a standard OXID eShop class with a module (let’s choose OxidEsales\Eshop\Application\Model\Article), you need to extend the module class (let’s say MyVendorMyModuleArticle) from a Unified Namespace parent class (MyVendorMyModuleArticle_parent). The shop creates the class chain in such a way that once your module is activated, all methods from the OxidEsales\Eshop\Application\Model\Article are available in MyVendorMyModuleArticle and can be overwritten with module functionality.

Now create a class to extend a shop class in your module’s namespace:

<?php
 # Example for module with own namespace

 namespace MyVendor\MyModuleNamespace\Application\Model;

 class MyModuleArticle extends MyModuleArticle_parent
 {
     public function getSize()
     {
         $originalSize = parent::getSize();

         //double the size
         $newSize = 2 * $originalSize;

         return $newSize;
     }
 }

Register the class in the module’s metadata.php:

# Register the extend class in the module's metadata.php
//.....
'extend'      => array(
     \OxidEsales\Eshop\Application\Model\Article::class =>
          MyVendor\MyModuleNamespace\Application\Model\MyModuleArticle::class
)
//.....

Install and register your module with composer

To have the composer autoloader find your module file via namespace, create a composer.json file in the module’s root directory.

{
    "name": "myvendor/mymodule",
    "autoload": {
        "psr-4": {
            "MyVendor\\MyModuleNamespace\\": "./src"
        }
    }
}

Then in the shop’s root directory do

composer config repositories.myvendor/mymodule vcs https://github.com/myvendor/mymodule
composer require myvendor/mymodule:dev-main

and run composer update.

Using namespaces in module classes that do not extend OXID eShop classes

Add for example a model class to your module:

<?php
namespace MyVendor\MyModuleNamespace\Application\Model;

class MyModuleModel
{
    public function doSomething()
    {
        //.....
        // do something
        //......
        return $someResult;
    }
}

There is no need to register this class in the metadata.php as the composer autoloader will do the trick.

<?php
 namespace MyVendor\MyModuleNamespace\Application\Controller;

 use MyVendor\MyModuleNamespace\Application\Model\MyModuleModel;

 class MyModulePaymentController extends MyModulePaymentController_parent
 {
     public function render()
     {
         $template = parent::render();
         //.....
         $model = new MyModuleModel;
         $someResult = $model->doSomething();
         // do something else
         //......
         return $template;
     }

or with oxNew instead of new

<?php
 namespace MyModuleNamespace/Application/Controller;

 class MyModulePaymentController extends MyModulePaymentController_parent
 {
     public function render()
     {
         $template = parent::render();
         //.....
         $model = oxNew(\MyVendor\MyModuleNamespace\Application\Model\MyModuleModel::class);
         $someResult = $model->doSomething();
         // do something else
         //......
         return $template;
     }

In the module’s metadata you only need to register the class extending the shop’s payment controller but not your module’s new model class.

# Register the extend class in the module's metadata.php
//.....
'extend'      => array(
     \OxidEsales\Eshop\Application\Controller\PaymentController::class
         => MyVendor\MyModuleNamespace\Application\Controller\MyModulePaymentController::class
)
//.....

Add new module controllers

If you want to introduce a new controller that handles own form data you need to register its class in the module’s metadata.php. More information can be found here.