For the past years I’ve been working with various, mostly custom-built shop systems, ranging from smaller, less frequented, to larger platforms with up to 50K users/s peaks.
Recently I joined a project, using shopware as a multishop/multilanguage environment. No real specialties, some plugins installed (e.g. OnePageCheckout, Pickware, PayPal, …) and had to bring the whole development up to speed.
Baseline
To outline the project and my tasks I’ll start with the baseline:
- default shop
- custom plugin, built by a third party company
- no deployment process
- no git integration
So the first steps were - clearly - establishing some kind of development process with git and a git-based deployment. For sake of simplicity, I opted for phploy and a stripped-down git-flow with only master/development and occasional feature branches. No tags, deployment version is HEAD of master.
First glance at shopware
To be fair: I know, shopware is a standard product with a lot of functionality to provide and maintain. Also it’s the result of an ongoing development and refactoring process over lots of years. This introduces a lot of legacy code and development practices, if we keep in mind: PHP4 → PHP5.3 → PHP7.x and the many improvements and changes in the ways one develops with php. I often describe it as “we moved from writing scripts to actual software development”.
This said, let’s have a look.
A lot of nice eyecandy in the default templates and backend, so mostly it’s kinda nice to look at (I’m no designer or design afficionado… ) and there are loads of plugins to add to your shop. Basically the plugin system works like the bundles in symfony2/3, where you have a whole sub-structure with service definitions, configuration, some initialization class and pre-defined extension points. It comes fully fledged with templating (Smarty), some database abstraction layer (Doctrine), dependency injection. All in all, everything you need to get started with your shop, from a technical point of view. Also the e-commerce abilities are quite sufficient. Works with all of Germany’s tax stuff and regulations and provides sufficient ways to add payment abilities to the checkout, like the forementioned PayPal, etc.
Some more in-depth looks
Digging deeper, reveals a lot of stuff I didn’t like, from an architectural point of view.
Architecture is basically monolithic with a plugin system - with all pros and cons. Some of the times, setter injection of dependcies, or even injecting the whole container are just a few of the things, I stumbeled upon. There are lots of extension points and classes to inherit for quick bootstrapping, like Controllers, Commands, etc. but the code you will get is really hard to test.
Code style is mostly inconsistent. You find Zend1-style classes like Enlight_Controller_Action
or newer PSR1/2 compliant ones. And even classes you might expect from a first-time programmer with no idea of OOP (within Libraries).
Template inheritance is scarcely documented and could be done better when using e.g. TWIG or some other more sophisticated templating language.
Cache layers always get in your way. You never know what cache to clear and even when to clear it. Rule-of-thumb is: Something does not work as expected? Clear the caches.
I developed a plugin, using the service definitions to add console commands and added a cache clear for the config cache in the backend. Commands were not showing up in console until I did a bin/console sw:cache:clear
- not so funny. That’s just one example of many… And deactivating the cache just doesn’t cut it. No or less cache in SW means no performance. Even in larger Symfony projects, being in dev mode does not considerately slow down your project.
Deployment and versioning just broke my heart. To be fair: I think shopware developers know about that and introduced composer as a means to manage dependencies. But still… If you have custom templates, some own plugins and want the whole shop deployed in a sane manner, we’re talking about a lot of thought and lot of workarounds.
First thing you need is a custom .gitignore
to keep shopware things out and your things within git. Then I strongly suggest, you start your project with composer! For deployment you’d better use something like ansistrano, since there are that many things to do (composer handling, git handling, config checks, cache clearing, … ).
My personal solution, since I had to deploy an already existing project, was to use phploy in combination with git and a fairly large .gitignore
. Although I suggest, you’d better use something more sophisticated than phploy ;-)
Also keep track of the shopware and plugin updates!
You can’t just update…
You’ll need at least a dev and a prod environment and need to do the updates on both systems simultaneously. That’s sometimes hard to keep track of, so be careful! Besides that, most of the times, SW updates work kinda smooth :-)
Conclusion
Shopware is on a good way to be a nice out-of-the-box solution for smaller businesses. The main criticism, I have to voice is about:
- Smarty …
- Ioncube (will be removed at SW 5.5, hopefully)
- lots of inconsitencies in the implementation, e.g. zend_db + doctrine
- many anti-patterns or bad practices like setter injection or injecting the whole container
- unwieldy to deploy
- Libraries like mpdf with ~30K LOC and PHP4-style code, hidden deep
If you want code quality, you have to have discipline and do it yourself in your own plugin. Put some thought in your deployment and development processes and you’ll be OK.