What's the difference between product.repository and sales_channel.product.repository in Shopware 6?
Looks easy? But did you checked in detail the differences or you just use always the product.repository? Let's deep dive into the core files to fully understand the differences so you can decide what to use when.
First of all there is a file called: EntityRepositoryInterface.php where you can see what kind of methodes you can use like search, update, merge and many more. You need to know that Shopware 6 uses Data Abstraction Layer (DAL) and generates for every entity the correspondending repository class. So normally you can use always the same functions for every entity repository.
But the sales_channel.product.repository is using this interface: SalesChannelRepositoryInterface.php and there we have only these three functions like search, aggregate, searchIds. This means you can only use this to search for products, aggregate some additional data to the product defaults data and search for Ids. So you can not use the sales_channel.product.repository to update, delete or create products. That's big difference depending on what you need to do. What else do we got?
So if you search with the sales_channel.product.repository it will call a function called processCriteria and this function will check if $this->definition is an Interface called: SalesChannelDefinitionInterface and this Interface will be called with a function that is also called processCriteria. Let's look at the implemtaion of this function:
public function processCriteria(Criteria $criteria, SalesChannelContext $context): void
{
$criteria
->addAssociation('prices')
->addAssociation('unit')
->addAssociation('deliveryTime')
->addAssociation('cover.media')
;
if (!$this->hasAvailableFilter($criteria)) {
$criteria->addFilter(
new ProductAvailableFilter($context->getSalesChannel()->getId(), ProductVisibilityDefinition::VISIBILITY_LINK)
);
}
}
So this function is adding some default associations and also adding the ProductAvailableFilter. So you only will get products that are assigned to the salesChannel, are visible and active. Keep this in mind. Because this can burn a lot of time when you search for some specific product. Here are the conditions from the ProductAvailableFilter.
class ProductAvailableFilter extends MultiFilter
{
public function __construct(string $salesChannelId, int $visibility = ProductVisibilityDefinition::VISIBILITY_ALL)
{
parent::__construct(
self::CONNECTION_AND,
[
new RangeFilter('product.visibilities.visibility', [RangeFilter::GTE => $visibility]),
new EqualsFilter('product.visibilities.salesChannelId', $salesChannelId),
new EqualsFilter('product.active', true),
]
);
}
}
Also do not forget that the sales_channel.product.repository is loading prices and the product.repository is not loading any association out of the box.