<?php
$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
);
preferences:
28.45 ms | 407 KiB | 5 Q