Finally, let me share some more things that I learned or rediscovered when validating and publishing a Symfony plugin to the Shopware marketplace:
- Customize the IDE
- Use templates and quality tools...
- Minimalism vs. overwhelmingly explicit boilerplate code
- Caches can cause outdated error messages!
- Don't forget to reinstall!
- Install Symfony profiler
- Use XDebug and adjust the default log level
- Use adminer to inspect the database
- Debug, research, review and learn!
- Build and verify!
- Don't use the admin UI for updates!
- Validations, inspections and debug commands
- Community blogs
- Don't get fooled by deprecations!
- Don't pay for outdated plugins!
- Question software decisions!
We should make sure that our local development setup meets the requirements: use PhpStorm with all required plugins and language support
- PHP (built-in)
- Symfony (Symfony Support extension)
- Shopware (Shopware Toolbox extension)
Customize the IDE
The default directory tree view in the current PhpStorm version adds the challenge of verifying paths, as the minimalistic flat design makes the directory structure hard to discern. At least there is an appearance setting to bring back the vertical helper lines ("tree indent guides"). But can you tell if the import path in routes.xml
is correct in the following screenshot?
Screenshot: the directory structure can be hard to discern in PhpStorm.
Use templates and quality tools...
... but without repeating other people's mistakes. Not only renowned community sites like StackOverflow are full of outdated or mismatching examples.
Official coding assistance like plugin create
or theme create
can also create code that does not fit our needs or that contains errors.
Cypress, Jest, and PHPUnit
See Shopware developers documentation: Extensions: Testing for best practices to use Cypress, Jest and PHPUnit to test Shopware 6 extensions without writing everything from scratch. The Shopware platform code contains test configurations we can reuse and extend as developers. The test suite is built on top of Cypress and some plugins like cypress-select-tests
, cypress-log-to-output
, and cypress-file-upload
.
Minimalism vs. overwhelmingly explicit boilerplate code
While learning, we might get overwhelmed by an overload of what seems to be verbose boilerplate code without an actual purpose. Many tutorials don't make much sense except for the tutors who conceived them. This is why we must build our own working experiments and add our purpose! Also, there is often a lot of optional explicit code that we would not necessarily need to write in production projects thanks to default values, autowiring and code generating assistants, but which might help us understand what is going on thanks to its verbose explicitness. Verbose definitions and annotations might also improve IDE autocompletion and inspection!
Performance and customizability vs. simplicity
Another reason for verbosity and redundancy: if I understood their tutorials correctly, Shopware prioritised performance/speed optimization over convenience/developer experience in certain cases.
Other redundancies are optional if we don't want to change or extend the implicit defaults.
For example, creating a custom Entity class, as well as a custom EntityCollection class, is highly recommended but optional. Both will be replaced with generic classes otherwise, using instances of ArrayEntity
instead of our own Entity collections.
A minimal custom entity definition
The most minimal example could be extended from an auto-generated theme stub, adding a database migration, an Entity Definition class, and extending an existing twig template to display our custom data in the storefront. That's it! In addition, we can, but we don't have to, define our own entity class and entity collection class, an entity repository route to add interactive frontend code to connect to an API to retrieve specific data dynamically, like the Shopware Academy store finder example.
If you feel there must be a simpler solution, there probably is.
Don't overengineer your requirements! You are probably right if you feel there must be a more straightforward solution. For example, to add custom fields to products in Shopware 6, we can conceive a new entity definition with a migration class for its distinct database table with foreign keys and one-to-one associations, writing hundreds of lines of boilerplate code. Or we can use Shopware's custom field system, which allows us "to extend entities, without writing a complete entity extension. This is possible by storing the additional data in a JSON field", as long as we only need scalar values and no complex data structures.
Caches can cause outdated error messages!
When we finally write the correct code, it might still not work until another bin/console cache:clear
and/or bin/console plugin:refresh
has removed every remnant of our previous attempts. See this similar (non-Shopware) StackOverflow question about "controller ... has no container set ... define it as a service subscriber", quoting the accepted answer:
The issue had to do with the cached files; deleting
/var/cache
prevented the error from occurring.
Don't forget to reinstall!
When changing migration classes or plugin lifecycle methods like install
, we must uninstall and reinstall the plugin to run our new code.
Install Symfony profiler
If there is no Symfony profiler yet, you can install it using composer:
composer require --dev symfony/profiler-pack
Use XDebug and adjust the default log level
We can set the default logging level from debug
to warning
in /var/www/html/config/packages/dev/monolog.yaml
to prevent Shopware from writing hundreds of lines of deprecation notes (INFO level) to dev.log
for each request. For the same reason, we usually don't want to enable Xdebug in Dockware by default, but use make xdebug-on
or make xdebug-off
on the command line inside the container, making sure to add operating-system specific settings like environment: - XDEBUG_REMOTE_HOST=172.17.0.1
for Linux in docker-compose.yml
, to install the XDebug browser extension and start PhpStorm's XDebug listener in the settings or by clicking the bug icon in the status bar at the bottom of the IDE.
If you have never used XDebug before, you might wonder what is supposed to happen when it works. Simply said, it's a connection between the Symfony profiler output in your browser and the source code in your IDE. Clicking on a line number in a stack trace will open the file at the mentioned line in PhpStorm.
XDebug can help us debug errors (except those that silently fail with a white screen).
Inspect the database with adminer
Use adminer (or the SQL CLI) to verify tables and database entries. In a dockware default development setup: http://localhost//adminer.php (Server: 127.0.0.1
, not localhost; database: shopware
; initial login: root:root
).
Debug, research, review and learn!
A bug in the software framework or its tools and extensions is no impossible reason for a problem, but it seems extremely unlikely that we were the first to find and report it. We should check search results, forums, issues, and release notes and remember known problems and necessary workarounds (like typing bin/console debug:router --no-debug
or other similarly peculiar idioms to prevent having to search for helpful output in the midst of irrelevant deprecation notes displayed due to unhelpful default log levels).
Solution strategies: google the error message, try to follow your gut feeling or inspect every piece of code and take notes and screenshots so you can review the situation later and learn about your coding vulnerabilities and how to fix them in the future.
Always use the latest documentation and don't be afraid to ask "silly" questions (Slack, StackOverflow, forum) if you have faced a specific challenge when extending or maintaining Shopware code.
Build and verify!
I had some issues using the storefront watcher, so I tend to rely on these manual steps to build and verify a modified theme after starting and entering the container:
docker-compose up -d
docker exec -it shop bash
bin/console plugin:refresh
-
bin/console theme:compile
(if it's a theme) bin/build-storefront.sh
bin/console cache:clear
After this, we can open or reload localhost in our browser.
Don't use the admin UI for updates!
One more addendum: don't use the admin UI for updates! You risk getting stuck in an unfinished update process that offers no rollback option after leaving your shop in a destroyed error state! This has happened too often with several Shopware 6 updates, and it's confirmed by other developers. Use the command line instead!
The command line (Shopware-CLI or bin/console
) offers more control and more options and has been recommended as a better alternative for everyone who has shell access!
PHP Version and other server requirements
Use the correct PHP version consistently! Shared hosting providers may have different PHP versions set for web servers (virtual hosts) vs. on the command line (ssh).
Check php -v
and call the appropriate PHP binary explicitly if necessary. We can think of composer install
as an abbreviation of php composer install
, so it makes sense to write something like
/usr/local/phpfarm/inst/php-8.3.6/bin/php /usr/local/bin/composer create-project shopware/production .
This is just an example, so ask your provider or coworkers for the appropriate path and prefer the latest stable release of the minimum required PHP version you can see in the composer file, or an error message if it's a peer dependency of one of the requirements.
You may also want to change settings like the maximum memory quota, and you might have to use the full path to the composer binary, making the command line even more verbose and explicit, e.g.
/usr/local/phpfarm/inst/php-8.3.6/bin/php -d memory_limit=512M /usr/local/bin/composer create-project shopware/production .
and
/usr/local/phpfarm/inst/php-8.3.6/bin/php -d memory_limit=512M /usr/local/bin/composer install
to prepare a Shopware 6 installation.
You might want to define an alias e.g.
alias php82='/usr/local/phpfarm/inst/php-8.3.6/bin/php -d memory_limit=512M'
Then you can write
php82 bin/console system:install --basic-setup
php82 bin/console plugin:install --activate IngoSCostTransparency
php82 bin/console cache:clear
php82 bin/build-storefront.sh
Validations, inspections and debug commands:
There are several validations, inspections and debug console commands, and there is the third-party extension shopware-cli
(see below).
-
bin/console snippets:validate
validates all snippets -
bin/console lint:container
validates the service container -
bin/console lint:twig <path-to-twig-file>
validates a specific twig template file -
bin/console debug:twig
shows twig commands and namespaces -
bin/console debug:router
shows all configured routes -
bin/console
lists all available bin/console commands.
Adding a verbosity flag (-v
or -vv
or -vvv
for the most verbose output) can sometimes reveal helpful details that are not part of the default output.
Community blogs
Given the state of documentation and the neglected community forum, we are lucky that individuals like Jan Schmidak (Shopwarian) or Bjรถrn Meyer (BrocksiNet) write posts like Custom fields in Shopware 6 or CustomFields, Properties and Entity Extensions for Shopware 6.
Thanks for sharing your knowledge! ๐๐๐
Don't get fooled by deprecations!
Beyond all that, we can focus on frontend customization and adding missing services in the backend and not get fooled by breaking changes, like introducing a mandatory hyphen in a frontend class name in Shopware 6.6 and other recent deprecations.
Shopware 6 changes since the academy training videos
Ingo Steinke, web developer ใป Dec 12 '23
Don't pay for outdated plugins!
When JetBrains support asked me to deactivate all my plugins to narrow down an IDE bug, I found that some of my plugins didn't work together well or did not provide any value anymore. Related to Shopware 6:
๐ซ "Shopware" is no official Shopware plugin but a paid third-party extension by Daniel Espendiller. It is not officially endorsed by the Shopware company, at least not anymore.
๐ค SonarLint might be useful, but it caused conflicts with JetBrains built-in inspections and the free version kept nagging me with frequent upgrade notifications, so I uninstalled SonarLint as well.
๐ Symfony Support is another commercial extension, but Shyim, one of Shopware's most renowned developer, recommended it recently (in 2024).
๐ Shopware 6 Toolbox is released and maintained by Shyim and it's free and open source software.
Question software decisions!
Last but not least, question software decisions! If, for example, a framework keeps causing frequent problems or increases development and maintenance efforts, then it may not be the right tool. Aspects to consider: documentation, support, security, stability, performance, accessibility. Are there best practices? Are they easy to discover? Does your working code still work after a framework upgrade? Can upgrades break production systems without a rollback option? Do manufacturers or community members answer questions and suggestions quickly and helpfully?
Coding standards and safe modes
Shopware, for example, has embraced modern coding standards and an open-source system (Symfony) as its foundation. However, WordPress, rightfully criticized for different problems, has introduced safe mode and recovery options that are easy to use even for non-tech-savvy website owners.
Changes to the installation and update process
Shopware used to change the installation and update process several times, trying to push new technologies and deprecate proven workflows. That's a pity in my eyes - if I want managed hosting, I can just create a Shopify account, and that's it.
Some takeaways to remember before trying to install Shopware manuelly next time: check the requirements! Minimum PHP versions and memory limits vs. shared hosting defaults, mandatory server configurations, known gotchas. Always prefer the command line to graphical interfaces and never upgrade without making a backup!
Frustrating developer experience: worth in the long run?
Comparing effort to rewards/income can be a more measurable way to evaluate software decisions. Maybe some software has many problems, but few alternatives for a given requirement, and a frustrating developer experience can be rewarded by billing hours and hours to customers with sufficient budgets. The more often you do this, the more efficiently you can scale your business and resell existing solutions.
Conclusion
This post sums up my series about Shopware 6 development. I think I'm done. I would rather spend my learning time on accessibility, UX, and ecological sustainability than trying to make sense of poorly documented implementation details, whether that's Shopware, Gutenberg, Elementor or React, and focus more on front-end web development and performance optimization again.
I will work with Shopware but without fighting against backend problems and framework idiosyncrasies. I will do frontend-focused web and e-commerce development. Shopware is a good option for some, but not the only solution. And I hope they will update their tutorials and documentation and stop changing too many details with every other update!
I will also keep learning in public and share my experiences, but I will use more tech-specific tags an categories. Although this series was called "learning in public", it was all about a very specific Shopware/Symfony learning path that I finished by getting officially certified as a Shopware 6 developer and Shopware extension partner.
Top comments (2)
After reviewing my PhpStorm extensions in August 2024, I added new paragraphs: don't pay for outdated plugins and don't use the admin UI to update!
I also added command line examples to show how to use a specific PHP version and set the memory limit explicitly when running the initial
composer install
.Minimum memory and other official requirements
Some hosters have enough resources but limit the defaults, so you might spot what looks like an arithmetic anomaly, when allocating 3399608 bytes exhausts the allowed memory size of 134217728 bytes, until you increase your memory limit to the recommended 512M. See Shopware Update fails due to exhausted memory size caused by deactivating extensions for more details and note that similar questions used to yield answers like "Why do you need that much memory? Is it a specific function/database query causing the issue? Can you optimise it? Are you sure, you really want to allocate that much memory? Typically, changing the memory limit on shared hosts isn't possible. It would be counter-productive to the idea of shared hosting. What do you need this much space for anyway? 512 MB sounds like an insane amount of RAM." Although common sense has shifted towards "with such a low memory limit, it's most probably enough to increase the memory limit and not a bug," we might still want to keep the default limit.
Instead of trying to raise the defaults, like by adding an
.htaccess
line likephp_value memory_limit 512M
, we could raise the limit only for critical command line options and let the stricter limits apply to end-user access to our storefront.php -d memory_limit=512M ./bin/console system:install --basic-setup
After installing Shopware's production template according to their installation documentation we might find out some other requirements that are not documented explicitly.