0

目标:

在我的产品详细信息页面上,我想显示我的产品拥有的所有父类别的面包屑。

例如,如果有一个产品被分配了一个指向 SubSubCategory 的 category_id;我希望面包屑是:

Root Category / SubCategory / SubSubCategory

问题:

一些产品的 category_id 可能指向根类别(没有子类别),而其他产品的 category_id 可能指向一个深度为 2 层的类别(有两个父类别)。我该如何处理这些场景?

我试过的:

这是我的类别模型

这是我的类别表

到目前为止,如果我想获得特定产品的类别面包屑,我会这样做:

{{$product->category->parent->name}} / {{$product->category->name}}

但它很快就对分配了根类别的产品产生了错误。因为我试图建立一种不存在的关系。

4

1 回答 1

0

我会将其视为行为,这意味着productand上的一种方法category。例如:

{{ $product->trail() }}

其中product知道如何计算它自己的category面包屑轨迹。

首先,对于类别,我们给出了一种计算其自身上游部分的方法。

$category = function(string $name, $parent = null) {
    return new class($name, $parent) {
        public $name;
        public $parent;

        public function __construct(string $name, $parent = null) {
            $this->name = $name;
            $this->parent = $parent;
        }

        public function breadcrumbs(array $trail = []) {
            $trail[] = $this->name;

            return $this->parent ? $this->parent->breadcrumbs($trail) : $trail;
        }
    };
};

然后从产品中,我们可以要求它用分隔符计算它,作为回报给我们线索。

$product = function(string $name, ...$categories) use($category) {
    $categories = array_reduce(array_reverse($categories), function($set, $item) use($category) {
        if (!$set) {
            return $category($item);
        }

        return $category($item, $set);
    });

    return new class($name, $categories) {
        public $name;
        public $categories;

        public function __construct(string $name, $categories) {
            $this->name = $name;
            $this->categories = $categories;
        }

        public function trail(string $separator = ' / '): string {
            return implode($separator, $this->categories->breadcrumbs());
        }
    };
};

然后像这样使用它:

$book = $product('Harry Potter', 'books', 'hardback', 'young-adult');
$shoes = $product('Air Jordans', 'shoes', 'mens', 'sports', 'basketball');
$tapeMeasure = $product('Stanley 25', 'hardware', 'tools', 'measurement');

var_dump(
    $book->trail(),        // books / hardback / young-adult
    $shoes->trail(),       // shoes / mens / sports / basketball
    $tapeMeasure->trail()  // hardware / tools / measurement
);

https://3v4l.org/FNKZI

如果您正在寻找更复杂的东西,您可以$product->trail()使用装饰器进行扩展。

public function linkSimilar(string $separator = ' / '): string {
    return $this->trail($separator, function(string $name) {
        return sprintf('<a href="/category/%s?similar-to=product/%s">%s</a>', $name, $this->sku, $name);
    });
}

...

$product->linkSimilar(' > ')

提供:

<a href="/category/hardware?similar-to=product/U425263">hardware</a>
 > <a href="/category/tools?similar-to=product/U425263">tools</a>
 > <a href="/category/measurement?similar-to=product/U425263">measurement</a>

https://3v4l.org/22n15

于 2020-05-16T14:19:07.793 回答