Türchen 18: Magento 2 for Magento 1 Developers

It's been one year since Magento 2.0 hit GA. This milestone for Magento was a proud moment for us and our first major action since being fully separated from eBay. It also rang the bell for Magento 1, which entered LTS through November of 2018. As it stands now, there are over 7000 Magento 2 sites and considerable buzz, interest, and critique regarding Magento 2. This post is intended to help Magento 1 developers take a first step in to Magento 2, though it should be informative to folks who are entirely new to Magento.

The essential takeaway from this post should be this: if you have strong Magento 1 experience, it should serve you well in Magento 2. Magento 2 tech improves upon it where we could. We have also introduced new concepts and technology which should feel familiar to the modern PHP developer (Composer, dependency injection, etc).

Like Magento 1, the core of a Magento 2 is PHP MVC framework. And just like Magento 1, Magento, Inc. use the architecture and conventions of the underlying framework to create the base digital commerce application, which is available as a free "Community Edition" and a licensed "Enterprise Edition" which adds functionality, scaling capacity, and enhanced core integrations appropriate for enterprise businesses.

Magento 2 offers new features and improvements over Magento 1 in the following areas:

  • Architecture & Conventions
  • Modularity
  • Configuration
  • Customization
  • Performance & Scaling
  • Systems Integration

As a Magento 1 developers review the Magento 2 filesystem and application, they will have two broad reactions:

"That Looks Familiar…"

  • Tons of out-of-the-box commerce and framework functionality
  • Multisite capability
  • Internationalization features
  • Shared themes
  • Two distinct frontends: one for customers, one for administrators
  • Modular architecture
  • MVC with proprietary ORM, powerful blocks & PHP+HTML templates, and thin controllers
  • User-configurable entities via EAV
  • Powerful layout XML for composing views
  • Configuration XML

"…What is That?!?"

  • Developer documentation
  • New module registration & activation conventions
  • Configurable dependency Injection
  • Plugins, a system for focused customization of core and community functionality; think of every public method as consumable event
  • Composer, a (the) PHP dependency manager
  • Tests: unit, integration, and functional
  • Native CLI component, an extensible tool for performing developer and ops tasks
  • Service layer, an architecture for defining extension points
  • UI components, an approach which ensures consistent design and enables efficient client-side rendering

I'll go through some of these topics below. If there is interest in other topics, please let me know via comments here, on Twitter, or at ben@magento.com.

Installation

While Magento 1 had only one official way to install (via archive), there are three methods for installing Magento 2. Most developers will want to create a project via Composer. If you want to contribute to the Magento 2 core via pull request, then you will use git clone. Another option is direct download of the metapackage, but this has limited applicability for developers. The best place for complete information on Magento 2 installation is the DevDocs section on installation. DevDocs is our developer documentation hub, which is open for contribution via pull request.

Given that Magento 2 has different system requirements for its Web stack compared to Magento 1 (especially PHP 7), and due to additional technologies used by the core (such as Varnish and Redis), many developers are turning to virtualization for their developer environments. We have an official Docker setup for developers coming out soon (email me if you want early access). There are also several community-maintained Vagrant and Docker projects. I personally use MageScotch from Joshua Warren on my MacBook Pro, and find it to be responsive and easy to maintain.

Architecture & Conventions

Magento 1 originated in 2006-07, with roots planted before Composer - before testing was in vogue, and before other cultural shifts which have given us modern PHP. In fact, some parts of Magento 1 go all the way back to the days of PHP 4, as there was originally some concern about hosting adoption of PHP 5 at the time (who remembers those days?). Magento 1's architecture was sophisticated when it was born, but these days evinces its age.

Magento 2 architecture seeks to simplify modification and integration by emphasizing true modularity via the following conventions: federated, constructor-based DI which displaces the so-called Mage god class from Magento 1; Composer-based dependency management along with semantic versioning; and an injected framework association which allows core concerns such as rendering to be replaced with the smallest footprint possible. This is by no means a complete list, nor does it describe current state for all components. The Magento 2 approach sees us more closely following the principles of SOLID, though there is still much refactoring to be done.

Versioning

In order to facilitate Composer usage in Magento 2, we employ two version numbers. There is the so-called metapackage version (e.g. 2.1.3) which is used as a marketing version. We use metapackage versions in our communications around functional, security, and bug releases. Underneath this is the so-called platform version (e.g. 102.x.x), for which we follow semantic versioning. This approach allows for extensions and customizations to better target core module versions.

Dependency Management

Composer, Composer, Composer! PHP's dependency manager is an essential tool when working with Magento 2. Core modules and libraries are associated via Composer, and Marketplace - our new extension app store - relies on Composer as well.

Modularity

Magento 2 modules have all code, configuration, and theme assets under one main folder. This is different from Magento 1, which confusingly have both PHP classes and configuration underneath a root module folder, but theme assets under a separate path. Another couple of changes from Magento 1 to Magento 2 is the loss of codepools (core, community, local) under ./app/code/, and the ability to store modules under ./app/code/ or in the ./vendor/ folder.

