2

Very often it is needed to add some custom logic to templates. For example it can be checking if customer is logged or some information about product - if it's already bought by current customer or if it's already in cart. The thing is how to do it in best way. There are many many ways to do it. Of course I am not wondering if it should be done in custom module or in theme, because it depends if it's more universal issue or just something needed only in theme.

First of all you can do it just writing some php code in your templates, but of course it not elegant and makes a real mess in your code.

Second way is to make preference on block, which is connected with templates we want to 'extend', but here comes drawbacks of overriding core files and in case that our functionality is needed in many places it's not efficient to override multiple blocks. Can't be used just for one theme, so it can break another ones if made in module for only one theme needs.

Third possible manner is to make a plugin on desired method and it works fine as long as it is not completely custom logic that needs some separate classes. So it can be achieved like this in many cases. Can't be used just for one theme, so it can break another ones if made in module for only one theme needs.

Fourth idea is to create new block, not necessarily with custom template. It can be just container for bunch of php methods. It can be easily added in any template using layout xmls and getChildBlock() method inside phtml. Although I am not sure if it is efficient to do it like this.

Last way I have figured out is to create custom helper classes, which can be easily called in any template just by using $this->helper('path\to\class') It is more portable way to add some logic, although helper needs to extend from it's abstract parent, so I am not sure here if it efficient. Also helper classes are discouraged from using, as not suiting anythin well, so code seems to be not well planned.

Has anyone well-checked way to achieve that? I would be extremely useful to hear points for any of these way, as well as discovering new ways to achieve that.

1

The "right" way depends on what you are trying to achieve. Also keep in mind, that in many places, magento2 itself does not follow it's best practices (hopefully yet)

I'll try to answer by writing something to each point in your question

First: Templates should only contain view logic. So mostly just ifs, foreaches and function calls on the block. If you find yourself needing more then 1 line of php code to output the next line of html it could be probably done better.

Second: Setting a preference can be very powerful but also very dangerous since you can change the behavior of each class globally. This might be causing side effects in places you don't think about.

Third: Plugins are a great way to change the behavior of a single public method. Keep in mind that you are also changing the method globally and you should always keep the original method call since other plugins might access the method, too.

Fourth: This is the safest way if you want to add functionality and the best way if you want to add it for a specific theme. You can remove the original block from the layout and add your custom block. This will ensure, that your new logic is only executed for your specific use case

Last: I would really recommend NOT to use the helper function and I honestly hope that this will be removed in the future. It can be pretty powerful but makes direct use of the objectmanager (in your template file!) and indirectly adds the whole Helper Class logic to your template. This can lead to very messy code (e.g. only creating helpers for business logic, which should reside in models, and executing it directly from the templates).

Edit: Just for completeness: There is a new (now not so new anymore) way to add logic to custom and core blocks by adding domain specific view models to the block, which is probably the best approach to add custom logic to core blocks by now and is really easy to use. read more about it in this article: https://firegento.com/blog/2017/12/07/better-blocks-magento-2-php-view-models/

  • agreed - the last one seems to me the best too! Good point with helpers - to use is that way your class have to extend abstract class of helper. – Bartosz Kubicki Dec 22 '16 at 23:05
  • hm, not sure if this was clear by my answer :D I really would recommend against(!) using the helper method. made that a little more clear ;) – David Verholen Dec 22 '16 at 23:12
  • There is one more thing although that is worth considering. We use fourth method and replace some blocks completely in theme - but it turns our that we add the same code for example in five places in our theme. What then? Should we extract redundant logic to separate class and just include it as dependency into classes we need? – Bartosz Kubicki Dec 22 '16 at 23:16
  • 1
    yes, that's a good way. If you have the same logic as in the original magento block, you could extend it. If you need business logic, you could inject some models or service classes through the constructor. If you have own business logic it's always good to have a dedicated model which does exactly what you want (and best only this one thing). This way, you can reuse it in any block class without much overhead and without duplicate code – David Verholen Dec 22 '16 at 23:23

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.