diff --git a/guides/plugins/plugins/administration/module-component-management/add-custom-module.md b/guides/plugins/plugins/administration/module-component-management/add-custom-module.md index f42b23d61a..3f204913cd 100644 --- a/guides/plugins/plugins/administration/module-component-management/add-custom-module.md +++ b/guides/plugins/plugins/administration/module-component-management/add-custom-module.md @@ -40,6 +40,10 @@ import './module/swag-example'; Now your module's `index.js` will be executed. +::: info +For generated Administration modules, `main.js`, module registration, routes/components, snippets, and the Administration build are parts of the same feature. The generated entry point connects the module to the build; `Shopware.Module.register()` describes the module; its routes and components provide the UI; and snippets provide the text. This guide shows the pieces separately so their relationship is clear. +::: + ## Registering the module Your `index.js` is still empty now, so let's get going to actually create a new module. @@ -179,6 +183,10 @@ As mentioned above, Shopware 6 is looking for a `main.js` file in your plugin. Its contents get minified into a new file named after your plugin and will be moved to the `public` directory of Shopware 6 root directory. Given this plugin would be named "AdministrationNewModule", the bundled and minified javascript code for this example would be located under `/src/Resources/public/administration/js/administration-new-module.js`, once you run the command following command in your shopware root directory: +::: info +The Administration build is the build boundary, not the whole feature lifecycle. A successful build means the generated assets compiled; the module still depends on its entry-point import, registration, routes/components, and snippets being connected correctly at runtime. +::: + diff --git a/guides/plugins/plugins/creating-plugins.md b/guides/plugins/plugins/creating-plugins.md index bd7edc29d8..7e37d2a4b9 100644 --- a/guides/plugins/plugins/creating-plugins.md +++ b/guides/plugins/plugins/creating-plugins.md @@ -102,11 +102,13 @@ components use paths such as: Treat generated examples as starting points. Selecting an option can create several related files and service definitions; deleting only one file later can leave broken -references or an invalid service configuration. If you are unsure whether you need -an option, use `--no-scaffold` and add the feature from its focused guide instead. +references or an invalid service configuration. If you are unsure whether you need an +option, use `--no-scaffold` and add the feature from its focused guide instead. + +If generated output does not behave as expected, use the existing feature guide to understand the generated pieces in context. The generator connects source files with registration, discovery, and build/runtime wiring; a generated file being present does not by itself mean that Shopware can use it. ::: info -Generated files are tied to the Shopware version you run the command on. When your plugin supports several Shopware versions, treat the output as a starting point and verify it against the version you target. +Generated files are tied to the Shopware version you run the command on. When your plugin supports several Shopware versions, treat the output as an example for that version and compare it with the focused guide when adapting it. ::: Make sure to adjust the namespace in the generated files as per your needs. diff --git a/guides/plugins/plugins/framework/store-api/add-store-api-route.md b/guides/plugins/plugins/framework/store-api/add-store-api-route.md index 447b14100f..1e06c3d480 100644 --- a/guides/plugins/plugins/framework/store-api/add-store-api-route.md +++ b/guides/plugins/plugins/framework/store-api/add-store-api-route.md @@ -50,6 +50,10 @@ abstract class AbstractExampleRoute Now we can create a new class `ExampleRoute` which uses our previously created `AbstractExampleRoute`. +::: info +A generated Store API route is normally more than the route class itself. The class defines the endpoint and response, the service definition registers it with the dependency injection container, and `routes.php` imports it for discovery. These pieces form one feature; the generator creates them together so you do not normally need to assemble the wiring by hand. +::: + ```php // /src/Core/Content/Example/SalesChannel/ExampleRoute.php /src/Resources/config/` location. Take a look at the official [Symfony documentation](https://symfony.com/doc/current/routing.html) about routes and how they are registered. +The route import is the discovery boundary: a route class can be present and correctly registered as a service without becoming a Store API endpoint until Shopware imports its route attributes. + ```php // /src/Resources/config/routes.php /src/Resources/Schema/StoreApi/` so the shopware internal OpenApi3Generator can find it (for Admin API endpoints, use `AdminApi`). diff --git a/guides/plugins/plugins/plugin-base-guide.md b/guides/plugins/plugins/plugin-base-guide.md index b9729d3d02..7be6cb2e7b 100644 --- a/guides/plugins/plugins/plugin-base-guide.md +++ b/guides/plugins/plugins/plugin-base-guide.md @@ -31,6 +31,8 @@ Most steps above can be generated instead of written by hand: * `bin/console plugin:create` scaffolds the plugin; see the [Creating Plugins guide](creating-plugins.md) * The [Shopware 6 Toolbox plugin](../../development/tooling/shopware-toolbox.md) generates plugins, subscribers, scheduled tasks, migrations, and Administration modules from PHPStorm, using file templates you can adapt to your own conventions +When a generator creates an optional feature, the files it produces are usually parts of one piece of framework wiring. For example, a generated controller can depend on both route configuration and service registration, while a scheduled task has separate task and handler roles. The focused guides explain those pieces in context; you do not normally need to reproduce the wiring manually. + ## Upgrade readiness Design plugins so that: diff --git a/guides/plugins/plugins/plugin-fundamentals/add-scheduled-task.md b/guides/plugins/plugins/plugin-fundamentals/add-scheduled-task.md index 9a5e612d5a..971d2b6222 100644 --- a/guides/plugins/plugins/plugin-fundamentals/add-scheduled-task.md +++ b/guides/plugins/plugins/plugin-fundamentals/add-scheduled-task.md @@ -23,6 +23,10 @@ A `ScheduledTask` and its respective `ScheduledTaskHandler` are registered in a Here's an example `services.php` containing a new `ScheduledTask` as well as a new `ScheduledTaskHandler`: +::: info +A scheduled task has two related runtime roles. The task definition describes when work is due, while the handler processes the message that Shopware dispatches. Generators create both sides and their service wiring together; seeing one generated class on disk does not mean the whole feature has been connected. +::: + ```php // /src/Resources/config/services.php /src/Resources/config/` location. Take a look at the official [Symfony documentation](https://symfony.com/doc/current/routing.html) about routes and how they are registered. +The route import is the discovery half of the feature: it tells Shopware which controller files to inspect for route attributes. A controller can therefore exist and be a valid service while still not expose a URL until its route is imported. + ::: code-group ```php [PLUGIN_ROOT/src/Resources/config/routes.php] diff --git a/guides/plugins/plugins/storefront/javascript/add-custom-javascript.md b/guides/plugins/plugins/storefront/javascript/add-custom-javascript.md index 77e7942e21..2a0b3d9945 100644 --- a/guides/plugins/plugins/storefront/javascript/add-custom-javascript.md +++ b/guides/plugins/plugins/storefront/javascript/add-custom-javascript.md @@ -68,6 +68,8 @@ Next you have to tell Shopware that your plugin should be loaded and executed. T Shopware is automatically looking for a `main.js` file in a directory `/src/Resources/app/storefront/src`, which then will be loaded automatically. Consider this to be your main storefront JavaScript entrypoint. +The entry point, plugin class, and optional DOM selector form one runtime chain. A generator creates these pieces together: `main.js` imports and registers the class, the selector connects it to rendered markup when one is used, and the Storefront build produces the asset the browser loads. Keeping that relationship in mind makes generated output easier to adapt without treating each file as an independent feature. + Create a `main.js` file inside your `/src/Resources/app/storefront/src` folder and get the PluginManager from the global window object. Then register your own plugin: ```javascript @@ -75,7 +77,7 @@ Create a `main.js` file inside your `/src/Resources/app/storefront/ // Import all necessary Storefront plugins import ExamplePlugin from './example-plugin/example-plugin.plugin'; -// Register your plugin via the existing PluginManager +// Register your custom Storefront plugin const PluginManager = window.PluginManager; PluginManager.register('ExamplePlugin', ExamplePlugin); ``` @@ -91,7 +93,7 @@ You can also bind your plugin to a DOM element by providing a css selector: // Import all necessary Storefront plugins import ExamplePlugin from './example-plugin/example-plugin.plugin'; -// Register your plugin via the existing PluginManager +// Register your custom Storefront plugin const PluginManager = window.PluginManager; PluginManager.register('ExamplePlugin', ExamplePlugin, '[data-example-plugin]'); ``` @@ -106,7 +108,7 @@ The import path can remain the same as the synchronous import. ```javascript // /src/Resources/app/storefront/src/main.js -// Register your plugin via the existing PluginManager using a dynamic import +// Register your own Storefront plugin using a dynamic import const PluginManager = window.PluginManager; PluginManager.register('ExamplePlugin', () => import('./example-plugin/example-plugin.plugin'), '[data-example-plugin]'); ```