分类
Magento PHP

magento2 产品分类页面按照指定

产品分类页面URL  ?skus=OPB-P112D,OPB-P206DN    指定sku显示在最前面

/etc/di.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <preference for="Magento\Elasticsearch\Model\ResourceModel\Fulltext\Collection\SearchResultApplier" type="Maijindou\Catalog\Plugin\Model\ResourceModel\Fulltext\Collection\SearchResultApplier" />
</config>
Plugin\Model\ResourceModel\Fulltext\Collection
<?php


namespace Maijindou\Catalog\Plugin\Model\ResourceModel\Fulltext\Collection;


use Magento\Catalog\Model\Product;
use Magento\CatalogSearch\Model\ResourceModel\Fulltext\Collection\SearchResultApplierInterface;
use Magento\Framework\Api\Search\SearchResultInterface;
use Magento\Framework\Data\Collection;

class SearchResultApplier implements SearchResultApplierInterface
{
    /**
     * @var Collection|\Magento\CatalogSearch\Model\ResourceModel\Fulltext\Collection
     */
    private $collection;

    /**
     * @var SearchResultInterface
     */
    private $searchResult;

    /**
     * @var int
     */
    private $size;

    /**
     * @var int
     */
    private $currentPage;

    private $request;

    private $product;

    /**
     * @param Collection $collection
     * @param SearchResultInterface $searchResult
     * @param int $size
     * @param int $currentPage
     */
    public function __construct(
        Collection $collection,
        \Magento\Framework\App\RequestInterface $request,
        SearchResultInterface $searchResult,
        Product $product,
        int $size,
        int $currentPage
    ) {
        $this->product = $product;
        $this->request = $request;
        $this->collection = $collection;
        $this->searchResult = $searchResult;
        $this->size = $size;
        $this->currentPage = $currentPage;
    }

    /**
     * @inheritdoc
     */
    public function apply()
    {
        if (empty($this->searchResult->getItems())) {
            $this->collection->getSelect()->where('NULL');

            return;
        }

        $items = $this->sliceItems($this->searchResult->getItems(), $this->size, $this->currentPage);
        $ids = [];
        foreach ($items as $item) {
            $ids[] = (int)$item->getId();
        }

        $skus = $this->request->getParam('skus');
        $arr_sku = explode(',',$skus);
        $new_ids = [];
        foreach($arr_sku as $str){
            $product_id = $this->product->getIdBySku($str);
            $new_ids[] = $product_id;
            if(in_array($product_id,$ids)){
                array_unshift($ids,$product_id);
            }
        }

        $ids = array_unique($ids);

        $this->collection->getSelect()
            ->where('e.entity_id IN (?)', $ids)
            ->reset(\Magento\Framework\DB\Select::ORDER);
        $sortOrder = $this->searchResult->getSearchCriteria()
            ->getSortOrders();
        if (!empty($sortOrder['price']) && $this->collection->getLimitationFilters()->isUsingPriceIndex()) {
            $sortDirection = $sortOrder['price'];
            $this->collection->getSelect()
                ->order(
                    new \Zend_Db_Expr("price_index.min_price = 0, price_index.min_price {$sortDirection}")
                );
        } else {
            $orderList = join(',', $ids);
            $this->collection->getSelect()
                ->order(new \Zend_Db_Expr("FIELD(e.entity_id,$orderList)"));
        }
    }

    /**
     * Slice current items
     *
     * @param array $items
     * @param int $size
     * @param int $currentPage
     * @return array
     */
    private function sliceItems(array $items, int $size, int $currentPage): array
    {
        if ($size !== 0) {
            // Check that current page is in a range of allowed page numbers, based on items count and items per page,
            // than calculate offset for slicing items array.
            $itemsCount = count($items);
            $maxAllowedPageNumber = ceil($itemsCount/$size);
            if ($currentPage < 1) {
                $currentPage = 1;
            }
            if ($currentPage > $maxAllowedPageNumber) {
                $currentPage = $maxAllowedPageNumber;
            }

            $offset = $this->getOffset($currentPage, $size);
            $items = array_slice($items, $offset, $size);
        }

        return $items;
    }

    /**
     * Get offset for given page.
     *
     * @param int $pageNumber
     * @param int $pageSize
     * @return int
     */
    private function getOffset(int $pageNumber, int $pageSize): int
    {
        return ($pageNumber - 1) * $pageSize;
    }
}