PHP 实体-属性-值 (EAV)模式
实体-属性-值 (EAV) 模式以使用 PHP 实现 EAV 模型。
目的
Entity-attribute-value (EAV) 模型是一种描述实体的数据模型,其中可用于描述它们的属性(属性、参数)的数量可能很大,但实际应用于给定实体的数量是比较适中。
UML 图
代码
Entity.php
<?php declare(strict_types=1); namespace DesignPatterns\More\EAV; use SplObjectStorage; class Entity implements \Stringable { /** * @var SplObjectStorage<Value,Value> */ private $values; /** * @param Value[] $values */ public function __construct(private string $name, $values) { $this->values = new SplObjectStorage(); foreach ($values as $value) { $this->values->attach($value); } } public function __toString(): string { $text = [$this->name]; foreach ($this->values as $value) { $text[] = (string) $value; } return join(', ', $text); } }
Attribute.php
<?php declare(strict_types=1); namespace DesignPatterns\More\EAV; use SplObjectStorage; class Attribute implements \Stringable { private SplObjectStorage $values; public function __construct(private string $name) { $this->values = new SplObjectStorage(); } public function addValue(Value $value) { $this->values->attach($value); } public function getValues(): SplObjectStorage { return $this->values; } public function __toString(): string { return $this->name; } }
Value.php
<?php declare(strict_types=1); namespace DesignPatterns\More\EAV; class Value implements \Stringable { public function __construct(private Attribute $attribute, private string $name) { $attribute->addValue($this); } public function __toString(): string { return sprintf('%s: %s', (string) $this->attribute, $this->name); } }
测试
Tests/EAVTest.php
<?php declare(strict_types=1); namespace DesignPatterns\More\EAV\Tests; use DesignPatterns\More\EAV\Attribute; use DesignPatterns\More\EAV\Entity; use DesignPatterns\More\EAV\Value; use PHPUnit\Framework\TestCase; class EAVTest extends TestCase { public function testCanAddAttributeToEntity() { $colorAttribute = new Attribute('color'); $colorSilver = new Value($colorAttribute, 'silver'); $colorBlack = new Value($colorAttribute, 'black'); $memoryAttribute = new Attribute('memory'); $memory8Gb = new Value($memoryAttribute, '8GB'); $entity = new Entity('MacBook Pro', [$colorSilver, $colorBlack, $memory8Gb]); $this->assertEquals('MacBook Pro, color: silver, color: black, memory: 8GB', (string) $entity); } }