Товары, категории, покупатели и заказы
Товары, категории, покупатели и заказы хранятся в десятках связанных таблиц ядра. Читать их запросами SQL не нужно: у каждого вида данных есть репозиторий — интерфейс с теми же методами get, getList и save, что и у репозитория отзывов. Эти интерфейсы не меняются при обновлении Magento.
Репозитории ядра
| Данные | Интерфейс |
|---|---|
| Товары | Magento\Catalog\Api\ProductRepositoryInterface |
| Категории | Magento\Catalog\Api\CategoryRepositoryInterface |
| Покупатели | Magento\Customer\Api\CustomerRepositoryInterface |
| Заказы | Magento\Sales\Api\OrderRepositoryInterface |
Репозиторий просят в конструкторе своего класса. Модули, чьи интерфейсы вы используете, перечисляют в разделе sequence файла module.xml.
Товар по артикулу
Создайте в модуле класс, который будет собирать сведения о магазине:
// app/code/Acme/Hello/Model/ShopInfo.php
namespace Acme\Hello\Model;
use Magento\Catalog\Api\ProductRepositoryInterface;
class ShopInfo
{
public function __construct(private ProductRepositoryInterface $productRepository) {}
public function productName(string $sku): string
{
$product = $this->productRepository->get($sku);
return (string) $product->getName();
}
}Метод get() ищет товар по артикулу (SKU), а getById() — по номеру. Если товара нет, оба бросают исключение NoSuchEntityException.
Использование
Вызовем класс из действия Status прошлых уроков:
// app/code/Acme/Hello/Controller/Index/Status.php
public function execute(): ResultInterface
{
return $this->resultFactory->create(ResultFactory::TYPE_JSON)
->setData(['name' => $this->shopInfo->productName('24-MB01')]);
}Добавьте ShopInfo в конструктор действия, очистите папку generated и откройте /hello/index/status. Если установлены демонстрационные данные, ответ будет {"name":"Joust Duffle Bag"}.
Список товаров
Условия поиска собирает SearchCriteriaBuilder — так же, как для отзывов:
// app/code/Acme/Hello/Model/ShopInfo.php
public function cheapProducts(): array
{
$criteria = $this->criteriaBuilder
->addFilter('price', 50, 'lt')
->setPageSize(10)
->create();
return $this->productRepository->getList($criteria)->getItems();
}Метод возвращает до десяти товаров дешевле 50. У каждого доступны getSku(), getName(), getPrice(). Объект Magento\Framework\Api\SearchCriteriaBuilder добавляют в конструктор.
Изменение товара
// app/code/Acme/Hello/Model/ShopInfo.php
public function setPrice(string $sku, float $price): void
{
$product = $this->productRepository->get($sku);
$product->setPrice($price);
$this->productRepository->save($product);
}Товар сохраняется со всеми проверками ядра, а индексы и кеш обновляются сами.
Категория, покупатель, заказ
// app/code/Acme/Hello/Model/ShopInfo.php
public function summary(int $categoryId, string $email, int $orderId): array
{
$category = $this->categoryRepository->get($categoryId);
$customer = $this->customerRepository->get($email);
$order = $this->orderRepository->get($orderId);
return [
'category' => $category->getName(),
'customer' => $customer->getFirstname() . ' ' . $customer->getLastname(),
'order' => $order->getIncrementId(),
'total' => $order->getGrandTotal(),
];
}Категорию и заказ находят по номеру, покупателя — по адресу почты или через getById(). Метод getIncrementId() возвращает номер заказа, который видит покупатель, а getGrandTotal() — итоговую сумму.
Заказы покупателя
// app/code/Acme/Hello/Model/ShopInfo.php
public function ordersOf(string $email): array
{
$criteria = $this->criteriaBuilder
->addFilter('customer_email', $email)
->create();
return $this->orderRepository->getList($criteria)->getItems();
}Метод возвращает все заказы с указанным адресом почты.
Частая ошибка
Репозиторий вызывают в цикле: для ста отзывов сто раз выполняют $this->productRepository->getById(). Каждый вызов загружает товар целиком со всеми атрибутами, и страница открывается несколько секунд. Соберите номера и получите товары одним вызовом getList() с условием in по полю entity_id.