From 63447996a47f94b82897efc2ba3e58127668b529 Mon Sep 17 00:00:00 2001 From: Vincent HADJEDJ Date: Mon, 8 Jun 2026 11:40:10 +0200 Subject: [PATCH 1/3] Document module services.php configuration --- modules/concepts/services/_index.md | 107 +++++++++++++++++++++------- 1 file changed, 80 insertions(+), 27 deletions(-) diff --git a/modules/concepts/services/_index.md b/modules/concepts/services/_index.md index 9cd704a67d..30b3d37726 100644 --- a/modules/concepts/services/_index.md +++ b/modules/concepts/services/_index.md @@ -57,7 +57,7 @@ class YourService { } ``` -Now that your namespace is setup, you can define your services in the `config/services.yml` file of your module. +Now that your namespace is setup, you can define your services in a service configuration file of your module, for example `config/services.yml`. ```yml # yourmodule/config/services.yml @@ -72,24 +72,75 @@ services: - "My custom message" ``` -{{% notice tip %}} It is possible to load PHP / XML files for modules services{{% /notice %}} +#### Service configuration files +{{< minver v="9.2.0" title="true" >}} -```yml -# yourmodule/config/services.yml -imports: - - { resource: services.php } +Starting from PrestaShop 9.2, modules can use several service configuration files. PrestaShop loads the first existing +file in this order: + +1. `services.php` +2. `services-{major}.{minor}.yml`, for example `services-9.2.yml` +3. `services-{major}.yml`, for example `services-9.yml` +4. `services.yml` + +The same priority applies to the supported module service configuration folders, such as `config/`, `config/admin/`, +`config/front/` and `config/webservice/`. + +This means you can use PHP service configuration in PrestaShop 9.2 and newer: + +```php +services(); + + $services + ->defaults() + ->public(); + + $services + ->set('your_company.your_module.your_service', \YourCompany\YourModule\YourService::class) + ->args([ + service('translator'), + 'My custom message', + ]); +}; ``` +You can use `services.php` as an entry point to load different service definitions depending on the PrestaShop version: + ```php =')) { + $container->import('services/services-ps-9.2.php'); + + return; + } + $container->import('services/services-ps-9.php'); }; ``` +You can also keep YAML files as fallbacks for compatibility with older PrestaShop versions: + +```text +yourmodule/ +`-- config/ + |-- services.php + |-- services-9.2.yml + |-- services-9.yml + `-- services.yml +``` + +When `services.php` exists, it has priority. Otherwise PrestaShop falls back to the most specific YAML file matching +the current PrestaShop version, then to `services.yml`. + This will then allow you to get your service from the Symfony container, like in your modern controllers: ```php @@ -114,7 +165,7 @@ class DemoController extends FrameworkBundleAdminController {{% notice tip %}} If you need more details about dependency injection and how services work in the Symfony environment we recommend you to read -their documentation about the [Service Container](https://symfony.com/doc/4.4/service_container.html). +their documentation about the [Service Container](https://symfony.com/doc/6.4/service_container.html). {{% /notice %}} ##### Exclude index.php files when adding wildcard resource @@ -135,13 +186,13 @@ The container definition can be modified by a module, which enables you to overr This is a mechanism similar to PrestaShop standard overrides, but the main benefit is that the php code stays unmodified. This prevents issues linked to code definition or autoloading failures. -As you can read it from the [Symfony documentation](https://symfony.com/doc/current/service_container/service_decoration.html), there are 2 ways to modify an existing service: +As you can read it from the [Symfony documentation](https://symfony.com/doc/6.4/service_container/service_decoration.html), there are 2 ways to modify an existing service: #### Override the service When you choose to override a service, this means that you _replace the service by another one_. The previous service is not usable anymore. Every other part of the code where this service is used will use the new version. -To do it: you declare your new service using the old service name. So if you want to override the service `prestashop.core.b2b.b2b_feature` with your own implementation, you write in `config/services.yml` : +To do it: you declare your new service using the old service name. So if you want to override the service `prestashop.core.b2b.b2b_feature` with your own implementation, you can write for example in `config/services.yml`: ```yml prestashop.core.b2b.b2b_feature: @@ -154,7 +205,7 @@ That's done. The service registered under the name `prestashop.core.b2b.b2b_feat When you choose to decorate a service, this means that you _make everybody use your service but you keep the old service available_. The previous service has been given a new name and can still be used. Every other part of the code where this service was used will use the new version. -To do it: you declare your new service using the 'decorates' keyword. So if you want to decorates the service `prestashop.core.b2b.b2b_feature` with my own implementation, you write in `config/services.yml` : +To do it: you declare your new service using the 'decorates' keyword. So if you want to decorates the service `prestashop.core.b2b.b2b_feature` with my own implementation, you can write for example in `config/services.yml`: ```yml mymodule.my_own_b2b_feature_service: @@ -167,7 +218,7 @@ That's done. The service registered under the name `mymodule.my_own_b2b_feature_ This means that in your container you can access 3 services now: - `mymodule.my_own_b2b_feature_service` your service -- `prestashop.core.b2b.b2b_feature` is now an alias for `mymodule.my_own_b2b_feature_service` (see [service aliases](https://symfony.com/doc/current/service_container/alias_private.html)) so the other services which rely on it now use your implementation +- `prestashop.core.b2b.b2b_feature` is now an alias for `mymodule.my_own_b2b_feature_service` (see [service aliases](https://symfony.com/doc/6.4/service_container/alias_private.html)) so the other services which rely on it now use your implementation - `mymodule.my_own_b2b_feature_service.inner` is the previous implementation, still available The decoration strategy can be very useful if: @@ -257,7 +308,7 @@ As you can see, interfaces lay the ground for easy extension and customization, #### Advanced services parameters (_instanceof or interface binding, manual tags) -Since {{< minver v=8.1 >}}, [modules autoloaders and service configurations loading are now registered before compiler passes](https://github.com/PrestaShop/PrestaShop/pull/30588). That means that you can now use native Symfony service configuration features in your modules. +Since {{< minver v=8.1 >}}, [modules autoloaders and service configurations loading are now registered before compiler passes](https://github.com/PrestaShop/PrestaShop/pull/30588). That means that you can now use native Symfony service configuration features in your modules. Those features are: @@ -266,7 +317,7 @@ Those features are: - [an option to skip the class attribute](https://symfony.com/blog/new-in-symfony-3-3-optional-class-for-named-services) - [automatically registering classes found in the specified directories as services](https://symfony.com/blog/new-in-symfony-3-3-psr-4-based-service-discovery) -As an example, let's consider a module with the following structure: +As an example, let's consider a module with the following structure: ``` config/ @@ -278,9 +329,9 @@ src/ ElementInterface.php ``` -And this content: +And this content: -File: `src/Collection/Collection.php` +File: `src/Collection/Collection.php` ```php }} @@ -393,8 +444,10 @@ container for this environment (`PrestaShop\PrestaShop\Adapter\ContainerBuilder` To define your services you need to follow the same principle as Symfony services, but this time you need to place your definition files in sub folders: -- `config/admin/services.yml` will define the services accessible in the back office (in legacy environment AND Symfony environment) -- `config/front/services.yml` will define the services accessible in the front office +- `config/admin/` service configuration files will define the services accessible in the back office (in legacy environment AND Symfony environment) +- `config/front/` service configuration files will define the services accessible in the front office + +The service file priority described above also applies in these folders. {{% notice warning %}} **Do not use named arguments for front services definition** @@ -467,12 +520,12 @@ in admin or front. Be careful and always keep in mind in which context/environme Here is a quick summary so that you know where you should define your services: -| Definition file | Symfony Container | Front Legacy Container | Admin Legacy Container | Webservice Container | Available services | -| --------------------------- | :---------------: | :--------------------: | :--------------------: | :------------------: | -------------------------------------------------------------------------- | -| `config/services.yml` | Yes | No | No | No | All Symfony components and `PrestaShopBundle` services | -| `config/admin/services.yml` | Yes | No | Yes | No | Doctrine, services defined in `/config/services/admin` folder | -| `config/front/services.yml` | Yes | Yes | No | No | Doctrine, services defined in `/config/services/front` folder | -| `config/webservice/services.yml` | Yes | No | No | Yes | Doctrine, services defined in `/config/webservice/front` folder | +| Definition folder | Symfony Container | Front Legacy Container | Admin Legacy Container | Webservice Container | Available services | +| ----------------------- | :---------------: | :--------------------: | :--------------------: | :------------------: | -------------------------------------------------------------------------- | +| `config/` | Yes | No | No | No | All Symfony components and `PrestaShopBundle` services | +| `config/admin/` | Yes | No | Yes | No | Doctrine, services defined in `/config/services/admin` folder | +| `config/front/` | Yes | Yes | No | No | Doctrine, services defined in `/config/services/front` folder | +| `config/webservice/` | Yes | No | No | Yes | Doctrine, services defined in `/config/webservice/front` folder | ### Define a service on both front and admin From c421735754a9acf2a8463d1bc6dc2701cd9a411c Mon Sep 17 00:00:00 2001 From: Vincent HADJEDJ Date: Mon, 8 Jun 2026 11:53:25 +0200 Subject: [PATCH 2/3] Reference services documentation from YAML examples --- modules/concepts/commands.md | 2 ++ modules/concepts/controllers/admin-controllers/_index.md | 2 ++ modules/concepts/hooks/use-hooks-on-modern-pages.md | 5 +++-- modules/creation/adding-configuration-page-modern.md | 2 +- 4 files changed, 8 insertions(+), 3 deletions(-) diff --git a/modules/concepts/commands.md b/modules/concepts/commands.md index d92d34c32b..118729d957 100644 --- a/modules/concepts/commands.md +++ b/modules/concepts/commands.md @@ -66,6 +66,8 @@ class ExportCommand extends Command Now, in order to make this really simple command available in the console, we register it in the services.yml file: +This example uses YAML, but other service configuration files are supported. See [Services]({{< relref "/9/modules/concepts/services/" >}}) for more details. + ```yaml # your-module/config/services.yml services: diff --git a/modules/concepts/controllers/admin-controllers/_index.md b/modules/concepts/controllers/admin-controllers/_index.md index e688b3dae2..524fcb28e7 100644 --- a/modules/concepts/controllers/admin-controllers/_index.md +++ b/modules/concepts/controllers/admin-controllers/_index.md @@ -136,6 +136,8 @@ public function __construct( In PrestaShop 9.0, controllers must be defined as services. You have two main approaches to configure your controller service: +The following examples use YAML, but other service configuration files are supported. See [Services]({{< relref "/9/modules/concepts/services/" >}}) for more details. + ### Option 1: Explicit service configuration with tags ```yaml diff --git a/modules/concepts/hooks/use-hooks-on-modern-pages.md b/modules/concepts/hooks/use-hooks-on-modern-pages.md index 07b7a471c0..c1c9b57263 100644 --- a/modules/concepts/hooks/use-hooks-on-modern-pages.md +++ b/modules/concepts/hooks/use-hooks-on-modern-pages.md @@ -152,7 +152,9 @@ services: Note: Since Symfony 4.4, services that are not dependency injected and that are not declared as “public” are removed from the container. {{% /notice %}} -Prestashop automatically checks if modules have a `config/services.yml` file and will autoload it for you. In order to force Prestashop to parse the file, you need to clear the cache: +PrestaShop automatically checks module service configuration files and will autoload them for you. This example uses YAML, but other service configuration files are supported. See [Services]({{< relref "/9/modules/concepts/services/" >}}) for more details. + +In order to force PrestaShop to parse the file, you need to clear the cache: ``` ./bin/console cache:clear --no-warmup @@ -289,4 +291,3 @@ We have used a key for translation, making our own translations available in bac And "voila!", the module could be of course improved with so many features, adding filters on export for instance, using the `request` hook parameter and updating the Product repository. [setup-composer]: {{< ref "/9/modules/concepts/composer.md" >}} - diff --git a/modules/creation/adding-configuration-page-modern.md b/modules/creation/adding-configuration-page-modern.md index 99b742a369..971749cd54 100644 --- a/modules/creation/adding-configuration-page-modern.md +++ b/modules/creation/adding-configuration-page-modern.md @@ -114,7 +114,7 @@ This form has only one setting : `config_text`, of type `Symfony\Component\Form\ ### Register your newly created form type -Create a `services.yml` file in `config/`. +Create a `services.yml` file in `config/`. This example uses YAML, but other service configuration files are supported. See [Services]({{< relref "/9/modules/concepts/services/" >}}) for more details. ```yml services: From a8c9fe3c58026c42d2666f813c74b1802dab9fdc Mon Sep 17 00:00:00 2001 From: Vincent HADJEDJ Date: Mon, 8 Jun 2026 15:00:38 +0200 Subject: [PATCH 3/3] Update module file structure service examples --- modules/creation/module-file-structure.md | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/modules/creation/module-file-structure.md b/modules/creation/module-file-structure.md index 086749a2e2..8a3abc7173 100644 --- a/modules/creation/module-file-structure.md +++ b/modules/creation/module-file-structure.md @@ -6,7 +6,7 @@ weight: 2 # Module file structure A module is made of a lot of files, all stored in a folder that bears the same name as the module, that folder being in turn stored in the -`/modules` folder at the root of the main PrestaShop folder: `/modules//`. +`/modules` folder at the root of the main PrestaShop folder: `/modules//`. {{% notice tip %}} Your module can be called anything, as long as it only contains lowercase letters and numbers (`/[a-z0-9]/`). @@ -17,15 +17,24 @@ A module distributed in a zip archive file must also be placed in a subfolder wi ## Main files and directories -Here are an example of files and folders for a PrestaShop 1.7 module: +Here is an example of files and folders for a PrestaShop 9.2 module: ``` mymodule ├── config │ ├── admin -│ │ └── services.yml +│ │ ├── services.php +│ │ ├── services-9.2.yml +│ │ ├── services-9.yml +│ │ └── services.yml │ ├── front +│ │ ├── services.php +│ │ ├── services-9.2.yml +│ │ ├── services-9.yml │ │ └── services.yml +│ ├── services.php +│ ├── services-9.2.yml +│ ├── services-9.yml │ └── services.yml ├── controllers ├── override @@ -52,6 +61,10 @@ Let's go through each one of the above. The `config` folder is the place where configuration files are stored. In particular, [Routes][sf-routes] and [Services][sf-services]. +Starting from PrestaShop 9.2, module service configuration files can use several names and formats, as shown in the +example above. Only one service configuration file is loaded per folder. See [Services][sf-services] for more details +about service configuration files and their loading priority. + ### `controllers/` folder The `controllers` folder contains the legacy-style Controller files. @@ -69,7 +82,7 @@ Symfony-based controllers go in the ["`src`" folder](#src-folder), described bel ### `override/` folder -PHP files placed in the `override` folder will replace the ones from the Core. +PHP files placed in the `override` folder will replace the ones from the Core. {{% notice warning %}} Overrides is a powerful, yet risky feature. Avoid using it if you can. @@ -149,7 +162,7 @@ This icon file will be displayed in module listings if present. It needs to be a ### `mymodule.php` file (main file) -The module's main PHP file should be named the same as the module’s root folder. +The module's main PHP file should be named the same as the module’s root folder. Example for the BlockCMS module: