Magento 2.0 GA was released this past Tuesday. This new major release of the well-known Magento eCommerce platform incorporates modern design practices, breathing new life into a steadily growing platform. Whether you’ve been working with Magento 1 for the last few years or are completely new to Magento, come and learn about the new and exciting aspects of Magento 2. You will be presented with an overview of the system architecture, shown some of the various ways to extend the system, and walk away ready to use Magento for your next eCommerce project.
2. Fundamentals of Extending Magento 2 @blackbooker / #phpworld
My Experience
Magento developer since early 2009
Magento 1 & 2 contributor
GitHub Community Moderator
Director of Technology at Classy Llama
2
4. Fundamentals of Extending Magento 2 @blackbooker / #phpworld
Technology Stack
PHP 5.6.x or 5.5.x*
PSR-0 through PSR-4
HTML5 & CSS3 w/LESS
JQuery w/RequireJS
3PLs ZF1, ZF2 and Symfony
Apache 2.2, 2.4 / Nginx 1.8
MySQL 5.6
Composer meta-packages
*There are known issues with 5.5.10–5.5.16 and 5.6.0
Optional components:
• Varnish as a cache layer
• Redis for sessions or page caching
• Solr (search engine)
4
5. Fundamentals of Extending Magento 2 @blackbooker / #phpworld
Backwards Compatibility
SemVer 2.0 policy for PHP code
Version numbers in MAJOR.MINOR.PATCH format
• MAJOR indicates incompatible API changes
• MINOR where added functionality is backward-compatible
• PATCH for backward-compatible bug fixes
Guaranteed BC for code with @api annotations
@deprecated annotations with ~1yr later removal
5
6. Fundamentals of Extending Magento 2 @blackbooker / #phpworld
Strongly Layered
Presentation layer to provide view components
Service layer defined interfaces for integrating with logic
Domain layer to provide core business logic and base functionality
Persistence layer using an active record pattern to store data
6
7. Fundamentals of Extending Magento 2 @blackbooker / #phpworld
Magento Components
Modules support major functionality and behavior
Themes implement the interface users interact with
Language packs to support i18n
Vendor libraries such as ZF1, ZF1 & Symfony
7
8. Fundamentals of Extending Magento 2 @blackbooker / #phpworld
Breaking it Down
MagentoFramework
• provides common libraries such as FS, Events, OM, etc
• core application behavior such as routing
• does not "know" about anything outside of itself
VendorLibrary similar to framework, don't re-invent
Modules,Themes & Language Packs
• areas you as a developer will be working with
• may fall into either of 2 categories: required or optional
8
10. Fundamentals of Extending Magento 2 @blackbooker / #phpworld
Dependency Injection
Implements the constructor injection pattern
Dependencies may be provided automatically
Some injected dependencies must be set in XML
This completely replaces the "Mage" god class in 1.x
Class dependencies can be replaced via module config
10
11. @blackbooker / #phpworldFundamentals of Extending Magento 2
Injecting an Interface
class Norf
{
protected $bar;
public function __construct(BarInterface $bar) {
$this->bar = $bar;
parent::__construct();
}
}
11
13. @blackbooker / #phpworldFundamentals of Extending Magento 2
DI Proxies
<type name="FooBarModelBaz" shared="false">
<arguments>
<argument name="norf" xsi:type="object">FooBarModelNorf</argument>
</arguments>
</type>
13
14. @blackbooker / #phpworldFundamentals of Extending Magento 2
Plugins
Plugins work using technique called interception
They are implemented in context of a module
You write your plugins; interceptor code is generated
Can wrap around, be called before/after class methods
14
http://devdocs.magento.com/guides/v2.0/extension-dev-guide/plugins.html
16. @blackbooker / #phpworldFundamentals of Extending Magento 2
Intercepting Before
class Qux
{
public function beforeSetBaz(Norf $subject, $baz)
{
// modify baz
return [$baz];
}
}
16
Plugin/Qux.php
17. @blackbooker / #phpworldFundamentals of Extending Magento 2
Intercepting After
class Qux
{
public function afterGetBaz(Norf $subject, $result)
{
// modify result
return $result;
}
}
17
Plugin/Qux.php
18. @blackbooker / #phpworldFundamentals of Extending Magento 2
Wrapping Around
class Qux
{
public function aroundBaztastic(Norf $subject, Closure $proceed)
{
// do something before
$result = $proceed();
if ($result) {
// do something really cool
}
return $result;
}
}
18
Plugin/Qux.php
19. Fundamentals of Extending Magento 2 @blackbooker / #phpworld
Where can you Plugin?
Anywhere except for…
• final methods / classes
• non-public methods
• class methods
• __construct
19
http://devdocs.magento.com/guides/v2.0/extension-dev-guide/plugins.html
20. Fundamentals of Extending Magento 2 @blackbooker / #phpworld
Code Generation
Auto-generates code to create non-existent classes
This is based on convention such as *Factory classes
You can still see and debug the code in var/generation
In development mode these are created in autoloader
Production mode expects pre-compilation via CLI tool
20
21. Fundamentals of Extending Magento 2 @blackbooker / #phpworld
Factory Pattern
Single purpose objects used to create object instances
Isolate the object manager from business logic
Instead of injecting ObjectManager, use a *Factory
Uniform pattern interface since they are generated
21
22. @blackbooker / #phpworldFundamentals of Extending Magento 2
BaseFactory
class BaseFactory
{
protected $objectManager;
public function __construct(ObjectManager $objectManager)
{
$this->objectManager = $objectManager;
}
public function create($sourceData = null)
{
return $this->objectManager->create('Base', ['sourceData' => $sourceData]);
}
}
22
23. @blackbooker / #phpworldFundamentals of Extending Magento 2
Using a Factory
class Norf
{
protected $barFactory;
public function __construct(BarFactory $barFactory) {
$this->barFactory = $barFactory;
parent::__construct();
}
/** returns Bar object instantiated by object manager */
public function createBar() {
return $this->barFactory->create();
}
}
23
24. Fundamentals of Extending Magento 2 @blackbooker / #phpworld
Component Management
All components installed via composer
Register component so Magento knows it's there
Composer auto-loader used to load registration.php
Any app/code/*/*/registration.php loaded in bootstrap
24
25. @blackbooker / #phpworldFundamentals of Extending Magento 2
Component Registration
use MagentoFrameworkComponentComponentRegistrar;
ComponentRegistrar::register(ComponentRegistrar::MODULE, 'Foo_Bar', __DIR__);
25
registration.php
29. Fundamentals of Extending Magento 2 @blackbooker / #phpworld
Which install method?
Getting the source
• Complete tarball
• Composer meta-packages
• GitHub clone
App installation
• Command line `bin/magento` tool
• GUI wizard
29
http://devdocs.magento.com/guides/v2.0/install-gde/continue.html
30. Fundamentals of Extending Magento 2 @blackbooker / #phpworld
Installing from GitHub
Used to contribute back to core via PRs
Sample data may still be installed, but messier
30
32. Fundamentals of Extending Magento 2 @blackbooker / #phpworld
Installing via Composer
Use of meta-packages provide you more control
Clear separation between custom / vendor code
Sample data is a snap to install
Best method to use for site builds and other projects
32
33. @blackbooker / #phpworldFundamentals of Extending Magento 2
Installing via Composer
$ cd /sites
$ composer create-project --repository-url=https://repo.magento.com/
magento/project-community-edition m2.demo
$ cd m2.demo
$ chmod +x bin/magento
$ bin/magento sampledata:deploy
$ composer update # this line here because bugs... fix on it's way
$ mysql -e 'create database m2_demo'
$ bin/magento setup:install --base-url=http://m2.demo --backend-frontname=backend
--admin-user=admin --admin-firstname=Admin --admin-lastname=Admin
--admin-email=user@example.com --admin-password=A123456
--db-host=dev-db --db-user=root --db-name=m2_demo
33
bit.ly/1H8P249
34. Fundamentals of Extending Magento 2 @blackbooker / #phpworld
Installing for Shared Hosting
Tarballs for "easy" install method on shared hosting
Essentially same code produced via composer install
Can be readily used where CLI access is not to be had
After install can be maintained with composer
34
44. @blackbooker / #phpworldFundamentals of Extending Magento 2
Example Block
namespace AlgerSkeletonBlock;
use AlgerSkeletonHelperBar;
use MagentoFrameworkViewElementTemplate;
use MagentoFrameworkViewElementTemplateContext;
class Norf extends Template {
protected $bar;
public function __construct(Bar $bar, Context $context, array $data = []) {
$this->bar = $bar;
parent::__construct($context, $data);
}
public function getDrinksCallout() {
return 'Helper your self to an ' . implode(' or a ', $this->bar->getDrinks()) . '!';
}
}
44
Block/Norf.php
45. @blackbooker / #phpworldFundamentals of Extending Magento 2
Using the Block
<?xml version="1.0"?>
<page xmlns:xsi="..." xsi:noNamespaceSchemaLocation="...">
<body>
<referenceContainer name="page.top">
<block class="AlgerSkeletonBlockNorf"
template="Alger_Skeleton::banner.phtml"/>
</referenceContainer>
</body>
</page>
45
https://github.com/davidalger/phpworld-talk2
46. @blackbooker / #phpworldFundamentals of Extending Magento 2
Unit Testing
namespace AlgerSkeletonTestUnit;
use MagentoFrameworkTestFrameworkUnitHelperObjectManager;
class HelperTest extends PHPUnit_Framework_TestCase {
protected $object;
protected function setUp() {
$this->object = (new ObjectManager($this))->getObject('AlgerSkeletonHelperBar');
}
/** @dataProvider pourDrinkDataProvider */
public function testPourDrink($brew, $expectedResult) {
$this->assertSame($expectedResult, $this->object->pourDrink($brew));
}
public function pourDrinkDataProvider() {
return [['Sam', 'Adams'], ['Blue', 'Moon']];
}
}
46
https://github.com/davidalger/phpworld-talk2
47. @blackbooker / #phpworldFundamentals of Extending Magento 2
Running our Test
$ cd dev/tests/unit
$ phpunit ../../../app/code/Alger/Skeleton/
PHPUnit 4.8.5 by Sebastian Bergmann and contributors.
..
Time: 235 ms, Memory: 15.00Mb
OK (2 tests, 2 assertions)
47
50. @blackbooker / #phpworldFundamentals of Extending Magento 2
Running from Anywhere
#!/usr/bin/env bash
dir="$(pwd)"
while [[ "$dir" != "/" ]]; do
if [[ -x "$dir/bin/magento" ]]; then
"$dir/bin/magento" "$@"
exit $?
fi
dir="$(dirname "$dir")"
done
>&2 echo "Error: Failed to locate bin/magento (you probably are not inside a magento site root)"
50
bit.ly/215EOYR — /usr/local/bin/magento