DEV Community

Ingo Steinke, web developer
Ingo Steinke, web developer Subscriber

Posted on • Edited on

Obstacles at the end of the tunnel: trying to finish my tutorial plugin

Ever so often, I felt I finally saw the light at the end of the tunnel of my learning session, only to hit the next obstacle. But let's sum up what seems to be left to do and sum up my achievements in coding a Shopware 6 plugin as a side-project so far.

I have been developing a back-end API plugin for Shopware 6 for my former employer back in 2020, partially based on trial and error and advice from the helpful community.

Side projects and tutorial hell vs. paid projects

After focusing on front-end development when I quit my job to become self-employed, I started various side-projects to deepen my knowledge, both as a full-stack developer using TypeScript, Preact, and MongoDB, as well as revisiting PHP-based back-end development to get a proper understanding and prepare for an exam to get certified as an official Shopware developer.

Having overcome the challenge of installing a development platform on localhost, things have been going quite well, and I followed the greater part of the developer tutorial successfully, all the more taken aback by the fact that some of the seemingly simple details turned out to be the biggest obstacles.

Inconsistencies vs. the harmony of Symfony

After fixing the relatively easy steps, like using translations, setting a twig variable to avoid redundant paths and improve readability, I returned to some problems that kept bothering me. Besides actual bugs, some parts of the code are hard to memorize as long as they appear to be in a random order, following an inconsistent, arbitrary syntax instead of making sense and fitting into the large picture. I know that I probably shouldn't say this about back-end development as someone who loves to code in CSS, but I hope that one day I will see the harmony of Symfony as well.

Inconsistent but consistent: screenshot of project structure in PhpStorm matching the same folder structure in the Shopware academy tutorial video

Inconsistent naming: capitalization, plural, cases

Sometimes the mixture of capitalization and cases helps to memorize where we are currently working in the project. The PHP / Symfony parts seem to be the most consistent, using capitalized first letters, singular form and camel case mostly, like
src/Storefront/Subscriber/FooterSubscriber.php

while the storefront resources get more inconsistent. Capitalization ends after the first level of sub-directories, e.g. it's src/Resources/anything/below/is/not/capitalized, but there is no comprehensive rule when to use singular or plural, so we have src/Resources/snippet vs. src/Resources/views although both directories usually contain more than one file.

So all of that stays annoyingly inconsistent, but at least it's consistent with the original framework(s) (Symfony, Shopware) that we want to extend. And again, just like CSS and spoken languages, programming languages and frameworks have evolved over time, and it takes time and practice to learn how to use them properly.

Logging an exception causes an ErrorException

This is a hard one, a problem that I already encountered, skipped, and worked around earlier many months ago: Trying to log errors or info messages. The common practice would be something like $this->logger->info("Message") (much like we would use console.log("message") in our front-end JavaScript code).

What a pity that it simply does not work in my custom plugin, maybe not even anywhere in my local Shopware installation. Worse still, this one seems impossible to google! Searching for my error message ("ErrorException: Notice: Undefined property: Storefront\Subscriber\FooterSubscriber::$logger") in various variations either produce results omitting the relevant search terms or else stating that "it looks like there aren't many great matches" for my search. You don't say! I have already wasted a lot of time and still fail to understand how I seem to be the only person on this planet to run into this kind of problem. And it's not the first time either that I thought "I really enjoy life-long learning, but..."

Screenshots of unhelpful search results described above

I suspect that this is another example of "I closely followed every aspect of a tutorial, but my code is not working," instead of just getting inspired by tutorials without stopping to use my own brain.

Keeping a local dev installation up to date

This brings me to another issue: how to make sure that my local installation is up to date? Maybe there are bugs in the framework that have been fixed already. Unlikely that's what's causing my current errors, but it doesn't help to check anyway.

According to my admin dashboard, I am using "6.4.9999999.9999999-dev", which is always greater and seemingly "newer" than the latest current stable "6.4.x" release, so there must be another way to update - hopefully without breaking the working system - probably pulling the latest changes from git and rebuilding the framework, and that should have been obvious from the docs, but obviously it wasn't, and I forgot, getting so desperate, confused and "lazy" that I have to seek guidance and assistance and ask another question in the community chat.

Meanwhile, I could try my luck with one of the other leftover embarrassments like the system config service not working properly.

