Magento 2 - An Intro to a Modern PHP-Based System - ZendCon 2015

Magento 2 - An Intro to a Modern PHP-Based System - ZendCon 2015

Newly updated version of my Magento 2 intro talk - make sure to refer to this one, not the older ones!

Over 200,000 companies use the Magento 1 platform to power their eCommerce needs. So when they set out to build a major new version, the Magento team had significant pressure to deliver a modern, well-designed PHP-based system. Pulling in some of the best of the PHP world through tools like Composer, phpunit and more, I believe they met that goal. In this talk, we’ll take a look at the design and architecture of Magento 2, including it’s use of dependency injections, interceptors and service contracts to provide numerous ways for developers to extend and customize the system.

Presented at ZendCon 2015.

8a2e3b7e9a3e4037934e5680e16e53e1?s=128

Joshua Warren

October 21, 2015
Tweet

Transcript

  1. 1.

    PRESENTED BY JOSHUA WARREN PRESENTED AT ZENDCON 2015 Magento 2

    AN INTRODUCTION TO A MODERN PHP- BASED SYSTEM
  2. 2.
  3. 3.

    JoshuaWarren.com 150 slides in ~50 minutes lots of code focus

    on the concepts, download the slides later #ZendCon
  4. 5.

    JoshuaWarren.com My Experience PHP Developer Since 1999 Founded Creatuity in

    2008 Focused on the Magento platform Magento 2 contributor #ZendCon
  5. 8.
  6. 11.

    JoshuaWarren.com Not a Magento employee, but working closely with the

    development, documentation & product teams on Magento 2 #ZendCon
  7. 14.

    JoshuaWarren.com A look at the state of the art when

    Magento 1 was built PHP & Ecommerce in 2007 osCommerce is state of the art Cloud-based / SaaS ecommerce doesn’t exist yet PHP 5.2 is cutting-edge Composer doesn’t exist - PHP has no dependency management There’s this new thing called ZF, otherwise it’s Cake or Symfony Testing? You might find a few people using PHPUnit #ZendCon
  8. 15.

    JoshuaWarren.com The Painful World of osCommerce PHP & Ecommerce in

    2007 Want to add an attribute? Modify your database schema on live. Looking at add new features? Modify core PHP files. Want to upgrade your store? Good luck! #ZendCon
  9. 19.

    JoshuaWarren.com Attracted by Magento’s free, open- source approach, hundreds of

    thousands of sites were launched using Magento 1 #ZendCon
  10. 22.
  11. 24.
  12. 27.

    JoshuaWarren.com Now the most widely-used eCommerce platform, powering over 250,000

    sites, expectations are high for the Magento 2 team. #ZendCon
  13. 29.

    JoshuaWarren.com Internal priorities continue to shift, and finally at the

    end of 2014, Magento 2 development is made public on Github. #ZendCon
  14. 30.

    JoshuaWarren.com Magento commits to a release schedule for Magento 2,

    and announces the acceptance of pull requests. #ZendCon
  15. 35.

    JoshuaWarren.com Magento 2 team has committed to quarterly releases. I’m

    targeting the Q1 2016 release for more cautious brands. #ZendCon
  16. 41.

    JoshuaWarren.com Approach Magento 2 with a desire to learn and

    understand the underlying patterns. #ZendCon
  17. 42.

    JoshuaWarren.com Don’t approach Magento 2 with the thought “how do

    I make my Magento 1 code work here” #ZendCon
  18. 58.
  19. 60.

    JoshuaWarren.com Some models use a single table, others continue to

    use the Entity-Attribute-Value design pattern used in Magento 1. #ZendCon
  20. 69.

    JoshuaWarren.com DI is exactly what it sounds like - injecting

    dependencies into the objects that need them. #ZendCon
  21. 74.

    JoshuaWarren.com #ZendCon di.xml <config xmlns:xsi=“[…]” xsi:noNamespaceSchemaLocation=“[…]”>
 <virtualType name="Magento\SamplePaymentProvider\Block\Form\Payinstore" type="Magento\Payment\Block\Form" shared="false">

    <arguments>
 <argument name="data" xsi:type="array">
 <item name="template" xsi:type=“string"> Magento_SamplePaymentProvider::form/payinstore.phtml </item>
 </argument>
 </arguments>
 </virtualType>
 </config>
  22. 84.

    JoshuaWarren.com #ZendCon ‘Around’ Interceptor class Plugin
 {
 public function aroundSave(\Magento\Catalog\Model\Product

    $subject, \Closure $proceed)
 {
 $this->doSomethingBeforeProductIsSaved();
 $returnValue = $proceed();
 if ($returnValue) {
 $this->postProductToFacebook();
 }
 return $returnValue;
 }
 }
  23. 91.

    JoshuaWarren.com #ZendCon CustomerRepositoryInterface.php 
 namespace Magento\Customer\Api;
 /**
 * Customer CRUD

    interface.
 */
 interface CustomerRepositoryInterface
 {
 /**
 * Create customer.
 *
 * @api
 * @param \Magento\Customer\Api\Data\CustomerInterface $customer
 * @param string $passwordHash
 * @return \Magento\Customer\Api\Data\CustomerInterface
 * @throws \Magento\Framework\Exception\InputException If bad input is provided
 * @throws \Magento\Framework\Exception\State\InputMismatchException If the provided email is already used
 * @throws \Magento\Framework\Exception\LocalizedException
 */
 public function save(\Magento\Customer\Api\Data\CustomerInterface $customer, $passwordHash = null);
  24. 92.

    JoshuaWarren.com #ZendCon CustomerRepositoryInterface.php /**
 * Retrieve customer.
 *
 * @api


    * @param string $email
 * @param int|null $websiteId
 * @return \Magento\Customer\Api\Data\CustomerInterface
 * @throws \Magento\Framework\Exception\NoSuchEntityException If customer with the specified email does not exist.
 * @throws \Magento\Framework\Exception\LocalizedException
 */
 public function get($email, $websiteId = null);
 /**
 * Retrieve customer.
 *
 * @api
 * @param int $customerId
 * @return \Magento\Customer\Api\Data\CustomerInterface
 * @throws \Magento\Framework\Exception\NoSuchEntityException If customer with the specified ID does not exist.
 * @throws \Magento\Framework\Exception\LocalizedException
 */
 public function getById($customerId);

  25. 103.

    JoshuaWarren.com Most service contracts are in the Api folder -

    but not all. There are SPIs annotated with @Api but in the Model folder, not Api #ZendCon
  26. 105.

    JoshuaWarren.com Check out the Magento 2 sample extensions - 12

    official samples, including 1 theme #ZendCon
  27. 108.

    JoshuaWarren.com #ZendCon Composer.json { "name": "joshuaswarren/sample-module-minimal", "description": "A minimal sample

    Magento 2 module", "type": "magento2-module", "version": "1.0.0", "license": [ "OSL-3.0", "AFL-3.0" ], "require": { "php": "~5.5.0|~5.6.0", "magento/magento-composer-installer": "*" }, "extra": { "map": [ [ "*", "joshuaswarren/SampleMinimal" ] ] } }
  28. 110.

    JoshuaWarren.com #ZendCon NEW! Registration.php As of last week, Magento 2

    modules need a registration.php file - this allows modules to live in vendor directory
  29. 118.

    JoshuaWarren.com Items in the 4 subdirectories apply only to that

    area - i.e., adminhtml only applies to the Magento backend #ZendCon
  30. 127.

    JoshuaWarren.com #ZendCon Block/System/Config/Form/Field/Locations.php namespace Magento\SampleShippingProvider\Block\System\Config\Form\Field;
 use Magento\Config\Block\System\Config\Form\Field\FieldArray\AbstractFieldArray;
 /**
 * Backend

    system config array field renderer
 */
 class Locations extends AbstractFieldArray
 {
 /**
 * Initialise columns for 'Store Locations'
 *
 * @return void
 */
 protected function _construct()
 {
 $this->addColumn('title',
 ['label' => __('Title'), 'class' => 'validate-no-empty validate-alphanum-with-spaces']);
 $this->addColumn('street',
 ['label' => __('Street Address'), 'class' => 'validate-no-empty validate-alphanum-with-spaces']);
 $this->addColumn('phone',
 ['label' => __('Phone Number'), 'class' => 'validate-no-empty validate-no-empty validate-phoneStrict']);
 $this->addColumn('message',
 ['label' => __('Message'), 'class' => 'validate-no-empty']);
 $this->_addAfter = false;
 parent::_construct();
 }
 }
  31. 128.

    JoshuaWarren.com #ZendCon Model/Type/Plugin/Onepage.php [1/2] namespace Magento\SampleShippingProvider\Model\Type\Plugin;
 use Magento\Checkout\Model\Type\Onepage as CheckoutOnePage;


    use Magento\SampleShippingProvider\Model\Carrier;
 /**
 * Change Shipping Address to selected Store location address
 */
 class Onepage
 {
 /**
 * @var Carrier
 */
 private $carrier;
 /**
 * @param Carrier $carrier
 */
 public function __construct(Carrier $carrier)
 {
 $this->carrier = $carrier;
 }

  32. 129.

    JoshuaWarren.com #ZendCon Model/Type/Plugin/Onepage.php [2/2] /**
 * Replace shipping address with

    pickup location address
 * @param CheckoutOnePage $subject
 * @param array $result
 * @return $this
 */
 public function afterSaveShippingMethod(CheckoutOnePage $subject, array $result)
 {
 if ($result) {
 return $result;
 }
 $quote = $subject->getQuote();
 $shippingAddress = $quote->getShippingAddress();
 $shippingMethod = $shippingAddress->getShippingMethod();
 /**
 * In-Store pickup selected
 * Update Shipping Address
 */
 if (strpos($shippingMethod, $this->carrier->getCarrierCode()) !== false) {
 $locationAddress = $this->carrier->getLocationInfo($shippingMethod);
 $shippingAddress->setCountryId($locationAddress['country_id']);
 $shippingAddress->setRegionId($locationAddress['region_id']);
 $shippingAddress->setPostcode($locationAddress['postcode']);
 $shippingAddress->setCity($locationAddress['city']);
 $shippingAddress->setStreet($locationAddress['street']);
 $shippingAddress->setTelephone($locationAddress['phone']);
 }
 return $result;
 }
 }
  33. 130.

    JoshuaWarren.com #ZendCon Model/Carrier.php namespace Magento\SampleShippingProvider\Model;
 use Psr\Log\LoggerInterface;
 use Magento\Framework\App\Config\ScopeConfigInterface;
 use

    Magento\Store\Model\ScopeInterface;
 use Magento\Shipping\Model\Carrier\AbstractCarrier;
 use Magento\Shipping\Model\Carrier\CarrierInterface;
 use Magento\Shipping\Model\Config;
 use Magento\Shipping\Model\Rate\ResultFactory;
 use Magento\Quote\Model\Quote\Address\RateResult\MethodFactory;
 use Magento\Quote\Model\Quote\Address\RateResult\ErrorFactory;
 /**
 * In-Store Pickup shipping model
 */
 class Carrier extends AbstractCarrier implements CarrierInterface
 {
 /**
 * @var string
 */
 protected $_code = 'storepickup';
 /**
 * @var bool
 */
 protected $_isFixed = true; … see https://github.com/magento/magento2-samples/blob/master/sample-module-shipping-provider/Model/Carrier.php 

  34. 133.

    JoshuaWarren.com #ZendCon Etc/Adminhtml/System.xml <system>
 <section id="carriers">
 <group id="storepickup" translate="label" type="text"

    sortOrder="10" showInDefault="1" showInWebsite="1" showInStore="1">
 <label>In-Store Pickup</label>
 <field id="active" translate="label" type="select" sortOrder="1" showInDefault="1" showInWebsite="1" showInStore="1">
 <label>Enabled</label>
 <source_model>Magento\Config\Model\Config\Source\Yesno</source_model>
 <comment>
 <![CDATA[<strong style="color:red">Warning</strong>: Shipping Origin should be configured to use this method.]]>
 </comment>
 </field>
 <field id="title" translate="label" type="text" sortOrder="2" showInDefault="1" showInWebsite="1" showInStore="1">
 <label>Title</label>
 </field>
 […]
  35. 136.

    JoshuaWarren.com #ZendCon Composer.json { "name": "magento/sample-module-shipping-provider", "description": "Demonstrate Shipping Provider",

    "type": "magento2-module", "version": "1.0.0", "license": [ "OSL-3.0", "AFL-3.0" ], "require": { "php": "~5.5.0|~5.6.0", "magento/magento-composer-installer": "*", "magento/framework": "~0.74", "magento/module-store": "~0.74", "magento/module-shipping": "~0.74", "magento/module-quote": "~0.74", "magento/module-checkout": "~0.74" }, "extra": { "map": [ [ "*", "Magento/SampleShippingProvider" ] ] } }
  36. 138.
  37. 140.

    JoshuaWarren.com Dev Docs includes a great ‘How Do I’ on

    the Magento Testing Framework and testing in Magento 2 #ZendCon
  38. 143.

    Dev Docs Team of hard-working technical writers (not developers) Writing

    documentation for a system that has yet to be used ‘in the wild’ Very eager for feedback and input - they don’t know what documentation you need Very open to pull requests of documentation or just open an issue on Github with feedback + requests JoshuaWarren.com #ZendCon
  39. 147.

    JoshuaWarren.com As a freelancer… Learning Magento 2 Set aside time

    in your week to learn the design patterns Magento 2 uses Work through the sample code the Magento 2 team has provided Begin experimenting with developing with Magento 2 Do not try to learn ‘on the job’ - be careful accepting M2 work before you’re ready #ZendCon
  40. 148.

    JoshuaWarren.com As an in-house developer for a merchant… Learning Magento

    2 Determine when your business is likely to migrate to Magento 2 First 2-4 weeks of your Magento 2 migration schedule should be learning Magento 2 Learn the patterns before you start! #ZendCon
  41. 149.

    JoshuaWarren.com As an agency or industry partner… Learning Magento 2

    Create a tiger team of developers focused on Magento 2 Allow those developers time in the day to learn Magento 2 Those developers should implement your first Magento 2 projects That team then helps the rest of your team through the learning curve #ZendCon
  42. 150.

    JoshuaWarren.com When do I need to be Magento 2 ready?

    Learning Magento 2 Magento 2 will be released late enough in the year that most merchants won’t begin using it immediately. Merchants will also wait until their mission-critical extensions are available on Magento 2. Start learning it now - but don’t panic! #ZendCon