What is the best way to add some method to for example product collection?

  1. I would like to add method which can be called on loaded collection (in fact it will be a filtering one for products that doesn't have any category assigned). The best will be situation if I want to use it I still inject Magento collection class, not mine - I guess it is possible with use of dependency injection.

  2. I have \Magento\Catalog\Model\ResourceModel\Product\CollectionFactory and also \Magento\Catalog\Model\ResourceModel\Product\Collection - which one I should extend?

  • 1
    use \Magento\Catalog\Model\ResourceModel\Product\CollectionFactory – Rakesh Jesadiya Jul 7 '16 at 6:56
  • I eddited question - of course I am using factory. – Bartosz Kubicki Jul 7 '16 at 7:02

You should extend \Magento\Catalog\Model\ResourceModel\Product\Collection and create a preference for your class in di.xml like this:

<preference for="Magento\Catalog\Model\ResourceModel\Product\Collection" type="Your\Module\Model\ResourceModel\Product\Collection" />

You would then inject \Magento\Catalog\Model\ResourceModel\Product\CollectionFactory in order to use it.

| improve this answer | |
  • But to all these thing to work properly my class should extend from Magento\Catalog\Model\ResourceModel\Product\Collection, I guess. Am I right? And if I do it in module A will my changes be available in module B? – Bartosz Kubicki Jul 7 '16 at 7:12
  • 1
    Yes, that's what you should do. The create method of \Magento\Catalog\Model\ResourceModel\Product\CollectionFactory will then return the desired object across the application. – Aaron Allen Jul 7 '16 at 7:51

Actually after some time I think, in some conditions (doesn't happen for product Collection) there is another solution. If class is replaced in Api section of module by an Interface and it implements that interface it's possible to replace it custom module with preference on real class. Example of Api section in module-catalog:

<preference for="Magento\Catalog\Api\ProductCustomOptionRepositoryInterface" type="\Magento\Catalog\Model\Product\Option\Repository" /> <preference for="Magento\Catalog\Api\Data\ProductCustomOptionTypeInterface" type="Magento\Catalog\Model\Product\Option\Type" /> <preference for="Magento\Catalog\Api\ProductTierPriceManagementInterface" type="\Magento\Catalog\Model\Product\TierPriceManagement" /> <preference for="Magento\Catalog\Api\ScopedProductTierPriceManagementInterface" type="\Magento\Catalog\Model\Product\ScopedTierPriceManagement" /> <preference for="Magento\Catalog\Api\Data\ProductTierPriceInterface" type="Magento\Catalog\Model\Product\TierPrice" /> <preference for="Magento\Catalog\Api\Data\CategoryProductLinkInterface" type="Magento\Catalog\Model\CategoryProductLink" />

The steps that should be proceeded:

  • Make your own implementation of class you want to replace, adding your custom logic.
  • In your module that is loaded later then original, declare preference on that Interface again, but argument for should be your implementation. It will work, but only in places of application, where you put in DI Interface instead of its implementation. Then you just replace called class with no harm.
| improve this answer | |

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.