Slide 1

Slide 1 text

PRESENTED BY JOSHUA WARREN PRESENTED AT MEET MAGENTO NEW YORK 2015 Magento 2 WORKSHOP

Slide 2

Slide 2 text

No content

Slide 3

Slide 3 text

MY EXPERIENCE

Slide 4

Slide 4 text

JoshuaWarren.com My Experience PHP Developer Since 1999 Founded Creatuity in 2008 Focused on the Magento platform Magento 2 contributor #MM15NY

Slide 5

Slide 5 text

JoshuaWarren.com early adopter of both Magento 1 and Magento 2 #MM15NY

Slide 6

Slide 6 text

JoshuaWarren.com Frequent Magento presenter #MM15NY

Slide 7

Slide 7 text

JoshuaWarren.com Led the Creatuity team in building 3 Magento 2 extensions (more on the way!) #MM15NY

Slide 8

Slide 8 text

JoshuaWarren.com Already migrating a few merchants from Magento 1 to Magento 2 #MM15NY

Slide 9

Slide 9 text

JoshuaWarren.com Wrote Writing the book on Magento 2 #MM15NY

Slide 10

Slide 10 text

A BRIEF HISTORY OF MAGENTO Photo courtesy of @YoavKutner

Slide 11

Slide 11 text

JoshuaWarren.com Just kidding - you all have heard the story of Magento 1 #MM15NY

Slide 12

Slide 12 text

JoshuaWarren.com I’ve been presenting about Magento 2 to PHP developers for a while #MM15NY

Slide 13

Slide 13 text

JoshuaWarren.com For Meet Magento, though, I’ve prepared something a bit different… #MM15NY

Slide 14

Slide 14 text

JoshuaWarren.com The hardest part for a Magento 1 developer learning Magento 2 has nothing to do with code… #MM15NY

Slide 15

Slide 15 text

JoshuaWarren.com #MM15NY

Slide 16

Slide 16 text

JoshuaWarren.com …for PHP developers new to Magento. #MM15NY

Slide 17

Slide 17 text

JoshuaWarren.com PHP developers are learning Magento 2 faster than many Magento 1 developers. #MM15NY

Slide 18

Slide 18 text

JoshuaWarren.com Approach Magento 2 with a desire to learn and understand the underlying patterns. #MM15NY

Slide 19

Slide 19 text

JoshuaWarren.com Don’t approach Magento 2 with the thought “how do I make my Magento 1 code work here” #MM15NY

Slide 20

Slide 20 text

JoshuaWarren.com Things have changed in the past eight years! #MM15NY

Slide 21

Slide 21 text

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 #MM15NY

Slide 22

Slide 22 text

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! #MM15NY

Slide 23

Slide 23 text

JoshuaWarren.com Modernizing PHP-based Ecommerce in 2007 Magento 1’s Initial Development Forces a standardized approach to extensions, database migrations, etc. Introduces patterns previously unseen in PHP (EAV, anyone?) Broke with standard practices at the time in pursuit of something better Developers flock to Magento 1 because of this #MM15NY

Slide 24

Slide 24 text

JoshuaWarren.com There’s just one problem… #MM15NY

Slide 25

Slide 25 text

JoshuaWarren.com Ecommerce development is hard. #MM15NY

Slide 26

Slide 26 text

No content

Slide 27

Slide 27 text

JoshuaWarren.com Lightly documented ecommerce development is even harder. #MM15NY

Slide 28

Slide 28 text

No content

Slide 29

Slide 29 text

JoshuaWarren.com As a community, we built documentation & tools to make Magento 1 development easier. #MM15NY

Slide 30

Slide 30 text

JoshuaWarren.com Fast forward eight years… #MM15NY

Slide 31

Slide 31 text

JoshuaWarren.com Ecommerce in 2015 Ecommerce grows by 10%/year every year - despite the Great Recession SaaS ecommerce platforms take off Responsive design & mobile commerce are the norm Ecommerce becomes a basic requirement for modern business - B2C & B2B #MM15NY

Slide 32

Slide 32 text

JoshuaWarren.com PHP in 2015 PHP 5.2 has been unsupported for 4 years Namespaces, added in PHP 5.3, didn’t exist when Magento 1 was designed Laravel, Symfony & others are bringing advanced design patterns to PHP PHP 7 is right around the corner, including scalar type hints and more #MM15NY

Slide 33

Slide 33 text

JoshuaWarren.com With all of those changes in mind, let’s dive into Magento 2… #MM15NY

Slide 34

Slide 34 text

