<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <title><![CDATA[Shopware Developers]]></title>
    <link href="https://developers.shopware.com/atom.xml" rel="self"/>
    <link href="https://developers.shopware.com/"/>
    <updated>2025-09-18T10:25:04+00:00</updated>
    <id>https://developers.shopware.com/</id>
        <generator uri="http://sculpin.io/">Sculpin</generator>
        <entry>
        <title type="html"><![CDATA[Shopware Tech Keynote]]></title>
        <link href="https://developers.shopware.com/blog/2019/06/11/shopware-tech-keynote/"/>
        <updated>2019-06-11T00:00:00+00:00</updated>
        <id>https://developers.shopware.com/blog/2019/06/11/shopware-tech-keynote/</id>
        <content type="html"><![CDATA[<h1 id="shopware-tech-keynote">Shopware Tech Keynote</h1>

<p>Shopware Community Day 2019 was the first time, we had two keynotes at the same time: The main keynote by our CEO and co-founder Sebastian Hamann - and the tech keynote by myself. For me it was a great honor and pleasure to give you a technical overview of Shopware 6; in this blog post, I want to summarize my thoughts about Shopware 6</p>

<h1 id="why-we-went-shopware-6">Why we went Shopware 6</h1>

<p>Shopware 6 is a complete rewrite of Shopware. Of course we didn't reinvent the wheel for things, that we were happy with in Shopware 5; at the same time we wanted to improve many topics we have not been able to address in Shopware 5.</p>

<p>Furthermore we thought a lot, how E-Commerce might look like in a few years, which requirements we might need to address - and which customer segments we want to reach. We quickly found, that it was not about hype technologies - but about creating a broad foundation, that small and smallest merchants as well as enterprise merchants could be successful with. In addition to many technological considerations this especially means, that merchants needs to know what customers want - perhaps without the customers knowing, what they want.</p>

<p>In order to reach existing and new customers, I pointed out three dimensions in my keynote:</p>

<ul>
<li>Internationalisation</li>
<li>New channels</li>
<li>Customer loyalty</li>
</ul>

<p>In Shopware 6 we placed great emphasis on these dimensions. For internationalisation we have new concepts for translations (and inheritance of translations). Also handling of gross and net prices as well as prices per currency has improved. The new SalesChannel concept allows for a new perspective on additional channels such as eBay, Amazon, Instagram etc. The new RuleBuilder allows you to address every SalesChannel specifically - and is also a powerful regarding customer loyalty, as you can shape very individual customer segments and address any customer exactly as you want to.</p>

<p>In order to set the potential of those dimensions free, complexity must be reduced. Merchants need to be able to try out new things and want to quickly identify failures and successes in order to learn from their experiences. At the same time enabling creativity and speed also means, that developers want to know, which direction to go. "Everything is possible somehow" is not a sentence, that will help you to create awesome software. That's why we reconsidered how e.g. our data model should look like, how extensions should take place and how developers want to work with the shopping cart.</p>

<p>Enabling people to use the new technologies also implies, that we need to reduce legal barriers. By switching to the more permissive MIT license, shopware clearly commits to the open source community.</p>

<p>For me, this is the philosophy behind Shopware 6: We enjoy new technologies and are excited to try them out. But the developers and merchants are the ones, who are truly innovative in their everyday projects. And they do neither need a tight e-commerce corset nor a spaceship toolbox. They need a reliable foundation on which to build. And that's Shopware 6: Simple, flexible, state of the art and open source.</p>

<h1 id="tech">Tech</h1>

<p>Now let's have a look at the technology. The most obvious change is the switch to Symfony, for sure. Symfony is probably the most popular PHP framework and has shaped a whole generation of developers. By using Symfony in Shopware, we make sure, that it becomes easier to onboard developers on Shopware 6.</p>

<p>For the same reason, we are switching from ExtJS to VueJS as a javascript framework for our new admin. VueJS describes itself as a "progressive and incrementally adoptable" framework. For us this means, that it can be tailored to our needs and requirements. And again: We are convinced, that it makes it easier to onboard new developers to Shopware 6.</p>

<h2 id="dal">DAL</h2>

<p>Another major change is the new data abstraction layer (DAL). This is a layer between your database storage and the actual application and takes care of all your data operations - be it reads, writes, searches or aggregations.</p>

<p><img src="/blog/img/dal.png" alt="DAL schema" /></p>

<p>In Shopware 5 we introduced a similar layer for read operations only for products in the storefront. We found, that it made Shopware much more understandable and predictable for the development community. But in difference to the product services in Shopware 5, the DAL takes care of all entities and all kind of data access. For that reason, no more custom SQL queries should be required anymore. Furthermore, the DAL can also take care of syncing various storages: In modern e-commerce infrastructures you will easily find ElasticSearch and Redis in addition to MySQL. The DAL can be used to sync those storages, so that MySQL is used as a primary storage but ElasticSearch is always kept in sync. And there are even more functionalities such as versioning or translations, that you can make use of easily:</p>

<pre><code class="php">class ProductManufacturerDefinition extends EntityDefinition
{
    public function getEntityName(): string
    {
        return 'product_manufacturer';
    }

    protected function defineFields(): FieldCollection
    {
        return new FieldCollection([
            (new IdField('id', 'id'))-&gt;addFlags(new PrimaryKey(), new Required()),
            new VersionField(),

            new FkField('media_id', 'mediaId', MediaDefinition::class),
            new StringField('link', 'link'),
            new TranslatedField('name'),
            new TranslatedField('description'),
            new TranslatedField('customFields'),

            new ManyToOneAssociationField('media', 'media_id', MediaDefinition::class, 'id', true),
            (new OneToManyAssociationField('products', ProductDefinition::class, 'product_manufacturer_id', 'id'))-&gt;addFlags(new RestrictDelete(), new ReverseInherited('manufacturer')),
            (new TranslationsAssociationField(ProductManufacturerTranslationDefinition::class, 'product_manufacturer_id'))-&gt;addFlags(new Required()),
        ]);
    }
}

</code></pre>

<p>The above example show, how to define a product manufacturer entity with various translatable fields and relations to e.g. media and products. For more details please have a look at <a href="https://docs.shopware.com/en/shopware-platform-dev-en/internals/core/data-abstraction-layer/definition">the description in our documentation</a>.</p>

<h2 id="extensions">Extensions</h2>

<p>If you are already familiar with the Shopware 5 plugin system, I've good news for your: Many of the patterns will look familiar to you.</p>

<pre><code>&lt;project root&gt;
└── custom
    └── plugins
        └── PluginQuickStart
            ├── src
            │   ├── Controller
            │   │   └── MyController.php
            │   ├── Resources
            │   │   ├── config
            │   │   │   ├── config.xml
            │   │   │   ├── routes.xml
            │   │   │   └── services.xml
            │   ├── Service
            │   │   └──  MyService.php
            │   ├── Subscriber
            │   │   └── MySubscriber.php
            │   └── PluginQuickStart.php
            └── composer.json
</code></pre>

<p>So you still have a base plugin file, where you can implement various methods to define the behaviour of your plugin during installation or uninstallation. Creating new services or extending existing ones is possible using the <code>service.xml</code> definition file. And if you want to use events, you can write the same kind of subscribers, you've been using in Shopware 5, too. For more details, have a look at our <a href="https://docs.shopware.com/en/shopware-platform-dev-en/internals/plugins/plugin-quick-start?category=shopware-platform-dev-en/internals/plugins">plugin quickstart guide</a>.</p>

<h2 id="summary">Summary</h2>

<p>All in all a lot of things have changed in Shopware 6. But we are convinced, that this will make things easier for you in the long run. If you are looking for additional resources, have a look at our <a href="https://docs.shopware.com/en/shopware-platform-dev-en">documentation</a> or our <a href="https://www.shopware.com/en/academy/online-trainings/">training program</a>. There are a lot of free remote trainings, that will help to get started with Shopware 6.</p>

<h1 id="business-models">Business Models</h1>

<p>Talking about "business models" in a tech keynote might seem a little strange. But if we really want to understand, what kind of requirements are relevant for our development community, we had to understand, what kind of requirements you get in projects - and where things became tedious in the past.</p>

<h2 id="rulebuilder">RuleBuilder</h2>

<p>The RuleBuilder is a whole new concept regarding customer targeting. In Shopware 5 (and many other e-commerce systems) you will just find some kind of "groups" that can be used for pricing, promotion, content, category restrictions, countries etc. The more usecases one had, the more complicated it became to maintain all the groups.</p>

<p>The RuleBuilder goes another approach: It allows you to create complex and nested rules that describe a customer you want to address for a certain usecase. This not only make easier to create "dynamic groups" (e.g. a group of all customers older than 18 or a group with all customers from a certain area) but also makes it easier to  give those customers special pricing, special content or restrict orders / payments / shipments for them.</p>

<p>The new RuleBuilder allows Shopware 6 to meet requirements that would have required a custom extension in the past.</p>

<h2 id="new-cart">New Cart</h2>

<p>One of the earliest parts of Shopware 6 is the new cart. Actually the first concepts where created in 2016. We analyzed many usecases where people had to modify the cart in order to meet the merchant's requirements.</p>

<p>As the new RuleBuilder can also be used to create price definitions, price handling becomes much more flexible with the new cart. Not only is the cart much more powerful when it comes to the question which customer gets which price: it also is more flexible regarding threshold prices per currency and handling of gross / net prices.</p>

<p>Another big topic was database performance. On the one hand, you want to make sure, that during the cart process all pricing and stock information is consistent and correct and no order is possibly lost. On the other hand, you want to reduce the impact of the cart onto the database as much as possible, as this critical part of most e-commerce-systems is notoriously known for its heavy write operations. This is why the new cart is much more lightweight and reduces read / write operations as much as possible. The price, to which this comes, are conventions regarding the information you should / could access with your extensions.</p>

<h2 id="shopping-experiences">Shopping experiences</h2>

<p>A new tool for merchants are the so called "shopping experiences". With this tool, it becomes easier to create unique and appealing content for the online shop. Of course - as you might now it from shopping worlds in Shopware 5 - you can create content. But the shopping experiences set another focus:</p>

<p>There a dozens of prefabricated blocks, which show you all kind of combinations between images, texts, sliders, videos and commerce components. You can just pick the block, that comes closest to your imagination and drop it to the designer. This designer will always give you a realistic overview of how the shopping experience could look like in the frontend. At the same time it allows you to configure the elements to your needs: You can edit texts, swap elements with others or rearrange blocks. Every block is responsive by default. So you don't need to think about viewports and columns any more.</p>

<p><img src="/blog/img/cms-data-mapping.png" alt="data mapping with the CMS" /></p>

<p>What makes the shopping experience so powerful is the fact, that every page you created this way, can be used as a layout for category pages, product pages or landing pages. You can even dynamically reference properties of those pages. For example: If you create a layout for categories, you can dynamically reference the category's name. For a product layout, you could dynamically reference an image of the product or its description.</p>

<p>And for the future, we are planning more functionalities, which will come in handy in many projects: E.g. editorial workflows for content pages or versioning.</p>

<h1 id="conclusion">Conclusion</h1>

<p>Of course this can just be a glimps of the new technologies, functionalities and concepts in Shopware 6. But what makes this awesome from my perspective is the fact, that based on our experiences with small, medium and large e-commerce projects we asked ourselves: What do customers want? What do merchants need? What do you need as a developer? This common theme makes Shopware 6 more fun to use - and more powerful in projects. 
At the SCD 19 we released the developer preview of Shopware 6. With this version we want to collect your feedback as a developer. Feel free to check out our <a href="https://github.com/shopware/platform">Shopware 6 repository on Github</a> and give us feedback.</p>
]]></content>
    </entry>
        <entry>
        <title type="html"><![CDATA[What is phive and why you should use it!]]></title>
        <link href="https://developers.shopware.com/blog/2018/11/30/what-is-phive-and-why-you-should-use-it/"/>
        <updated>2018-11-30T00:00:00+00:00</updated>
        <id>https://developers.shopware.com/blog/2018/11/30/what-is-phive-and-why-you-should-use-it/</id>
        <content type="html"><![CDATA[<p>At the beginning of this year we decided to create a new enterprise accelerator for our enterprise eco system. The so called Pricing Engine. With this new project we evaluated the PHAR Installation and Verification Environment (PHIVE) to manage all our *.phar dev tools.</p>

<p>Normally we store our dev tools in the document root of our git repository. As an example in the B2B-Suite we have seven several phar files (deptrac, phpDocumentator, phpcpd, phploc, phpstan, psh and security-checker). With phive we can manage all our dev tools with a phive.xml file. As you can see in the below example, you can define the version which should be used, the position where it should be placed and at last if it should be a symlink or a real copy of the phar file. Normally phive downloads the specific phar file and symlinks it in the place where it has to be.</p>

<pre><code class="xml">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;phive xmlns="https://phar.io/phive"&gt;
  &lt;phar name="php-cs-fixer" version="^2.12.2" installed="2.13.0" location="./tools/php-cs-fixer" copy="true"/&gt;
  &lt;phar name="shopwarelabs/psh" version="^1.2.0" installed="1.2.0" location="psh" copy="true"/&gt;
  &lt;phar name="phpstan" version="^0.10.1" installed="0.10.3" location="./tools/phpstan" copy="true"/&gt;
  &lt;phar name="shopwarelabs/sw-cli-tools" version="^0.0.1" installed="0.0.1" location="./tools/sw" copy="true"/&gt;
&lt;/phive&gt;
</code></pre>

<p>This sounds very interesting isn't it? But how difficult is it to create a new software project and use phive for managing all dev tools?</p>

<h2 id="setup-a-new-project-with-phive">Setup a new Project with phive</h2>

<p>The question is very easy to answer, it is as easy as to create a new composer project. As a preparation we have to install phive on our system. To do it use the snippet below:</p>

<pre><code class="bash">wget -O phive.phar https://phar.io/releases/phive.phar
wget -O phive.phar.asc https://phar.io/releases/phive.phar.asc
gpg --keyserver pool.sks-keyservers.net --recv-keys 0x9D8A98B29B2D5D79
gpg --verify phive.phar.asc phive.phar
chmod +x phive.phar
sudo mv phive.phar /usr/local/bin/phive
</code></pre>

<p>After the installation we can easily install php-cs-fixer with <code>phive install php-cs-fixer</code>. In this example php-cs-fixer is an alias and corresponds to the GitHub repository <a href="https://github.com/FriendsOfPHP/PHP-CS-Fixer">FriendsOfPHP/PHP-CS-Fixer</a>. You can find alternative installation instructions below:</p>

<pre><code class="bash">phive install php-cs-fixer
phive install FriendsOfPHP/PHP-CS-Fixer
phive install https://github.com/FriendsOfPHP/PHP-CS-Fixer/releases/download/v2.13.1/php-cs-fixer.phar
</code></pre>

<p>You can use the already mentioned alias, or an github repository with a maintained release section or the direct url to the specific file.</p>

<h2 id="own-phar-files">Own phar files</h2>

<p>To install own phar files with phive you have several ways to achieve this:</p>

<ul>
<li>GitHub Releases (phive install username/project)</li>
<li>registered alias on phar.io (phive install alias)</li>
<li>explicit url (phive install https://server/file-1.0.0.phar)</li>
</ul>

<p>We will have a more detailed look in the GitHub Releases way and we will use <a href="https://github.com/shopwareLabs/psh">psh</a> as an example for that. We have the following requirements:</p>

<ul>
<li>GPG Key for your project</li>
<li>GPG Key must be public available on the SKS Keyservers</li>
<li>already generated phar file.</li>
</ul>

<p>If all requirements fit we open the console and go to our project directory where the phar file is stored. Now we will use this command <code>gpg -u psh@example.com --detach-sign --output psh.phar.asc psh.phar</code> to sign our generated phar file. After that we have a new file psh.phar.asc. Both files has to be uploaded to our existing version under https://github.com/shopwareLabs/psh/releases. That was all the work we needed for that. If you want access your phar file via url you have to store the .asc file in the same directory.</p>

<p>Now you can use <code>phive install shopwareLabs/psh</code> to install psh.phar. We have already <a href="https://github.com/phar-io/phar.io/commit/d88298103c9fe7a99fdc00d930f505c83b67ada0">created</a> an alias for psh so a <code>phive install psh</code> is also possible. If you want to create your own alias you just have to create a pull request for <a href="https://github.com/phar-io/phar.io">phar-io/phar.io</a></p>

<h2 id="conclusion">Conclusion</h2>

<p>Phive is a very good tool to manage the ecosystem around the needed dev tools. You escape easily the dependency hell and manage updates of your tool has never been so easy. Furthermore you save much space in your repository. The usage of OpenPGP/GnuPG secures the hole workflow of getting the needed phar files.</p>

<p>At the moment we uses phive only for the Pricing Engine. In the future we will integrate phive in our other projects. Who does not use phive at the moment, should start not later than now.</p>
]]></content>
    </entry>
        <entry>
        <title type="html"><![CDATA[Clickstream analysis with server logs]]></title>
        <link href="https://developers.shopware.com/blog/2018/09/28/clickstream-analysis-with-server-logs/"/>
        <updated>2018-09-28T00:00:00+00:00</updated>
        <id>https://developers.shopware.com/blog/2018/09/28/clickstream-analysis-with-server-logs/</id>
        <content type="html"><![CDATA[<p>Demographic data like server logs are more valuable than many shop user think. With server logs we identify user groups, push valuable products or do customer specific shop marketing with data lying around on the server. In this blog post I will describe how to use the data in a theoretical way with a book selling online shop.</p>

<h3 id="identify-the-customer">Identify the customer</h3>

<p>First of all, lets divide the customers in two groups. Traditional customers buy printed books and innovative ones buy other types like audio books. To filter the customers we have to prepare the log data and bring the data together to form sessions. Sessions contain all server log entries from a specific IP address starting with the the first view of the shop until he leaves it. An access to a SuperTracker Database can help to validate and add additional attributes and characteristics to the sessions. After defining the sessions they have to be filtered into useful and useless ones. Useless sessions are caused by bots and customers with only one or two log entries who accidentally visited the shop.</p>

<blockquote>
  <p>(Suchacka &amp; Chodak, 2017)</p>
</blockquote>

<div style='text-align:center;'>
<img src="/blog/img/2018-09-28-clickstream-analysis-with-server-logs/framework.jpg"/>

###### Association rule generation framework for a B2C website (Suchacka & Chodak, 2017)
</div>

<h3 id="classification-of-sessions">Classification of sessions</h3>

<p>After the session filter, every session will be classified. Basic Classifications can be the time duration on the shop, how many pages were visited or the time duration on a specific page. These classified sessions can also be more detailed classified. The classification parameters can be wich browser was used, the login status of the customer, did the customer add some products into the basket or actually performed an order. Using the data with an A-priori algorithm, events can be identified, which improves the chances of customer orders.</p>

<blockquote>
  <p>(Suchacka &amp; Chodak, 2017)</p>
</blockquote>

<h3 id="result-click-stream-analysis">Result click stream analysis</h3>

<div style="text-align:center;">
<img src="/blog/img/2018-09-28-clickstream-analysis-with-server-logs/histogram.jpg"/>

###### Histogram of session lengths for buying sessions for innovative and traditional customers (Suchacka & Chodak, 2017)
</div>

<p>In our case traditional customer perform orders very fast and innovative customers wander longer through the shop before perform an order. Another result of the analysis determine 89 percent of innovative customers perform an order by entering the shop with a link from a search engine, add an article in the basket and open up to 45 pages on the system. Traditional customers have a tendency of 92 percent to perform an order after login in, visit 30 to 75 pages and be in the shop around 10 to 25 minutes. With these results customer group specific marketing can be performed. We can improve our page views of innovative customers by adding more optimised ads in search engines.</p>

<blockquote>
  <p>(Suchacka &amp; Chodak, 2017)</p>
</blockquote>

<h3 id="gender-prediction">Gender prediction</h3>

<p>Another way to use the session data is to predict the customers gender and show specific landing pages to them. For gender prediction we have to classify and filter the session in other ways.  We do not want only to know how long the customer was on one page or in the shop but also in which season and on which day and month of the year. The amount of viewed products is also a possible filter for the sessions. Another group of data can be formed by display the categories and products in a binary tree view and show every switch and view of the category and product pages on this tree. With machine learning algorithm like <a href="https://en.wikipedia.org/wiki/Random_forest">Random Forest</a>, <a href="https://en.wikipedia.org/wiki/Support_vector_machine">Support Vector Machine</a>, <a href="https://en.wikipedia.org/wiki/Bayesian_network">BayesNet</a> or <a href="https://en.wikipedia.org/wiki/Gradient_boosting">Gradient Boosting Decision Trees</a>, we can predict the gender from sessions.</p>

<blockquote>
  <p>(Duc Duong et al., 2016)
  (Lu et al., 2015)</p>
</blockquote>

<h3 id="machine-learning-algorithms">Machine learning algorithms</h3>

<ul>
<li><a href="https://en.wikipedia.org/wiki/Random_forest">Random Forest</a> is a classification method working with decision trees. Through randomising the decision tree is growing and at the end, the class with the most votes will be chosen.</li>
<li><a href="https://en.wikipedia.org/wiki/Support_vector_machine">Support Vector Machine</a> classifies the data with hyperplanes in the vector space of the objects.</li>
<li><a href="https://en.wikipedia.org/wiki/Bayesian_network">BayesNet</a> consists of a directed acyclic graph with various nodes and edges, which are randomised variables and conditional dependencies between the variables.</li>
<li><a href="https://en.wikipedia.org/wiki/Gradient_boosting">Gradient Boosting Decision Trees</a> create weak classifications which will be combined to one strong classification.</li>
</ul>

<p>To choose the right method for learning with test data depends on how balanced the data is. With unbalanced Data like 80 percent women and 20 percent men, a “Cost-Sensitive Learning” method is needed to minimise the total costs and therefore get a higher statistically percentage for the right gender prediction.</p>

<blockquote>
  <p>(Duc Duong et al., 2016)</p>
</blockquote>

<h3 id="result-of-gender-prediction">Result of gender prediction</h3>

<p>In the end it depends on the quality of the data and the chosen algorithm how high the percentage for the right gender prediction is. Two teams at a tournament from <a href="https://knowledgepit.fedcsis.org/contest/view.php?id=107">FPT Corporation of PAKDD’15</a> performed with the given dataset a 81,4 percent correct prediction for both gender and the other team a 95 percent correct prediction of the female and a 77 percent correct prediction of the male gender.</p>

<blockquote>
  <p>(Duc Duong et al., 2016) (Lu et al., 2015)</p>
</blockquote>

<h3 id="literature">Literature</h3>

<ul>
<li>Suchacka, G., &amp; Chodak, G. (2017). Using association rules to assess purchase probability in online stores. Information Systems and E-Business Management, 15(3), 751–780. https://doi.org/10.1007/s10257-016-0329-4</li>
<li>Duc Duong, Hanh Tan, &amp; Son Pham. (2016). Customer gender prediction based on E-commerce data. In 2016 Eighth International Conference on Knowledge and Systems Engineering (KSE) (pp. 91–95). IEEE. https://doi.org/10.1109/KSE.2016.7758035</li>
<li>Lu, S., Zhao, M., Zhang, H., Zhang, C., Wang, W., &amp; Wang, H. (2015). GenderPredictor: A Method to Predict Gender of Customers from E-commerce Website. In 2015 IEEE/WIC/ACM International Conference on Web Intelligence and Intelligent Agent Technology (WI-IAT) (pp. 13–16). IEEE. https://doi.org/10.1109/WI-IAT.2015.106</li>
</ul>
]]></content>
    </entry>
        <entry>
        <title type="html"><![CDATA[An Argument against Microservices]]></title>
        <link href="https://developers.shopware.com/blog/2018/08/22/an-argument-against-microservices/"/>
        <updated>2018-08-22T00:00:00+00:00</updated>
        <id>https://developers.shopware.com/blog/2018/08/22/an-argument-against-microservices/</id>
        <content type="html"><![CDATA[<p>Microservices... I have problems with that. And from many discussions at conferences I get the impression that I might not be the only one who's <em>not getting</em> it. So in the following article I want to attempt to deep dive into the promises behind the Microservice architecture, lament on solutions and show the costs behind it.</p>

<h2 id="micro-what%3F">Micro What?</h2>

<p>Distributed systems are all the rage now and have been at least over the past decade. The Cloud innovation, especially in the PaaS and FaaS (= keep Moore's Law alive by increasing the number of parallel processes) area, pushes software development to create finer grained executable stacks for more and more abstract machines. Technologies invented for <a href="https://en.wikipedia.org/wiki/Common_Object_Request_Broker_Architecture">CORBA</a>, <a href="https://en.wikipedia.org/wiki/Service-oriented_architecture">SOA</a> or <a href="https://en.wikipedia.org/wiki/Representational_state_transfer">REST</a> are joining forces in Microservices to rule the world.</p>

<p>Microservices are an architecture style. They are a possible solution to key demands for large scale development. Large software, large userbase, large development team, large data and so on. The central promise is that they allow for <strong>far greater scaling</strong> than any other style of architecture by reducing the need for <strong>global decisions</strong>.</p>

<p>They usually get contrasted with the vast space of <strong>monolithic</strong> architecture styles => an application as a single interconnected entity of functionality.</p>

<h2 id="so-what-is-a-microservice%3F">So what is a Microservice?</h2>

<p>If you look at the - always insightful - <a href="https://martinfowler.com/articles/microservices.html">blog of Martin Fowler</a> he describes the style as</p>

<blockquote>
  <p>[...] a particular way of designing software applications as suites of <strong>independently deployable services</strong> [...]</p>
</blockquote>

<p>How would this work? When planing a green field application one typically slices the project up front in <strong>layers/components/milestones/building blocks</strong>. If you plan to create Microservices you are now free to slice these building blocks into different applications. Communication is only allowed to go through an API and in many cases publish and subscribe to an event system. These Services do not share infrastructure. They are (potentially) deployed to different servers, write to their own storage and know only about necessary peers, that they themselves only access through a well defined API. The term <em>micro</em> comes from the idea that these services themselves should be <em>really small</em> or do <em>one thing only</em>.</p>

<p>A single service then has to be a fully working application, that performs a miniscule part of the workload of the whole application. Well known and published examples of this architecture styles are <a href="https://medium.com/netflix-techblog">Netflix</a> and Amazon, or eCommerce specific <a href="https://dev.otto.de/tag/self-contained-systems/">Otto Group</a> or the <a href="https://academy.spryker.com/">Spryker plattform</a>.</p>

<p>Of course the devil is in the detail. But simply put Microservices reduce code coupling in favor of networking and reduce organization coordination by giving more freedom to the individual teams and developers. So let's investigate these two promises separately:</p>

<h2 id="reduced-coupling">Reduced Coupling</h2>

<p>It should be common knowledge by now, that coupling code is not only the one thing responsible for software to actually do something, but also the main cause of death for legacy systems. Systems need to be intertwined because one of the main benefits is, that existing data and functionality can be rearranged into new and interesting functionality. A byproduct of this rearrangement usually is friction, because the original system was not designed to behave in the newly implemented way. As a system gains new capabilities it internally starts to accumulate more and more friction. When handling this friction outweighs the time spent on the actual feature implementation you are in trouble.</p>

<p>This insight is not only well known, but also a quite old. And of course multiple - not mutually exclusive - strategies are available to prevent this already: <a href="https://en.wikipedia.org/wiki/Domain-driven_design">DDD</a>, <a href="http://alistair.cockburn.us/Hexagonal+architecture">Ports &amp; Adapters</a>, <a href="https://en.wikipedia.org/wiki/SOLID">SOLID</a>, <a href="https://en.wikipedia.org/wiki/Test-driven_development">TDD</a>, <a href="https://medium.com/mindorks/how-to-write-clean-code-lessons-learnt-from-the-clean-code-robert-c-martin-9ffc7aef870c">Clean Code</a> and many other sources try to help you here.</p>

<p>Microservices now add three main strategies for prevention.</p>

<p><strong>Services share the least viable amount of information with each other.</strong> If executed correctly, this is a very good thing! <a href="https://en.wikipedia.org/wiki/Information_hiding">Information hiding</a> is by no means a new concept, and by no means a solved problem. Microservices effectively try to achieve this, by making the process simply <strong>more painful</strong>, than it was in the past. If you need an API, that contains additional information this needs additional planning and agreement between the developers. However the incentive still is to create a too broad interface if not checked otherwise.</p>

<p><em>Verdict: Adding pain is an interesting concept, but by no means a sufficient guarantee for good design.</em></p>

<p><strong>Make services small, so they can easily be replaced</strong> Also a nice idea! Create a service in hours or days, if it doesn't add the expected value, just discard it. If a service that is currently not owned needs changes, the next developer can start at a green field, if he so chooses - just the API needs to be the same. I would bet you have done this countless times in the past, but without calling it service. Reengineering a class, a namespace, a feature. This is not new. Our programming languages actually have constructs for this. And at least in my experience, changing the internal structure without changing the external behaviour only works to a certain degree. Imagine moving from <a href="https://en.wikipedia.org/wiki/Create,_read,_update_and_delete">CRUD</a> to <a href="https://martinfowler.com/bliki/CQRS.html">CQRS</a>+<a href="https://martinfowler.com/eaaDev/EventSourcing.html">ES</a> for a single building block. This either has consequences for external usage or just adds friction.</p>

<p><em>Verdict: Really no help</em></p>

<p><strong>Use unreliable communication technologies so that all coupling is taken with a grain of salt.</strong> This one is interesting: Networking adds the problem of delays, retries, unavailabilities to something that a monolith would do and guarantee in process. Failure tolerant networking adds the ability to silence functionality by only removing a single service without having to change anything else about the system. But there is a tradeoff: There needs to be an enforced convention to secure all applications behave like this and you need documentation to know which service needs to be killed for this. Exactly the thing you are now missing for your existing application, too. If you want to enforce methodologies like this I would make a case, that it is actually easier to do it through static analysis in a monolith.</p>

<p><em>Verdict: Has a desirable effect on your architecture.</em></p>

<p>Microservices effectively reduce coupling mainly by making it harder to use common abstractions across a project. Since these are all different applications you need some kind of package management system to achieve code sharing. But more on that in the next chapter.</p>

<p>Ok, so where is the Microservice advantage exactly? Quite easily put: <strong>Best practices get enforced through pain</strong>. If you don't behave according to common wisdom they show bugs very early. But basically - at least I would argue - there are not that many benefits to a monolith from a software architecture standpoint here.</p>

<h2 id="freedom-for-teams">Freedom for teams</h2>

<p>Developers, developers, developers!!! Maybe Microservices show strengths here? As <a href="https://en.wikipedia.org/wiki/Conway%27s_law">Conway's Law</a> states.</p>

<blockquote>
  <p>"organizations which design systems ... are constrained to produce designs which are copies of the communication structures of these organizations." - M. Conway</p>
</blockquote>

<p>While this abstract definition might be a little hard to grasp, there is a very good example that showcases the effect your organizational structure has on the software you produce:</p>

<blockquote>
  <p>"If you have four groups working on a compiler, you'll get a 4-pass compiler." - E. S. Raymond</p>
</blockquote>

<p>... because communication is most intense inside the team and gets sparser and sparser the further away another team is organization wise. Microservices are the logical conclusion to this. There needs to be a formal way to negotiate API interfaces between teams and that's it. This actually solves a real problem in software development: <strong>Scale</strong> If you ever started a green field project with a projection for more then two developers and a initial runtime of more then a year you should know how hard it is to get everyone working. Huge Silicon Valley corporations want to start projects with hundreds of developers or maintain flagship products with even more people. Communication becomes an overhead that delays a product significantly think of it like an expression of the big upfront design antipattern. The more people you have that need to work the more expensive it becomes to negotiate a single decision.</p>

<p>By giving the highest degree of freedom to your teams the structure of your software changes, too. Dependencies in such a huge product can no longer be organized like a top down tree but are in fact more like a <strong>bee hive</strong>. Microservices can potentially be even more than that. The hive is multinational! Your services can be written in any language, come from any source and as long as network communication is possible you are fine. In extreme cases there can and will be C code communicating happily with a PHP script that notifies a Python app that provides data for Node app. Every one of these apps is self contained and uses a different set of tools for its build, deployment, integration and monitoring. Yeah!</p>

<p>Now imagine something is broken. How can you inspect, debug and fix any issue in such a system? You need conventions!</p>

<blockquote>
  <p>"With great power comes great responsibility" - B. Parker</p>
</blockquote>

<p>If you want to base each new service on different technology you will find that your Microservices have multiple different solutions to the same common problem. <a href="https://en.wikipedia.org/wiki/Not_invented_here"><em>Not invented here</em></a> is the built-in result from this approach to team organizations.</p>

<p>To stay with the bee hive metaphor: Even they grow over time from just a founding queen.</p>

<p>In the end the freedom simply does not come for free. Where does scale outweigh central technical decision management? Some huge companies that develop concurrently on a single product of course have good reasons to go into that direction. And in the wild you will find scaled back solutions (e.g. single programming language, central logging and monitoring, centrally enforced architecture, even single process) that try to get the pros without the cons. But what is left in these cases?</p>

<h2 id="problems-arise">Problems arise</h2>

<p>I get hyped by talks on conferences. Either watching them directly live or in recording. But Microservices tend to tickle a nerve, where I constantly ask myself: "What aren't they talking about?" Microservices add pressure on sophisticated technological solutions, where a monolith can get away with far less effort. Take logging for example. While a single process application may be inspectable through a file log initially, a distributed system can not.</p>

<p>Or how do you secure, that the negotiated API interfaces actually work? Integration tests of course! All neighboring services must be integrated with one another, through the network, which means a lot of of tests for a lot of of services with a lot of of communication.</p>

<p>How will developers set up the application locally? Docker containers of course! Each Service runs in its own container, comes usually with at least one storage container. Also: Somewhere is a routing configuration.</p>

<p>Scaling - contrary to common belief - is an issue too. There may be many independent services that need to be scaled appropriately to improve the overall performance of the application.</p>

<p>While all these issues are of course solvable, they will block development resources. They may delay the product significantly. They are the real <strong>cost of Microservices</strong>.</p>

<h2 id="the-php-factor">The PHP factor</h2>

<p>Actually we are developing PHP here. PHP is single threaded, shared nothing, often stateless function execution at it's heart. So when we talk about scaling we actually do not mean the application itself but the limits in the infrastructure. MySQL too slow? Use ElasticSearch! Webserver responds too slow? Put a load balancer in front of two! Horizontal scaling is actually not that hard in PHP.</p>

<p>Oh and while we are at it. The <em>Deployment Monolith Antipattern</em> is solvable through package management too. Just look at the shopware plugin store. PHP is an interpreted language, source changes in production are actually not the hardest problem.</p>

<h2 id="benefits-in-cherry-picking">Benefits in cherry picking</h2>

<p>Of course I do not want to discard the whole notion of Microservices. There is value, but there are also other options. From a technical standpoint I would argue that projects usually do not fail because the test suite was too sophisticated, the documentation too helpful, or the architecture was too clear and predictable.</p>

<p>And there are real world benefits to all of them! Good old static code analysis will help you greatly with dependency management and finally this can all be part of the global CI process.</p>

<p>And it even might be necessary to create different applications for parts of your problem. Maybe the requirements for a single part of your application are so drastically different that this becomes necessary. Feel free to use concepts from Microservices. <strong>Hybridization</strong> of architecture is not necessarily a bad thing.</p>

<p>Problem solved? Well there are still the organizational difficulties...</p>

<h2 id="alternative%3A-micro-kernel">Alternative: (Micro-)Kernel</h2>

<p>Microservices and monoliths are on opposing sides of the static dependency spectrum. While a monolith is interconnected and interdependent, a Microservice is <em>(almost)</em> not. Well this spectrum does not only consist of black and white. My favorite alternative is the kernel style. A kernel represents a core domain of an application. In our case eCommerce. This kernel then provides an extension mechanism for others to extend, alter and replace these core concepts. A plugin system if you want.</p>

<p>Apart from the basic eCommerce workflows the kernel provides the technical groundwork for all plugins to use. It contains a deployment mechanism, package management and lays the technological groundwork for the necessary infrastructure coupling. Most importantly it provides <strong>the base quality of the product as a whole</strong>.</p>

<p>In a company driven by Conways law the natural limit for a kernel is the amount of features a single team can handle. A basic runtime that shares a technical and functional base for everyone to harness. One arranges orthogonal features in orthogonal teams and creates a core, that is owned and used by everyone. The viability of this approach is proven by big and small companies alike, think operating system vendors, framework vendors and the like. There is however a critical situation when a kernel's size outgrows the team. A need for action arises. A split is necessary.</p>

<p>Conway's insight should mean that an organization in order to produce software needs to be fluid enough to support good design. So if an application changes the communication and therefore team structure needs to be changed in the best interest of the product.</p>

<h2 id="conclusion">Conclusion</h2>

<p>From a technical standpoint there is no clear benefit in using Microservices as the main application design. They just have the potential to add risk and cost to a project. In my opinion this style just complicates stuff from the get go. Sizing is a really hard problem in software and I have seen many applications, that where surprisingly large in relation to the work they actually performed. If you have a fairly simple problem to solve a single developer will be faster to fix it then twenty. Or as we say:</p>

<blockquote>
  <p>Not everybody is Netflix</p>
</blockquote>

<p>If in the past you were not able to create a good application through concepts of OOP, why would you be able to create such a thing by adding layers of indirection on top of the actual problem. If the application design rots, there is no reason to expect adding networking to the communication will help. Microservices are by no means automatically cheaper in development or maintenance than a monolith. So when investing into new technology, maybe one should rather invest in solving the actuall problems of the past, directly.</p>

<p>That's it for my rant. Thanks for reading!</p>
]]></content>
    </entry>
        <entry>
        <title type="html"><![CDATA[An easy example how to switch from classic installation to composer installation]]></title>
        <link href="https://developers.shopware.com/blog/2018/07/25/an-easy-example-how-to-switch-from-classic-installation-to-composer-installation/"/>
        <updated>2018-07-25T00:00:00+00:00</updated>
        <id>https://developers.shopware.com/blog/2018/07/25/an-easy-example-how-to-switch-from-classic-installation-to-composer-installation/</id>
        <content type="html"><![CDATA[<div class="alert alert-warning">
Before you start please make a backup of your whole shop system!
</div>

<p>In this blog post you will learn how to change your Shopware classic installation to the composer installation. I already mentioned it in the shopware <a href="https://www.youtube.com/watch?v=oUME-FnlUKE">livestream</a> (a format you should know ;-) ).</p>

<p>The requirements are very easy to fulfill. We need Shopware in the latest Version of 5.4. Nothing more.</p>

<h3 id="clean-up-classic-installation">Clean up classic installation</h3>

<p>So let's start. Please go into the shopware root directory and delete some files and directories which are no longer needed from the classic installation:</p>

<pre><code class="bash">rm -rv bin recovery vendor composer.* shopware.php
</code></pre>

<h3 id="create-composer-installation">Create composer installation</h3>

<p>Now we create a new composer project with the following command:</p>

<pre><code class="bash">composer create-project shopware/composer-project composer-installation \ 
    --no-interaction --stability=dev
</code></pre>

<p>You should receive an error message like the following because we didn't create a .env file:</p>

<pre><code class="bash">Could not load .env file
Script ./app/post-update.sh handling the post-update-cmd event returned with error code 1
</code></pre>

<h3 id="merge-classic-and-composer-installation">Merge classic and composer installation</h3>

<p>The command creates a new directory composer-installation wich contains all needed files for our composer installation. After that we have to move some files and directories stored in the new directory a level up with this commands:</p>

<pre><code class="bash">mv composer-installation/{app,bin,Plugins,vendor,composer.json,shopware.php} ./
mv composer-installation/.env.example ./.env
</code></pre>

<p>The directories <code>custom</code>, <code>files</code>, <code>media</code>, <code>themes</code>, <code>var</code> and <code>web</code> are equal with the composer installation so we can still use them and don't lose our files, plugins and themes. If you have plugins in <code>engine/Shopware/Plugins/Community</code> or <code>engine/Shopware/Plugins/Local</code> they must be moved to <code>./Plugins</code>! Now we can delete the old <code>engine</code> directory because from now on the Shopware core files will be provided by the <code>shopware/shopware</code> composer package inside the <code>vendor</code> directory.</p>

<p>After that we should reduce the .env file. Please use your database credentials from your <code>config.php</code>. If you have further config settings there move them to <code>app/config/config.php</code> and delete the <code>config.php</code> afterwards. The <code>.env</code> file should look like the following:</p>

<pre><code># Database credentials
DB_HOST=localhost
DB_DATABASE=shopware
DB_USERNAME=root
DB_PASSWORD=root
DB_PORT=3306

# This variable is checked by Shopware
DATABASE_URL=mysql://${DB_USERNAME}:${DB_PASSWORD}@${DB_HOST}:${DB_PORT}/${DB_DATABASE}

# Environment
SHOPWARE_ENV="production"
</code></pre>

<p>The next step is to set your database credentials as an environment variable. An example virtual host configuration can be found bellow:</p>

<pre><code>&lt;VirtualHost *:80&gt;
        ...
        SetEnv DB_USERNAME "root"
        SetEnv DB_PASSWORD "root"
        SetEnv DB_DATABASE "shopware"
        SetEnv DB_HOST "localhost"
        SetEnv DB_PORT "3306"
        SetEnv SHOPWARE_ENV "dev"
&lt;/VirtualHost&gt;
</code></pre>

<p>The last step is to uninstall the Shopware Auto Update Plugin. If you try an update with this Plugin, it will not work correctly and harm your Installation. You can uninstall the SwagUpdate Plugin via the following command:</p>

<pre><code class="bash">./bin/console sw:plugin:uninstall SwagUpdate
</code></pre>

<h2 id="conclusion">Conclusion</h2>

<p>The switch from classic installation to the new composer installation is not very difficult. Please use it if you want to achieve easier deployment and shopware updates. Our colleague Soner aka shyim develops an extension for the composer project to handle community store plugins as a composer dependency. If you are interested please have a look <a href="https://github.com/shyim/store-plugin-installer">here</a>.</p>
]]></content>
    </entry>
        <entry>
        <title type="html"><![CDATA[An anecdote about pair programming]]></title>
        <link href="https://developers.shopware.com/blog/2018/06/07/an-anecdote-about-pair-programming/"/>
        <updated>2018-06-07T00:00:00+00:00</updated>
        <id>https://developers.shopware.com/blog/2018/06/07/an-anecdote-about-pair-programming/</id>
        <content type="html"><![CDATA[<p>When we decided to rebuild a central piece of our Merchant Integration Architecture, I was assigned to write a new component, that handles asynchronous function calls through event queueing. 
So from the get go it was assumed that this was quite a large task. After having completed a rough prototype to interact with our queue service, I hit a problem with deciding how to proceed.
There were many paths that needed to be worked on: error handling, at least once execution, backing up the queue to our database, et cetera.
So I asked for ideas during our daily stand-up meeting, our team lead suggested to team up with a colleague who's out of work to try <a href="http://www.extremeprogramming.org/rules/pair.html">pair programming</a>.</p>

<h2 id="parallel-thinking">Parallel Thinking</h2>

<p>At first we both had doubts about the benefits of sitting at the same computer, working at the same task and fighting over the keyboard.
But we quickly realized that the thought process was streamlined even though the typing speed remained the same.</p>

<p>It's a well known fact, that in any moderately complex project or component there are many possible paths to think about. Generally this isn't a problem. 
The developer figures out a <a href="https://en.wikipedia.org/wiki/Happy_path">happy path</a> and thinks about the obvious edge cases, then they write down this path as code and add handling for the edge cases.</p>

<p>Here the first advantage of pair programming takes effect: any two people don't exactly think the same. For example: 
I tried to handle errors by writing a time stamp to the database and having an external script run periodically to re-queue eligible events. But then my coworker came up with the idea to simply use the build in delay ability of our 
queue service. This is the strength of <em>parallel thinking</em>. While I was occupied thinking how to structure my code and where to put it, he had a whole different path in mind.
And the synthesis of these two ideas turned out to be the ideal structure for our use case.</p>

<h2 id="it%27s-not-only-the-lines-of-code-that-count">It's not only the lines of code that count</h2>

<p>"Figuring out solutions together is nice but a single dev could have done it by themselves.", some of you might say.</p>

<p>But coming up with solutions, arguably the most fun part of the job, is by far not the only time sink developing software. Another significant source of delays and frustration are bugs.
And im not strictly talking about the ones being found by QA or customers, that need intensive research and tracing to fix. I mean those tiny bugs that keep the tests from succeeding and the dev from continuing their work.</p>

<p>Here pair programming helps out again. Not only can two pairs of eyes see more than one, also two brains can hold more context than one. But what is context in this case?</p>

<p>By context I mean the mental picture a developer has about the code while working on it. It consists of: 
- Landmarks (central &amp; important pieces of code)
- Call paths leading into and out of the code
- Well known pitfalls
- Limitations (real or imagined)</p>

<p>This picture may not be accurate but it's the framework in which the dev actually makes changes to the code.</p>

<p>Having two people keeping track of and building their context, instead of one, leads to many otherwise hard to find bugs being found in matter of minutes sometimes even instantly. That might sound overblown but I lost track of 
how many time as soon a local test failed one of us went "Ahh that's the problem" and fixed something that was hard to see, like this:</p>

<pre><code class="php">class Foo {

    /**
     * @var string
    **/
    private $prefix;

    /**
     * @var array
    **/
    private $config;

    /**
     * @var SomeService
    **/
    private $someService;

    /**
     * @var array
    **/
    private $stringVariations;

    public function __construct(array $config, SomeService $someService, string $prefix, string $str) 
    {
        $this-&gt;config = $config;
        $this-&gt;stringVariations = $this-&gt;createStringVariations($str);
        $this-&gt;someService = $someService;
        $this-&gt;prefix = $prefix;
    }

    private function createStringVariations(string $str): array
    {
       $arr = [];
       for($i = 1; i&lt; 5; $i++) {

           $arr[] = $this-&gt;prefix . $str . $i;
       }

       return $arr;
    }
}
</code></pre>

<p>A problem like this caused really weird behavior locally and in the failing tests, but my coworker spotted it right away:</p>

<p>The lines <code>$this-&gt;stringVariations = $this-&gt;createStringVariations($str);</code> and
<code>$this-&gt;prefix = $prefix;</code> simply had to be swapped.</p>

<p>This bug was an artifact left over from a round of refactoring that simply was not present in my mind because I worked on the <code>createStringVariations</code> method before running the tests.</p>

<p>These things make pair programming itself enjoyable and productive for the developers actively participating. But lets switch gears and talk about the effects on the team.</p>

<h2 id="islands-made-of-knowledge">Islands made of knowledge</h2>

<p>As is often the case every member of our team knows some parts of the project better than others and this is fine. But when this specialisation develops too far, it leads to pretty big problems.</p>

<p>In the extreme case the <a href="https://en.wikipedia.org/wiki/Bus_factor">bus factor</a> drops to 1 and should somebody be absent no progress can be made.
Even before the problem escalates that much, it will reduce the ability of the team to spread the work load properly.
Because not every team member can handle every task, some team members will inevitably get more work assigned than others. This can stall progress while leaving a part of the team bored.</p>

<p>Pair programming prevents this by simply involving two developers. The effects of that are obvious. My coworker and I both know the component we wrote well, and already briefed other team members on it.</p>

<h2 id="logistics-%26-agility">Logistics &amp; Agility</h2>

<p>Now for something that's well known: Most agile developers are not writing code nonstop through their workday.</p>

<p>Of course this is not a bad thing, great ideas can spring from meetings and team performance is best evaluated through dialogue between its members.</p>

<p>Nonetheless meetings are not necessarily relevant to the current task of the developer and these meetings therefore seem to stop progress for their duration.
At least in our case there were quite a few days when either I or my coworker were held up in meetings or one of us had a day off.</p>

<p>Regardless we were able to keep the pace up, because the other one of us was still free to work on the task.
This was one of the really big speedups that pair programming gave to us.</p>

<h1 id="epilogue">Epilogue</h1>

<p>Once we finished the component feedback from the team was very positive.
Together we managed to write a core component that performs well and is easy to adapt to changes.
Even though it took two developers 3 weeks to finish a task that would have taken 4 weeks by a single one   .</p>

<p>It's not only the result that convinced us to use pair programming in the future.
It also felt very productive and the steady progress throughout the development process satisfied the whole team.</p>

<p>Although this post describes the success we had with pair programming, pair programming should be seen for what it is: just another technique to help you and your team.
It may not help your team as much as it helped us. It may not be needed for the size of tasks you regularly encounter. And you may not be comfortable with taking the backseat when writing code.
Due to these very valid concerns, I think every team should judge pair programming themselves.</p>

<p>Still don't be put off at first and give a try the next time you are in a tight spot.</p>
]]></content>
    </entry>
        <entry>
        <title type="html"><![CDATA[Thoughtram Angular Master Class at Shopware]]></title>
        <link href="https://developers.shopware.com/blog/2018/03/20/thoughtram-angular-master-class-at-shopware/"/>
        <updated>2018-03-20T00:00:00+00:00</updated>
        <id>https://developers.shopware.com/blog/2018/03/20/thoughtram-angular-master-class-at-shopware/</id>
        <content type="html"><![CDATA[<p>For three days, from <strong>20th to 22nd June 2018</strong> Shopware will host an awesome event that is all about <a href="https://angularjs.org/">AngularJS</a>.</p>

<p>During these three days, you'll build a real-world Angular application, learning everything you need to call yourself an angular master! It's fun, and if you plan to do something with angular anytime soon, you definitely should join.</p>

<p>What will you learn?</p>

<ul>
<li>Components and Modules</li>
<li>Fetching data using Http</li>
<li>Advanced Dependency Injection</li>
<li>Basic Forms</li>
<li>Observables deep-dive</li>
<li>Architectural patterns</li>
<li>Component communication</li>
<li>ContentChildren and ViewChildren</li>
<li><a href="http://ngrx.github.io/"><strong>ngrx</strong></a></li>
</ul>

<p>More information about the event can be found on the thoughtram <a href="http://thoughtram.io/angular-master-class.html">website</a> and <a href="https://blog.thoughtram.io/announcements/2018/02/07/announcing-angular-master-class-at-shopware.html">blog</a>. Do yourself a favour, check it out!</p>

<p>...ok, if you've made it so far, you probably want to attend the event.</p>

<p>Tickets can be bought via <a href="https://www.eventbrite.de/e/angular-master-class-shopware-tickets-42705611634">eventbrite</a> - and you get <strong>15% off</strong>!</p>

<p>Just enter the promitional code <code>ANGULAR_SHOPWARE</code> when ordering your ticket via <a href="https://www.eventbrite.de/e/angular-master-class-shopware-tickets-42705611634">eventbrite</a>:</p>

<iframe width="100%" height="355" src="//eventbrite.de/tickets-external?eid=42705611634&amp;ref=etckt" frameborder="0" vspace="0" hspace="0" marginheight="5" marginwidth="5" scrolling="auto" allowtransparency="true"></iframe>

<p>Be quick - while I'm writing this, only 4 tickets are left!</p>
]]></content>
    </entry>
        <entry>
        <title type="html"><![CDATA[New - Get your template or developer certification online]]></title>
        <link href="https://developers.shopware.com/blog/2018/03/15/new-get-your-template-or-developer-certification-online/"/>
        <updated>2018-03-15T00:00:00+00:00</updated>
        <id>https://developers.shopware.com/blog/2018/03/15/new-get-your-template-or-developer-certification-online/</id>
        <content type="html"><![CDATA[<p>Interested in sharing your Shopware expertise with potential clients? Why not make it official - you can now take the exam to become a certified Shopware developer or template designer and developer online. Not only does a certificate increase your opportunities as a developer, but it’s proof of your expertise and ability to develop innovative solutions for Shopware. Equipped with everything you need to know to pass, our free trainings on Udemy are the perfect way to prepare for the exam. Those who are looking to become re-certified can also do so online.</p>

<p>After booking the certification, you will receive an email with a link to the test and your individual access data. You do not have to take the test straight away - you are free to determine when and where to take the exam. There are between 19 and 20 questions for each test. You can find out what minimum score is required in order to pass plus further information about the certification on our FAQ page.</p>

<p><strong><a href="https://en.shopware.com/academy/online-trainings/faq/">To the FAQ page</a></strong></p>

<p>After passing the test, your certificate will be made available for download in your account. The certificate will automatically appear in the partner listing and on your partner detail page, permitting you have an existing partner profile on the Shopware website. Your certificates help Shopware customers identify which partner is best suited for their project needs. If you are a plugin manufacturer, your certificate appears in your profile in the Community Store. Next to having an impact on your trust level, your certification affects whether your plugin qualifies for bronze, silver or gold. Every certificate is valid for 18 months. You will automatically receive a notification before your certificate is set to expire.</p>

<p><strong><a href="https://en.shopware.com/academy/online-trainings/">Register to become certified today</a></strong></p>
]]></content>
    </entry>
        <entry>
        <title type="html"><![CDATA[Free Online Course - Shopware Developer Basic Training]]></title>
        <link href="https://developers.shopware.com/blog/2018/01/31/free-online-course-shopware-developer-basic-training/"/>
        <updated>2018-01-31T00:00:00+00:00</updated>
        <id>https://developers.shopware.com/blog/2018/01/31/free-online-course-shopware-developer-basic-training/</id>
        <content type="html"><![CDATA[<p><a href="https://www.udemy.com/developer-training-basic-english"><img src="/blog/img/udemy_dev_basic_training.jpg" alt="Udemy Developer Basic Training Banner" /></a></p>

<p>Interested in learning the basics of Shopware development? Or have you always wanted to create a plugin for Shopware? You now have the opportunity to dive into the technology behind Shopware 5 in our free course on Udemy, where you’ll be taken through the fundamentals of working with one of Europe’s leading open source eCommerce platforms.</p>

<p>The course starts with setting up multiple shop configurations for different system environments and takes you through creating your first plugin from scratch. The result should serve as a foundation so that you can gradually extend the plugin by applying more knowledge throughout the remainder of the course.</p>

<p>While creating new pages and setting up a redirection for unauthenticated users, you will
cover topics like:</p>

<ul>
<li>Controllers and routing</li>
<li>Templates</li>
<li>Events</li>
<li>Using the service container</li>
</ul>

<p>Two examples will round off the course by using what you’ve learned to create a new service and implement the plugin lifecycle methods.</p>

<p>Your trainer will be Dominic Klein, Core Developer at Shopware.</p>

<p> 
<a href="https://www.udemy.com/developer-training-basic-english">Enrol now and start writing your first plugin!</a></p>
]]></content>
    </entry>
        <entry>
        <title type="html"><![CDATA[How to use Environment Variables for Plugin Configuration]]></title>
        <link href="https://developers.shopware.com/blog/2018/01/23/how-to-use-environment-variables-for-plugin-configuration/"/>
        <updated>2018-01-23T00:00:00+00:00</updated>
        <id>https://developers.shopware.com/blog/2018/01/23/how-to-use-environment-variables-for-plugin-configuration/</id>
        <content type="html"><![CDATA[<div class="alert alert-info">
Anyone who is just searching for the example source code and does not want to read the complete blog post, <a href="https://github.com/teiling88/shopware-environment-variables">here it is.</a>
</div>

<p>This blog post describes a small proof of concept how we can handle different plugin configurations for multi stage environments. I use our Paypal plugin as an example and will overwrite the two config values <code>paypalUsername</code> and <code>paypalPassword</code>.</p>

<h2 id="preparation">Preparation</h2>

<p>At first, we have to create our environment variables. For a quick test, I added the environment variables to my <code>.htaccess</code> file:</p>

<pre><code>SetEnv paypalUsername EnvPayPalUsername
SetEnv paypalPassword EnvPaypalPassword
</code></pre>

<p>I recommend for a production environment to set this kind of environment variables in your vhosts configuration file to protect you for unintentionally changes. After creating our environment variables we should make them available via the dependency injection container. 
You have to add the following lines to your config.php:</p>

<pre><code class="php">&lt;?php return [
    'db' =&gt; [...],
    'custom' =&gt;
        [
            'paypalUsername' =&gt; getenv('paypalUsername'),
            'paypalPassword' =&gt; getenv('paypalPassword'),
        ],
];
</code></pre>

<p>With this addition our environment variables are available as parameter in the %shopware.custom% array.</p>

<h2 id="plugin-installation">Plugin Installation</h2>

<p>In the last step we can install the ShopwareEnvironmentVariables plugin and extend our mapping in: <a href="https://github.com/teiling88/shopware-environment-variables/blob/master/Reader.php#L35">Reader</a> If you don't know the name of the configuration element, you can easily create a small debug statement in the Reader.php.</p>

<h1 id="conclusion">Conclusion</h1>

<p>This is a very small proof of concept how to overwrite plugin configurations by environment variables. <strong>Nothing more</strong>. You can extends this proof of concept to overwrite other configurations as well.</p>
]]></content>
    </entry>
    </feed>