Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Typical customization pitfalls in Magento 2

206 views

Published on

Author: Vlad Veselov
Presentation #1 at Magento Meetup Kharkiv 26.01.2018

Published in: Technology
  • Be the first to comment

Typical customization pitfalls in Magento 2

  1. 1. Типичные ошибки при кастомизации Magento 2 и как их избежать Спикер: Влад Веселов
  2. 2. /me 2 Vlad https://github.com/orlangur
  3. 3. Extend core classes in order to change behavior 3 http://fabien.potencier.org/pragmatism-over-theory-protected-vs-private.html https://ocramius.github.io/blog/when-to-declare-classes-final/ Many method are private, copy-paste is lesser evil
  4. 4. Extend core classes in order to add behavior 4 Do not increase core classes responsibility
  5. 5. Bad: inheritance 5 class AbstractController extends Action { // ... protected function validate( $request ) {} protected function generateHash( $request ) {} } class Edit extends AbstractController { public function execute() { $errors = $this->validate( $request ); // ... $hash = $this->generateHash( $request ); // ... } } // Smaller classes, one responsibility, more flexible, easy to understand, more testable.
  6. 6. Good: composition 6 class Edit extends Action { public function __constructor( ValidatorInterface $validator, HashGeneratorInterface $hashGenerator ) {} public function execute() { $errors = $this->validator- >validate($request); // ... $hash = $this->hashGenerator- >generateHash($request); } }
  7. 7. Entity management - EntityManager? 7 namespace MagentoFrameworkEntityManager; /** * It's not recommended to use EntityManager and its infrastructure for your entities persistence. * In the nearest future new Persistence Entity Manager would be released which will cover all the requirements for * persistence layer along with Query API as performance efficient APIs for Read scenarios. * Currently, it's recommended to use Resource Model infrastructure and make a successor of * MagentoFrameworkModelResourceModelDbAbstractDb class or successor of * MagentoEavModelEntityAbstractEntity if EAV attributes support needed. * * For filtering operations, it's recommended to use successor of * MagentoFrameworkModelResourceModelDbCollectionAbstractCollection class. */ class EntityManager {
  8. 8. Extend core entity 8 Steps to reproduce 1. Create a custom module that add a field to quote and sales_order table 2. Update the field in quote table and then place an order Expected result 1. The field value will get copied to the order table Actual result 1. The field does not get copy over to sales_order table https://github.com/magento/magento2/issues/5823
  9. 9. Extend @api interface with own fields 9 You don’t need it, really
  10. 10. Extend @api interface with core fields 10 Sometimes it may be valid but please don’t blindly fill a GitHub issue each time you meet such situation
  11. 11. 11 The standard was developed in the scope of our efforts to ensure the following: • Decouple visual (CSS) layer from the functional (JavaScript) layer. • Decouple functional (JavaScript) layer from the markup (HTML). • Reinstate emphasis on using of jQuery templates. • Reinstate emphasis on decoupling HTML, CSS and JS from PHP classes. http://devdocs.magento.com/guides/v2.0/coding-standards/code-standard-demarcation.html Code demarcation standard
  12. 12. Visual representation must rely only on HTML class attributes, CSS pseudo-classes and pseudo-elements, HTML tags, and form element’s type attribute and form elements state attributes (example: disabled, checked) 12
  13. 13. Bad 13 #header { ... } [data-action="delete"] { ... } form input[name="password"] { ... } section[role="main"] { ... } [role="menu] [role="menuitem"] { ... } [role="menu] [role="menuitem"].active { ... }
  14. 14. Good 14 .notices-wrapper { ... } .page-header:after { ... } .payment-list:first-child { ... } .caution { ... } .caution.link { ... } form input[type="password"] { ... } .control-text:focus { ... } a:hover { ... } nav li._active { ... }
  15. 15. You must not hard-code CSS styles in JavaScript files 15
  16. 16. Bad 16 this.element.on('click', function() { if ($(this).is(':visible')) { $(this).css({ visibility: 'hidden' }); } else { $(this).css({ visibility: 'visible' }); } });
  17. 17. Good 17 ... options: { hOffset: 0, myCustomElement: '[data-container="my-custom-element"]', hiddenClass: '_hidden' } ... this.element.toggleClass(this.options.hiddenClass); ... this.options.hOffset = /* calculation based on dimensions of some DOM elements within a widget */ this.element.find(this.options.myCustomElement).css({'margin-top', this.options.hOffset + 'px'}) ...
  18. 18. You must not use inline CSS styles inside HTML tags 18
  19. 19. Bad 19 <div style="display: none;"> ... </div>
  20. 20. Good 20 <div class="no-display"> ... </div>
  21. 21. Business logic must rely on only the form, form element name attributes, or data attributes 21
  22. 22. Good 22 <div id="my-widget"></div> $('#my-widget').doSomething(); $('.parent').on('click', '.button', function() { ... }); $('form').validate(); $('[role="menu"]').navigation();
  23. 23. Actually, bad 23 <div id="my-widget"></div> $('#my-widget').doSomething(); $('.parent').on('click', '.button', function() { ... }); $('form').validate(); $('[role="menu"]').navigation();
  24. 24. Really Good 24 <div data-action="delete" data-mage-init="{myWidget: [option1: 'string']}"></div> <div data-role="tooltip">More details</div> options { deleteAction: '[data-action="delete"]', tooltip: '[data-role="tooltip]' } ... this.element.find(this.options.deleteAction).on( ... ); this.element.on('click', this.options.deleteAction , function() { ... }); ... // Globally initialized widgets $( this.options.tooltip).tooltip(); // Globally for ALL tooltip elements ...
  25. 25. You must not select DOM elements based on HTML structure 25
  26. 26. Bad 26 this.element.children().children().html('hello world'); this.element.parent().find('[data-action="edit"]').data('entity_id');
  27. 27. Good 27 this.element.find('[data-action="edit"]'); this.elements.closest(‘[data-container]');
  28. 28. Don't use (arbitrary) core code for reference 28
  29. 29. Спасибо за внимание!

×