Fix reading Shopware's SystemConfigService

Screenshot of code using SystemConfigService

It can't hurt to make our code so verbose that it starts to look like Java: there are 10 occurrences of "SystemConfigService" in my class file, only to look up one (1) setting in my plugin configuration once! But that would be fine for me if it would work - only it doesn't!

It's not the first time that I use the logger or the system config service, so what is going on here?

I will probably tell you in the next part of my shameless revelations about feeling clueless learning in public, so stay tuned!

Top comments (3)

Collapse
 
ingosteinke profile image
Ingo Steinke, web developer • Edited

Update: updating without reinstallation must use the update command instead of install to retain existing data (see Joshi's StackOverflow post: How to update shopware 6 docker local setup while persisting existing data?

Updating locally:

cd development/platform
git pull
rm composer.lock && rm -rf vendor/* && composer install
cd ..
git pull
rm composer.lock && rm -rf vendor/* && composer install
./psh.phar docker:start && ./psh.phar docker:ssh
Enter fullscreen mode Exit fullscreen mode

Inside the docker container, don't use install but update!!!

./psh.phar update # don't use install or you lose data and configuration
Enter fullscreen mode Exit fullscreen mode

Then log in to the administration backend, configure storefront, reactivate themes and settings, and continue development.

To verify that you actually updated your shop, watch out for errors and deprectations, like EntityRepositoryInterface is now deprecated (although it is still being used in the official Shopware Academy developer tutorial videos). Just to make sure that (like JavaScript developers) there is always something to do, always some code to update just for the sake of updating?!

Of course, there are reasons. You can see all the details on GitHub (shopware/platform NEXT-21456). Shopware "deprecated EntityRepositoryInterface, the class will be removed with next major, type hint with EntityRepository instead". And there are more deprecations, like

bin/console dal:refresh:index 15:03:56 INFO [php] User Deprecated: Since shopware/core : Class "Shopware\Core\Framework\Routing\Annotation\RouteScope" is deprecated and will be removed in v6.5.0.0. Use ""@route(defaults={"_routeScope"={"storefront"}})"" instead.

Collapse
 
ingosteinke profile image
Ingo Steinke, web developer • Edited

I researched an reposted my inquiry about properly handling the deprecations introduced in the latest Shopware 6.4.13.0 release as a StackOverflow question: Replacement for deprecated Shopware EntityRepositoryInterface is also deprecated.

Thanks to shiyim's quick reply.

The deprecation of EntityRepository has been fixed with commit 99cf9093464d679f6abcb91bb68cc4205bc6ccf0

EntityRepository has now only @final github.com/shopware/platform/blob/...

According to Shopware 6.4.13.0 upgrade instructions, EntityRepositoryInterface has been deprecated and should be replaced by EntityRepository. But EntityRepository is also marked as deprecated in my IDE, using the recommended development setup all upgraded to the latest versions:

  • PhpStorm (2022.1.3 Build #PS-221.5921.28)
  • Symfony Support plugin 2022.1.230
  • Shopware plugin 4.4.3
Collapse
 
ingosteinke profile image
Ingo Steinke, web developer

Logging in Shopware 6 using Logger in a PHP file

I am not sure if this is the official best practice, but at least this works in Shopware 6 for example in a Subscriber.php inside a custom plugin:

  • inject the Logger interface as a service argument
  • receive the service in the constructor function
  • service arguments and constructor paramaters must be in the same order
  • define $this->logger in the constructor,
  • so that you can use $this->logger->info etc. like in a regular Symfony project.

services.xml

<?xml version="1.0" ?>

<container xmlns="http://symfony.com/schema/dic/services"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd">
    <services>
        <service id="MyTheme\Storefront\Subscriber\FooterSubscriber">
            <!-- This must be in the same order as the constructor arguments in FooterSubscriber.php ! -->
            <argument id="logger" type="service" />
            <!-- ... anything else -->
Enter fullscreen mode Exit fullscreen mode

FooterSubscriber.php

use Psr\Log\LoggerInterface;
class FooterSubscriber implements EventSubscriberInterface
{
    /** @var Logger */
    private Logger $logger;
        LoggerInterface $logger
    )
    {
      $this->logger = $logger;
    public function __construct(
Enter fullscreen mode Exit fullscreen mode