Shopware dev productivity and plugin validation
Published: 2024-03-25 07:47:07

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](#customize-the-ide)
- [Use templates and quality tools...](#use-templates-and-quality-tools)
  - [Cypress, Jest, and PHPUnit](#cypress-jest-and-phpunit)
- [Minimalism vs. overwhelmingly explicit boilerplate code](#minimalism-vs-overwhelmingly-explicit-boilerplate-code)
  - [Performance and customizability vs. simplicity](#performance-and-customizability-vs-simplicity)
  - [A minimal custom entity definition](#a-minimal-custom-entity-definition)
  - [If you feel there must be a simpler solution, there probably is.](#if-you-feel-there-must-be-a-simpler-solution-there-probably-is)
- [Caches can cause outdated error messages!](#caches-can-cause-outdated-error-messages)
- [Don't forget to reinstall!](#dont-forget-to-reinstall)
- [Install Symfony profiler](#install-symfony-profiler)
- [Use XDebug and adjust the default log level](#use-xdebug-and-adjust-the-default-log-level)
- [Use adminer to inspect the database](#use-adminer-to-inspect-the-database)
- [Debug, research, review and learn!](#debug-research-review-and-learn)
- [Build and verify!](#build-and-verify)
- [Validations, inspections and debug commands](#validations-inspections-and-debug-commands)
- [Community blogs](#community-blogs)
- [Don't get fooled by deprecations!](#dont-get-fooled-by-deprecations)
- [Question software decisions!](#question-software-decisions)

We should make sure that our local setup meets the requirements: use PhpStorm with all required plugins and language support
 - PHP
 - Symfony
 - Shopware

## 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](https://www.jetbrains.com/help/phpstorm/settings-appearance.html#ui) 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?

![PhpStorm screenshot with tree indent guides](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/e84fvslg9w54l2tp01m7.png)

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](https://developer.shopware.com/docs/guides/plugins/plugins/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](https://symfony.com/doc/current/service_container/autowiring.html) 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](https://developer.shopware.com/docs/guides/plugins/plugins/framework/data-handling/add-custom-complex-data.html) 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](https://developer.shopware.com/docs/guides/plugins/plugins/framework/custom-field/add-custom-field.html), 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"](https://stackoverflow.com/questions/61059875/controller-has-no-container-set-did-you-forget-to-define-it-as-a-service-subscr), 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!

![Uninstall dialog screenshot](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x5u8xtirf52sggkjuh15.png)

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](https://developer.shopware.com/docs/guides/hosting/configurations/observability/logging.html) 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](https://docs.dockware.io/development/debugging#configure-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](https://chromewebstore.google.com/detail/xdebug-helper/eadndfjplgieldjbigjakmdgkmoaaaoc?hl=en&pli=1) and [start PhpStorm's XDebug listener](https://www.jetbrains.com/help/phpstorm/configuring-xdebug.html#integrationWithProduct) 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](https://www.adminer.org/) (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.

## 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](https://forum.shopware.com/), we are lucky that individuals like [Jan Schmidak (Shopwarian)](https://shopwarian.com/) or [Björn Meyer (BrocksiNet)](https://www.brocksi.net/) write posts like [Custom fields in Shopware 6](https://shopwarian.com/custom-fields-in-shopware-6/) or [CustomFields, Properties and Entity Extensions for Shopware 6](https://www.brocksi.net/blog/customfields-properties-entity-extensions-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](https://github.com/shopware/shopware/blob/trunk/UPGRADE-6.6.md#user-content-full-list-of-selectors) and other [recent deprecations](https://dev.to/ingosteinke/shopware-changes-since-the-60-dev-training-videos-481o).

{% post https://dev.to/ingosteinke/shopware-changes-since-the-60-dev-training-videos-481o %}

## 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.

### 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.

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.