MAGENTO 2 github.com/magento/magento2

Slide 35

Slide 35 text

JoshuaWarren.com Technologies #MM15NY

Slide 36

Slide 36 text

JoshuaWarren.com #MM15NY Composer composer create-project magento/product-community-edition --stability="beta"

Slide 37

Slide 37 text

JoshuaWarren.com Each Magento 2 module is a separate Composer package #MM15NY

Slide 38

Slide 38 text

JoshuaWarren.com PSR-0 thru PSR-4 #MM15NY

Slide 39

Slide 39 text

JoshuaWarren.com Testing built in from the start. phpunit, selenium, JMeter, Jasmine #MM15NY

Slide 40

Slide 40 text

JoshuaWarren.com HTML5, CSS3, LESS CSS Preprocessor, JQuery, RequireJS #MM15NY

Slide 41

Slide 41 text

JoshuaWarren.com Components from Zend Framework 1, Zend Framework 2, Symfony #MM15NY

Slide 42

Slide 42 text

JoshuaWarren.com Technical Architecture #MM15NY

Slide 43

Slide 43 text

JoshuaWarren.com Presentation Layer, Service Layer, Domain Layer, Persistence Layer #MM15NY

Slide 44

Slide 44 text

JoshuaWarren.com #MM15NY

Slide 45

Slide 45 text

JoshuaWarren.com Presentation Layer - views, literally and figuratively #MM15NY

Slide 46

Slide 46 text

JoshuaWarren.com Service Layer - an intermediary between the presentation and model layers #MM15NY

Slide 47

Slide 47 text

JoshuaWarren.com Service layer provides a stable, backwards-compatible interface and forms the foundation for dependency injection. #MM15NY

Slide 48

Slide 48 text

JoshuaWarren.com Domain layer - business logic, including models. Contains the implementation of service contracts. #MM15NY

Slide 49

Slide 49 text

JoshuaWarren.com Persistence Layer - resource models that perform CRUD operations on database tables. #MM15NY

Slide 50

Slide 50 text

JoshuaWarren.com Some models use a single table, others continue to use the Entity-Attribute-Value design pattern used in Magento 1. #MM15NY

Slide 51

Slide 51 text

JoshuaWarren.com Design Patterns #MM15NY

Slide 52

Slide 52 text

JoshuaWarren.com Loose Coupling #MM15NY

Slide 53

Slide 53 text

JoshuaWarren.com Dependency Injection #MM15NY

Slide 54

Slide 54 text

JoshuaWarren.com Service Contracts #MM15NY

Slide 55

Slide 55 text

JoshuaWarren.com Interceptors #MM15NY

Slide 56

Slide 56 text

JoshuaWarren.com Semantic Versioning #MM15NY

Slide 57

Slide 57 text

JoshuaWarren.com Start your Magento 2 journey learning the basics of these design patterns #MM15NY

Slide 58

Slide 58 text

DEPENDENCY INJECTION Sorry - no cool photo here, because I don’t like needles…

Slide 59

Slide 59 text

JoshuaWarren.com DI is exactly what it sounds like - injecting dependencies into the objects that need them. #MM15NY

Slide 60

Slide 60 text

JoshuaWarren.com DI is designed to reduce dependencies and promote loose coupling #MM15NY

Slide 61

Slide 61 text

JoshuaWarren.com DI makes unit testing much easier #MM15NY

Slide 62

Slide 62 text

JoshuaWarren.com Magento 2 uses the Constructor Injection pattern of DI #MM15NY

Slide 63

Slide 63 text

JoshuaWarren.com DI in Magento 2 is handled via XML files #MM15NY

Slide 64

Slide 64 text

JoshuaWarren.com #MM15NY di.xml 
 
 
 Magento_SamplePaymentProvider::form/payinstore.phtml 
 
 
 


Slide 65

Slide 65 text

INTERCEPTORS

Slide 66

Slide 66 text

JoshuaWarren.com Plugin system based on the interceptor pattern #MM15NY

Slide 67

Slide 67 text

JoshuaWarren.com Calls to almost any module can be intercepted and altered #MM15NY

Slide 68

Slide 68 text

JoshuaWarren.com Vast improvement over the rewrite pattern in Magento 1 - no more rewrite conflicts #MM15NY

Slide 69

Slide 69 text

JoshuaWarren.com #MM15NY di.xml 
 
 
 


Slide 70

Slide 70 text

JoshuaWarren.com Sort order defines order if multiple plugins intercept the same item #MM15NY

Slide 71

Slide 71 text