Regarding the two roots for Magento core code: if you are planning to contribute to the Magento 2 core, you will clone from GitHub and therefore have Magento core modules under ./app/code/; if you are doing anything else then you will likely have Magento core modules under ./vendor/. Framework code is similarly variable in location.

Decoupling & Dependency Injection

Coupling is a pervasive issue in Magento 1. Coupling comes in many forms and is a bane to both extensibility and testability. For Magento 2 we removed the Mage god class, as its global scope complicates testing and binds code into context. We've almost totally removed direct class instantiation, replacing it instead with constructor-based dependency injection and an object manager which saves us from the insidious implicit coupling that can plague constructor-based DI.

It is worth noting that the MVC framework of Magento 2 is almost entirely abstracted away from the application modules via dependency injection. The last main vestige of coupling between application and rendering framework is the abstract block class, and there is work underway to remove this dependency. There are also plans to move away from model-based CRUD in a future release of Magento 2; see our lead architect's explanation about this on Magento SE.

Configuration

Like its forebear, Magento 2 is a primarily configuration-based system (as opposed to convention-based), and the mechanism of configuration is still XML. However, there are two major improvements to Magento 2's config XML: use-based organization in multiple files and schema definitions (XSD). In Magento 1 the main module configuration file (config.xml) is a wide-open DOM for mixed multiple concerns, such as store-scoped configuration data, class name mapping, route configuration, module-specific settings, email settings. This unrestricted, unstructured approach has been a constant source of confusion while learning and cause of errors while developing. A further complication is that the execution-scope version of some parts of the DOM is derived from both the filesystem and the database!

In Magento 2 we still make ample use of XML for configuration, but to improve usability and reduce developer errors we separate XML into different files which indicate the XML's usage. For example, acl.xml contains permission node configuration only. Try to add a functionally-unrelated node to your module's acl.xml and your IDE should indicate the error. Another good example is config.xml, which now only contains default store-scoped values, all the more important given that these values are merged with DB-stored configurations.

Another dimension of improvement in config XML organization is the separation of config XML file types by area. This can typically be seen in route, event, and DI configuration. While the associated XSDs are the same, the directives in these files can be scoped according to functional areas, typically global (etc/*.xml), customer/public (etc/frontend/*.xml), and admin (etc/adminhtml/*.xml) - note that other areas exist and additional areas can be defined. This removes another level of hierarchy from the DOM structure. An additional benefit of this approach is more granular caching and in-memory performance of these structures.

Layout XML

Layout XML has evolved in Magento 2 to better serve its purpose. In addition to being covered by an XSD, it is more intuitive to understand what each element does. In Magento 1, the concept of a page is just another block, but in Magento 2 pages are now a separate element with better encapsulation of the things which are relevant to a page, such as how many columns there are. Structural blocks such as the left and right columns are similarly differentiated from functional blocks. Going up a level, the storage of these directives is now broken out by layout handle per file, which improves both overall readability and ease of determining what a given module is doing to the view in a given view scope.

Customization

An essential feature of commerce applications is the ability to be customized based on merchant requirements. One of the most exciting things about Magento 2 are the many customization mechanisms. Just like Magento 1, Magento 2 has events which the observer system which can consume in multiple scopes. Replacing one class with another still exists as well. In Magento 1 these are called rewrites and are declared in configuration XML. In Magento 2 these are called preferences and are effected via the DI system. What makes Magento 2 more extendable is the plugin system. Magento 2's plugin architecture is inspired by Aspect-Oriented Programming. It allows to declare in di.xml some class and method which will be executed before, after, or around any public Magento method. The complete syntax and explanation for Magento 2 plugins is available on DevDocs.

The benefit of plugins cannot be understated: they facilitate focused addition to or (if necessary) override of application code (whether local, core, or third-party). Magento 1 developers who have ever wanted an event where one did not exist have experienced the problem that plugins solve - especially if a class rewrite was out of the question.

Testability

Thanks to the tireless work of luminaries like Sebastian Bergmann, Chris Hartjes, and others - along with the ever-sophisticating trend of PHP development - software testing is now de rigueur in PHP. Core testability is therefore an essential concern for Magento 2 (a reality which simply doesn't exist for Magento 1). Our initial and current architectural approach is driven by the need to make classes and components testable, and you can find multiple test types in the Magento 2 core: unit, integration, and functional. Given that fact, covering your custom code with tests is not really an option anymore. While testing may be new to many Magento 1 developers, fortunately there are a number of resources to learn PHP testing in general. There are also Magento 2-specific testing resources; Vinai Kopp's Mage2katas series is a great place to start.

Contribution

Magento 2 is the ability to contribute via pull request, which was not possible in Magento 1. This took considerable retooling of how we engineer, but it has been an important part of the Magento 2 story. 2.0 was released with numerous PRs as part of mainline, and we have many, many more waiting review & merging. It is not ideal to make PRs sit in queue for so long, so we are currently putting substantial effort into both our ability to process PRs and our ability to release more frequently, so that contributions can make it into Magento 2 more quickly.

Conclusion

There is a lot more to the Magento 2 story. As mentioned earlier in the post, I am eager to hear which of the topics listed (or even additional topics) you might like me or my colleagues to write about. I hope you will take a look at Magento 2 and join this next phase in Magento's evolution.