PHPackages                             oxid-esales/examples-module - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. oxid-esales/examples-module

ActiveOxideshop-module[Utility &amp; Helpers](/categories/utility)

oxid-esales/examples-module
===========================

Module with solution examples

v2.0.0(5mo ago)3402[3 issues](https://github.com/OXID-eSales/examples-module/issues)2proprietaryPHPPHP ^8.2CI passing

Since May 14Pushed 2mo ago2 watchersCompare

[ Source](https://github.com/OXID-eSales/examples-module)[ Packagist](https://packagist.org/packages/oxid-esales/examples-module)[ RSS](/packages/oxid-esales-examples-module/feed)WikiDiscussions b-7.5.x Synced 1mo ago

READMEChangelogDependencies (15)Versions (11)Used By (2)

OXID eShop Examples Module
==========================

[](#oxid-eshop-examples-module)

[![Development](https://github.com/OXID-eSales/examples-module/actions/workflows/trigger.yaml/badge.svg?branch=b-7.5.x)](https://github.com/OXID-eSales/examples-module/actions/workflows/trigger.yaml)[![Latest Version](https://camo.githubusercontent.com/0ecd298224909dbfd7fc7d501845cce17accaea855668df50304387ce1610d96/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f4f5849442d6553616c65732f6578616d706c65732d6d6f64756c653f6c6f676f3d636f6d706f736572266c6162656c3d6c617465737426696e636c7564655f70726572656c656173657326636f6c6f723d6f72616e6765)](https://packagist.org/packages/oxid-esales/examples-module)[![PHP Version](https://camo.githubusercontent.com/d9c31edf935ab6d384d8cf916b1dcec1b012389a0c36338b6e6319c72e9918d9/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f7068702d762f6f7869642d6573616c65732f6578616d706c65732d6d6f64756c65)](https://github.com/oxid-esales/examples-module)

[![Quality Gate Status](https://camo.githubusercontent.com/7b6ea7c3683e07273f49f3270336cc36ab91f574cdde5f2b8165a1b830d89b4a/68747470733a2f2f736f6e6172636c6f75642e696f2f6170692f70726f6a6563745f6261646765732f6d6561737572653f70726f6a6563743d4f5849442d6553616c65735f6578616d706c65732d6d6f64756c65266d65747269633d616c6572745f737461747573)](https://sonarcloud.io/dashboard?id=OXID-eSales_examples-module)[![Coverage](https://camo.githubusercontent.com/6243b2a42a004f2233b709e5934b547bd2dfbda02bee31704a7db0477d3ed863/68747470733a2f2f736f6e6172636c6f75642e696f2f6170692f70726f6a6563745f6261646765732f6d6561737572653f70726f6a6563743d4f5849442d6553616c65735f6578616d706c65732d6d6f64756c65266d65747269633d636f766572616765)](https://sonarcloud.io/dashboard?id=OXID-eSales_examples-module)[![Technical Debt](https://camo.githubusercontent.com/09ae2a0b74c753e309e5bc319c1f898d689e64918ad62b8efa71cef031a23432/68747470733a2f2f736f6e6172636c6f75642e696f2f6170692f70726f6a6563745f6261646765732f6d6561737572653f70726f6a6563743d4f5849442d6553616c65735f6578616d706c65732d6d6f64756c65266d65747269633d7371616c655f696e646578)](https://sonarcloud.io/dashboard?id=OXID-eSales_examples-module)

The examples module contains examples for the most common use cases (see below) like OXID suggests it could be implemented.

This module also comes with all the quality tools OXID recommends to use.

Table of contents
-----------------

[](#table-of-contents)

1. [Branch compatibility](#branch-compatibility)
2. [The Idea](#the-idea)
3. [Goals](#goals)
4. [Examples](#examples)
5. [Install and try it out](#install-and-try-it-out)
6. [Development installation](#development-installation)
7. [Development installation on OXID eShop SDK](#development-installation-on-oxid-eshop-sdk)
8. [Things to be aware of](#things-to-be-aware-of)
9. [Running tests and quality tools](#running-tests-and-quality-tools)
10. [Additional info](#additional-info)

Branch compatibility
--------------------

[](#branch-compatibility)

- b-7.5.x branch - compatible with OXID eShop compilation 7.5.x and the respective branch
- b-7.4.x branch and v2.x releases - compatible with OXID eShop compilation 7.4.x and the respective branch
- b-7.3.x branch and v1.x releases - compatible with OXID eShop compilation 7.3.x and the respective branch

The Idea
--------

[](#the-idea)

OXID eSales would like to provide a lightweight reusable example module incorporating our best practices recommendations to be used for developing own module solutions.

Story:

- Module will extend a block on shop start page to show a greeting message (visible when module is active).
- Module will have a setting to switch between generic greeting message for a logged in user and a personal custom greeting. The Admin's choice which way it will be.
- A logged in user will be able to set a custom greeting depending on module setting. Press the button on start page and be redirected to a module controller which handles the input.
- User custom greetings are saved via shop model save method. We subscribe to BeforeModelUpdate to track how often a user changed his personal greeting.
- Tracking of this information will be done in a new database table to serve as an example for module's own shop model.
- Module will extend the shop's basket model to add info to module specific log file when an item is added into basket. Logging can be enabled or disabled depending on module setting.
- Module will have console command `oeexamples:logger:read` to read log file.

```
./vendor/bin/oe-console oeexamples:logger:read
```

Goals
-----

[](#goals)

Install and try out the module with simple examples to most common development questions.

We would like to encourage following ideas and principles in module development:

- Separate contexts into their own folders (e.g. Greeting, Tracker, ProductVote)
    - Basics of DDD in module development
    - Controllers are our use cases and entry points
    - Services contain business logic
    - Infrastructure contains shop framework/database related code
- Layered architecture within those contexts (e.g. Infrastructure, Service, Controller, Subscriber)
    - Changing the implementation should not affect other layers
    - Interfaces are the contracts between layers
    - Data Transfer Objects (DTOs) used for data exchange between layers
    - Factories are responsible for creating DTOs (e.g. from database rows)
        - Centralizes mapping logic and makes it reusable and testable
- Hexagonal architecture ideas
    - Ports (interfaces here) and adapters (implementations here)
    - Adapters depend on ports, not the other way round
    - Application core is independent of external systems (as much as possible in the current context)
- Dependency injection
    - Allows awesome testability and flexibility
    - Avoids usage of global state (Registry, oxNew, static calls)
        - Use factories to create model objects instead of oxNew directly
- SOLID principles
    - SRP and DIP in focus
- Clean architecture ideas
    - Dependencies point inwards
    - Business logic is independent of frameworks, databases, UIs
- Avoid the extension of shop core classes as much as possible
    - Prefer event listeners, DI service decoration/replacement
    - If extension is necessary, follow minimal invasion principle
- Tests are a good example of Unit usage

Examples
--------

[](#examples)

The repository contains examples of following cases and more:

- [Extending of shop controllers and models](https://github.com/OXID-eSales/examples-module/blob/b-7.5.x/metadata.php#L25)

    - extending a shop model (`OxidEsales\ExamplesModule\Extension\Model\User`) / (`OxidEsales\ExamplesModule\Extension\Model\Basket`)
    - extending a shop controller (`OxidEsales\ExamplesModule\Extension\Controller\StartController`)
- [Controllers as service](https://github.com/OXID-eSales/examples-module/blob/b-7.5.x/src/Greeting/services.yaml#L34)

    - own module controller (`oeem_greeting` with own template and own translations)
    - own module admin controller (`oeem_admin_greeting` with own template and own translations)
- [Using Symfony DI](services.yaml)

    - [Injection of Registry classes with bind](https://github.com/OXID-eSales/examples-module/blob/b-7.5.x/services.yaml#L16)
    - [Service decoration](src/Greeting/Service/Decorator/GreetingValidationDecorator.php) - shows how to decorate services
        - Note: While the example uses validation/truncation for simplicity, better use cases include logging, caching, performance monitoring, or audit trails
        - [Decorator registration](src/Greeting/services.yaml) - using `decorates:` in DI configuration
- [Migrations](migration)

    - extending a shop database table (`oxuser`)
- Accessing the database

    - Model with a database (`OxidEsales\ExamplesModule\Tracker\Model\TrackerModel`)
    - `oxNew` object factory example (`OxidEsales\ExamplesModule\Greeting\Infrastructure\Factory\UserModelFactory`)
    - [DAO examples](src/ProductVote/Dao) - lower level abstraction for database access
    - Repository examples - higher level abstraction for data access
        - [GreetingRepository](src/Greeting/Infrastructure/Repository/GreetingRepository.php) - direct database query with QueryBuilder example (consider making DAO instead for cases like this)
        - [UserRepository](src/Greeting/Infrastructure/Repository/UserRepository.php) - loading shop user with model example
        - [TrackerRepository](src/Tracker/Infrastructure/Repository/TrackerRepository.php) - more comprehensive example showing dependencies and DTO usage
- [Various types of module settings](https://github.com/OXID-eSales/examples-module/blob/b-7.5.x/metadata.php#L38)
- Templates

    - [creating templates for your module](views/twig/templates/greetingtemplate.html.twig)
    - [extending of oxid theme templates or blocks](views/twig/extensions/themes)
        - extending a shop admin template block (`admin_user_main_form` - only an extension of a block, without functionality)
        - extending a shop template block (`start_newest_articles`)
- Using the translations for your module specific phrases

    - [in admin](views/admin_twig)
    - [in frontend](translations)
- Events and listeners

    - [Subscribing to shop events](src/Tracker/Subscriber/BeforeModelUpdate.php) - listening to `BeforeModelUpdateEvent`
    - [Creating and dispatching custom module events](src/ProductVote/Event/ProductVotedEvent.php)
        - [Dispatching the event](src/ProductVote/Service/VoteService.php) - triggering events from services
- Testing your module backend and frontend part

    - [Composer aliases for easy running of tests and quality tools](https://github.com/OXID-eSales/examples-module/blob/b-7.5.x/composer.json#L49)
    - [Using the github actions as CI tool with all recommended tools preconfigured for you.](.github)
- [Using variables from .env file](.env)

    - [Access via `getenv()` function](src/Extension/Controller/StartController.php)
        - Note: Changes to environment variables take effect immediately — no cache clearing is required.
    - [Access via DI container](src/Greeting/services.yaml)
        - Note: After updating environment variables, you must clear the cache for changes to take effect.

**HINTS**:

- Only extend the shop core if there is no other way like listen and handle shop events, decorate/replace some DI service.
- Your module might be one of many in the class chain and you should act accordingly (always ensure to call the parent method and return the result).
- When extending shop classes with additional methods, best prefix those methods in order to not end up with another module picking the same method name and wreacking havoc.
- In case there is no other way than to extend existing shop methods try the minimal invasion principle. Put module business logic to a service (which make it easier to test as well) and call the service in the extended shop class. If you need to extend the shop class chain by overwriting, try to stick to the public methods.

#### Not yet in here but might come later:

[](#not-yet-in-here-but-might-come-later)

- example for payment gateway extension
- seo url for module controller
- to redirect or not to redirect from inside the shop core
- graphql query/mutation example
- extending the internal part

Install and try it out
----------------------

[](#install-and-try-it-out)

Note: This installation method fits for trying out the module development basics, its not meant to be used as development base for your own module. Check further installation/usage methods.

This module is in working state and can be directly installed via composer:

```
composer require oxid-esales/examples-module
./vendor/bin/oe-eshop-doctrine_migration migrations:migrate oe_examples_module

```

and [activate the module](https://docs.oxid-esales.com/developer/en/latest/development/modules_components_themes/module/installation_setup/setup.html#setup-activation).

Customizable parameters
-----------------------

[](#customizable-parameters)

There is a parameter in the `services.yaml` that can be customized for the module:

- `app.log_file_path` - Path to the log file where example log message will be stored.

To modify the parameters, create the `configurable_services.yaml` file in the `var/configuration` folder as described in the [Documentation](https://docs.oxid-esales.com/developer/en/latest/development/tell_me_about/service_container.html#replacing-oxid-eshop-services-in-a-project), and overwrite the parameters you want to change. Ex.:

```
parameters:
  app.log_file_path: '/my/custom/filepath/to.log'
```

Development installation
------------------------

[](#development-installation)

To be able running the tests and other preconfigured quality tools, please install the module as a [root package](https://getcomposer.org/doc/04-schema.md#root-package).

The next section shows how to install the module as a root package by using the OXID eShop SDK.

In case of different environment usage, please adjust by your own needs.

Development installation on OXID eShop SDK
------------------------------------------

[](#development-installation-on-oxid-eshop-sdk)

The installation instructions below are shown for the current [SDK](https://github.com/OXID-eSales/docker-eshop-sdk)for shop 7.5. Make sure your system meets the requirements of the SDK.

1. Ensure all docker containers are down to avoid port conflicts
2. Clone the SDK for the new project

```
echo MyProject && git clone https://github.com/OXID-eSales/docker-eshop-sdk.git $_ && cd $_
```

2. Clone the repository to the source directory

```
git clone --recurse-submodules https://github.com/OXID-eSales/examples-module.git --branch=b-7.5.x ./source
```

3. Run the recipe to setup the development environment, you can decide which shop edition to install. Omitting the flag installs EE.

```
./source/recipes/setup-development.sh -e CE
```

You should be able to access the shop with  and the admin panel with (credentials:  / admin)

Things to be aware of
---------------------

[](#things-to-be-aware-of)

The examples module is intended to act as a tutorial module so keep your eyes open for comments in the code.

**NOTES:**

- Acceptance tests are way easier to write if you put an id on relevant fields and buttons in the templates.
- If you can, try to develop on OXID eShop Enterprise Edition to get shop aware stuff right from the start.

### Module migrations

[](#module-migrations)

- migrations are intended to bump the database (and eventual existing data) to a new module version (this also goes for first time installation).
- ensure migrations are stable against rerun

Migrations have to be run via console command (`./vendor/bin/oe-eshop-doctrine_migration`)

```
./vendor/bin/oe-eshop-doctrine_migration migrations:migrate oe_examples_module
```

NOTE: Existing migrations must not be changed. If the database needs a change, add a new migration file and change to your needs:

```
./vendor/bin/oe-eshop-doctrine_migration migrations:generate oe_examples_module
```

For more information, check the [developer documentation](https://docs.oxid-esales.com/developer/en/latest/development/tell_me_about/migrations.html).

### Where the module namespace points to

[](#where-the-module-namespace-points-to)

As already mentioned above, in the 7.x versions of OXID eShop, the module code only resides in the vendor directory so the namespace needs to point there. In our case this looks like

```
    "autoload": {
        "psr-4": {
            "OxidEsales\\ExamplesModule\\": "src/"
        }
    },
    "autoload-dev": {
        "psr-4": {
            "OxidEsales\\ExamplesModule\\Tests\\": "tests/",
            "OxidEsales\\EshopCommunity\\Tests\\": "./vendor/oxid-esales/oxideshop-ce/tests"
        }
    },
```

Running tests and quality tools
-------------------------------

[](#running-tests-and-quality-tools)

Check the `scripts` section in the composer.json of the module to get more insight of preconfigured quality tools available. Example:

```
$ composer phpcs
$ composer phpstan
$ composer phpmd
```

### Integration/Acceptance tests

[](#integrationacceptance-tests)

- install this module into a running OXID eShop
- run `composer update` in module root directory

```
$ composer update
```

After this done, check the "scripts" section of module `composer.json` file to see how we run tests.

```
$ composer tests-unit
$ composer tests-integration
$ composer tests-codeception
```

NOTE: From OXID eShop 7.0.x on database reset needs to be done with this command (please fill in your credentials)

```
$ bin/oe-console oe:database:reset --db-host=mysql --db-port=3306 --db-name=example --db-user=root --db-password=root --force
```

And just in case you need it, admin user can now also be created via commandline

```
$ bin/oe-console oe:admin:create-user --admin-email  --admin-passowrd
```

for example

```
$ bin/oe-console oe:admin:create-user --admin-email admin@oxid-esales.com --admin-password admin
```

### Writing Codeception tests

[](#writing-codeception-tests)

As a rule of thumb, use codeception tests to ensure the frontend is behaving as expected. Codeception tests take a while to run, so try to navigate the way between covering the relevant cases and overtesting.

We definitely need some acceptance tests if the module affects the frontend like in our example. If the module breaks the frontend, we need to see it asap.

In our case, we cover the reaction of the startpage to the different possibilities

- generic greeting mode (with/without logged in user)
- personal greeting mode (with/without logged in user)
- updating the greeting mode
- ensure module can be activated/deactivated without destroying the shop
- ensure edge case safety like not logged in user directly calling module controller

The great thing about codeception tests is - they can create screenshot and html output in failure case, so you literally get a picture of the fail (`tests/Coreception/_output/`).

### Github Actions Workflow

[](#github-actions-workflow)

The examples-module comes complete with a github actions workflow. No need to rig up some separate continuous integration infrastructure to run tests, it's all there in [github](https://github.com/OXID-eSales/examples-module/actions). You will see three files in `.github/workflow` directory. The workflow from `.github/workflow/trigger.yaml` starts on every `push` and `pull_request` to run the code quality checks and all the module tests.

In our experience it is useful to run the shop tests with the module installed and activated from time to time. For sure those shop tests have been written with only the shop itself in mind. Your module, depending on what it is doing, might completely change the shop behaviour. Which means those shop tests with a module might just explode in your face. Which is totally fine, as long as you can always explain WHY those tests are failing.

Real life example: There is one shop acceptance test case `OxidEsales\EshopCommunity\Tests\Acceptance\Frontend\ShopSetUpTest:`which is testing the frontend shop setup. Very good chance this test will fail if a module is around which extends the class chain. That test is for setting up a shop from scratch so it will simply not expect a module to be around. And we only need our module to safely work with a working shop. We definitely will decide to skip that `ShopSetUpTest`as we have a good explanation as to why it will not work. And having this special test case work with our module will give no benefit.

This is only one example, there might be other tests that fail with your module but fail because your module is changing the shop. In that case the suggestion would be to exclude the original test from the github actions run, copy that test case to your module tests and update to work with your module. This was for example the strategy used for our reverse proxy modules which are mandatory to not make the shop's acceptance tests fail. Unless those test cases that somehow bypass reverse proxy cache invalidation. To be on the safe side, we took over those few test cases to the module and plan to improve the shop tests as soon as possible. We'll gladly also take your PR with improved shop tests ;)

And then there are some few shop tests marked as `@group quarantine` in the doc block. Test in that group have stability issues so they'd better be excluded as well.

Ps: a failing shop test might also turn up issues in your module, in that case fix the module and let the test live ;)

Additional info
---------------

[](#additional-info)

### Useful links

[](#useful-links)

- Vendor home page -
- Bug tracker -
- Developer Documentation -
- Quality Tools and Requirements - [https://docs.oxid-esales.com/developer/en/latest/development/modules\_components\_themes/quality.html](https://docs.oxid-esales.com/developer/en/latest/development/modules_components_themes/quality.html)
- Docker SDK -

### Contact us

[](#contact-us)

- In case of issues / bugs, use "Issues" section on github, to report the problem.
- [Join our community forum](https://forum.oxid-esales.com/)
- [Use the contact form](https://www.oxid-esales.com/en/contact/contact-us.html)

In case you have any complaints, suggestions, business cases you'd like an example for please contact us. Pull request are also welcome. Every feedback we get will help us improve.

###  Health Score

40

—

FairBetter than 88% of packages

Maintenance59

Moderate activity, may be stable

Popularity20

Limited adoption so far

Community17

Small or concentrated contributor base

Maturity56

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 61.3% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~174 days

Total

2

Last Release

171d ago

Major Versions

v1.0.0 → v2.0.02025-11-27

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/1374817?v=4)[oxid](/maintainers/oxid)[@OxID](https://github.com/OxID)

---

Top Contributors

[![Sieg](https://avatars.githubusercontent.com/u/98882?v=4)](https://github.com/Sieg "Sieg (38 commits)")[![MarcelOxid](https://avatars.githubusercontent.com/u/98812941?v=4)](https://github.com/MarcelOxid "MarcelOxid (10 commits)")[![tkcreateit](https://avatars.githubusercontent.com/u/42207462?v=4)](https://github.com/tkcreateit "tkcreateit (5 commits)")[![hkreuter](https://avatars.githubusercontent.com/u/3692295?v=4)](https://github.com/hkreuter "hkreuter (4 commits)")[![RahatHameed](https://avatars.githubusercontent.com/u/11661532?v=4)](https://github.com/RahatHameed "RahatHameed (4 commits)")[![kenariosz](https://avatars.githubusercontent.com/u/2828175?v=4)](https://github.com/kenariosz "kenariosz (1 commits)")

---

Tags

OXIDmoduleseshop

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Code StylePHP\_CodeSniffer

Type Coverage Yes

### Embed Badge

![Health badge](/badges/oxid-esales-examples-module/health.svg)

```
[![Health](https://phpackages.com/badges/oxid-esales-examples-module/health.svg)](https://phpackages.com/packages/oxid-esales-examples-module)
```

###  Alternatives

[ddoe/wysiwyg-editor-module

Summernote WYSIWYG Editor for OXID eShop.

19981.7k2](/packages/ddoe-wysiwyg-editor-module)[oxid-esales/gdpr-optin-module

This is the GDPR opt-in module for the OXID eShop.

20459.1k2](/packages/oxid-esales-gdpr-optin-module)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