JoshuaWarren.com Possible to intercept before, after and around a function #MM15NY

Slide 72

Slide 72 text

JoshuaWarren.com #MM15NY ‘Before’ Interceptor class Plugin
 {
 public function beforeSetName(\Magento\Catalog\Model\Product $subject, $name)
 {
 return array('(' . $name . ')');
 }
 }

Slide 73

Slide 73 text

JoshuaWarren.com #MM15NY ‘After’ Interceptor class Plugin
 {
 public function afterGetName(\Magento\Catalog\Model\Product $subject, $result)
 {
 return '|' . $result . '|';
 }
 }

Slide 74

Slide 74 text

JoshuaWarren.com #MM15NY ‘Around’ Interceptor class Plugin
 {
 public function aroundSave(\Magento\Catalog\Model\Product $subject, \Closure $proceed)
 {
 $this->doSomethingBeforeProductIsSaved();
 $returnValue = $proceed();
 if ($returnValue) {
 $this->postProductToFacebook();
 }
 return $returnValue;
 }
 }

Slide 75

Slide 75 text

SERVICE CONTRACTS Credit to Allan MacGregor for the Soylent Green joke.

Slide 76

Slide 76 text

JoshuaWarren.com Set of interfaces to define the public API of a module #MM15NY

Slide 77

Slide 77 text

JoshuaWarren.com This API is the interface provided to other modules to access its implementation #MM15NY

Slide 78

Slide 78 text

JoshuaWarren.com Designed to hide business logic behind a stable interface #MM15NY

Slide 79

Slide 79 text

JoshuaWarren.com Service contracts + semantic versioning = minor releases will not break existing code #MM15NY

Slide 80

Slide 80 text

JoshuaWarren.com @deprecated = will be removed with the next major version release #MM15NY

Slide 81

Slide 81 text

JoshuaWarren.com #MM15NY 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);

Slide 82

Slide 82 text

JoshuaWarren.com #MM15NY 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);


Slide 83

Slide 83 text

JoshuaWarren.com Service Contracts include Data Interfaces and Service Interfaces #MM15NY

Slide 84

Slide 84 text

JoshuaWarren.com Data Interfaces return information about data entities #MM15NY

Slide 85

Slide 85 text

JoshuaWarren.com Service Interfaces handle business logic #MM15NY

Slide 86

Slide 86 text

JoshuaWarren.com Three types of service interfaces in Magento 2 (so far) #MM15NY

Slide 87

Slide 87 text

JoshuaWarren.com Repository Interfaces provide access to persistent data entities #MM15NY

Slide 88

Slide 88 text

JoshuaWarren.com CustomerRepositoryInterface, AddressRepositoryInterface, etc. #MM15NY

Slide 89

Slide 89 text

JoshuaWarren.com Repository interfaces contain the CRUD operations #MM15NY

Slide 90

Slide 90 text

JoshuaWarren.com Management interfaces contain management functions not related to repositories #MM15NY

Slide 91

Slide 91 text

JoshuaWarren.com Validators, createAccount, changePassword, etc #MM15NY

Slide 92

Slide 92 text

JoshuaWarren.com Metadata interfaces provide meta information - primarily about custom attributes #MM15NY

Slide 93

Slide 93 text

EXTENDING MAGENTO 2

Slide 94

Slide 94 text

JoshuaWarren.com Create your basic module file structure #MM15NY

Slide 95

Slide 95 text

JoshuaWarren.com #MM15NY App/Code/// composer.json etc/module.xml Test/Unit/

Slide 96

Slide 96 text

JoshuaWarren.com #MM15NY 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" ] ] } }

Slide 97

Slide 97 text

JoshuaWarren.com #MM15NY etc/module.xml

Slide 98

Slide 98 text

JoshuaWarren.com Optional config files in etc: acl.xml config.xml di.xml webapi.xml #MM15NY

Slide 99

Slide 99 text

JoshuaWarren.com acl.xml defines new items for Magento’s ACL system #MM15NY

Slide 100

Slide 100 text

JoshuaWarren.com Config.xml adds new configuration options #MM15NY

Slide 101

Slide 101 text

JoshuaWarren.com Webapi.xml defines items to expose via the REST or SOAP APIs #MM15NY

Slide 102

Slide 102 text

JoshuaWarren.com Optional subdirectories in etc: adminhtml frontend webapi_rest webapi_soap #MM15NY

Slide 103

Slide 103 text

JoshuaWarren.com Items in the main etc directory apply globally to your extension #MM15NY

Slide 104

Slide 104 text

JoshuaWarren.com Items in the 4 subdirectories apply only to that area - i.e., adminhtml only applies to the Magento backend #MM15NY

Slide 105

Slide 105 text

JoshuaWarren.com Optional subdirectories: API Block Controller Helper Model #MM15NY

Slide 106

Slide 106 text

JoshuaWarren.com Optional subdirectories: Plugin Setup Ui i18n view #MM15NY

Slide 107

Slide 107 text

JoshuaWarren.com API contains any new service contracts your extension adds #MM15NY

Slide 108

Slide 108 text

JoshuaWarren.com Plugin contains any interceptors your extension defines #MM15NY

Slide 109

Slide 109 text

JoshuaWarren.com UI is for Magento 2’s new Magento UI library #MM15NY

Slide 110

Slide 110 text

JoshuaWarren.com I18n contains internationalization files - CSV files defining the translations for your strings #MM15NY

Slide 111

Slide 111 text

JoshuaWarren.com If your extension doesn’t need one of these items, just omit that folder #MM15NY

Slide 112

Slide 112 text

JoshuaWarren.com Sample: custom shipping method to allow for in-store pickup from several locations #MM15NY

Slide 113

Slide 113 text

JoshuaWarren.com #MM15NY 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();
 }
 }

Slide 114

Slide 114 text

JoshuaWarren.com #MM15NY 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;
 }


Slide 115

Slide 115 text

JoshuaWarren.com #MM15NY 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;
 }
 }

Slide 116

Slide 116 text

JoshuaWarren.com #MM15NY 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 


Slide 117

Slide 117 text

JoshuaWarren.com model/carrier.php contains all of the functions a shipping carrier must have in Magento 2 #MM15NY

Slide 118

Slide 118 text

JoshuaWarren.com GetAllowedMethods CollectRates GetLocationInfo BuildRateForLocation GetLocations GetShippingOrigin #MM15NY

Slide 119

Slide 119 text

JoshuaWarren.com #MM15NY Etc/Adminhtml/System.xml 
 
 
 In-Store Pickup
 
 Enabled
 Magento\Config\Model\Config\Source\Yesno
 
 Warning: Shipping Origin should be configured to use this method.]]>
 
 
 
 Title
 
 […]

Slide 120

Slide 120 text

JoshuaWarren.com #MM15NY Etc/Frontend/di.xml 
 
 
 
 


Slide 121

Slide 121 text

JoshuaWarren.com #MM15NY Etc/Module.xml 
 
 


Slide 122

Slide 122 text

JoshuaWarren.com #MM15NY 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" ] ] } }

Slide 123

Slide 123 text

JoshuaWarren.com We now have a complete, functioning in-store-pickup shipping extension for Magento 2 #MM15NY

Slide 124

Slide 124 text

JoshuaWarren.com Take a look at the Test/Unit directory on Github for tests for this extension #MM15NY

Slide 125

Slide 125 text

JoshuaWarren.com Magento 2 unit testing includes mocking, fixtures, etc. - everything you need for TDD #MM15NY

Slide 126

Slide 126 text

LEARNING MORE Don’t end up like this guy ->

Slide 127

Slide 127 text

JoshuaWarren.com devdocs.magento.com magento.stackexchange.com/questions/tagged/magento2 https://github.com/magento/magento2-samples #MM15NY

Slide 128

Slide 128 text

JoshuaWarren.com Magento U Courses Fundamentals of Magento 2 Development Front-end Course #MM15NY

Slide 129

Slide 129 text

JoshuaWarren.com AlanStorm.com AlanKent.me CoderOnCode.com #MM15NY

Slide 130

Slide 130 text

JoshuaWarren.com Upcoming events: ZendCon, php[world] #MM15NY

Slide 131

Slide 131 text

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 #MM15NY

Slide 132

Slide 132 text

JoshuaWarren.com As an in-house developer for a merchant… Learning Magento 2 Determine when your business is likely to migrate to Magento 2 Start your Magento 2 migration schedule with 2-4 weeks of time dedicated to learning Magento 2 Learn the patterns before you start! #MM15NY

Slide 133

Slide 133 text

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 #MM15NY

Slide 134

Slide 134 text

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! #MM15NY

Slide 135

Slide 135 text

JoshuaWarren.com Programming With Magento 2 coming to amazon.com & phparch.com #MM15NY

Slide 136

Slide 136 text

Keep in Touch! @JoshuaSWarren JoshuaWarren.com Mage2DevBook.com

Slide 137

Slide 137 text

JoshuaWarren.com #MM15NY