实体属性值模式(EAV 模式)

实体属性值(Entity—attribute—value EAV)模式,可以方便 PHP 实现 EAV 模型。

目的

实体属性值模型(Entity-attribute-value EAV)是一种用数据模型描述实体的属性(属性,参数),可以用来形容他们潜在巨大,但实际上将适用于给定的实体的数量是相对较少。 在数学中,这种模式被称为一个稀疏矩阵 。 EAV也被称为对象的属性值的模式,垂直的数据库模型和开放式架构。

UML 图

file

代码

您可以在 GitHub 查看这段代码。

Entity.php

  1. <?php
  2. namespace DesignPatterns\More\EAV;
  3. class Entity
  4. {
  5. /**
  6. * @var \SplObjectStorage
  7. */
  8. private $values;
  9. /**
  10. * @var string
  11. */
  12. private $name;
  13. /**
  14. * @param string $name
  15. * @param Value[] $values
  16. */
  17. public function __construct(string $name, $values)
  18. {
  19. $this->values = new \SplObjectStorage();
  20. $this->name = $name;
  21. foreach ($values as $value) {
  22. $this->values->attach($value);
  23. }
  24. }
  25. public function __toString(): string
  26. {
  27. $text = [$this->name];
  28. foreach ($this->values as $value) {
  29. $text[] = (string) $value;
  30. }
  31. return join(', ', $text);
  32. }
  33. }

Attribute.php

  1. <?php
  2. namespace DesignPatterns\More\EAV;
  3. class Attribute
  4. {
  5. /**
  6. * @var \SplObjectStorage
  7. */
  8. private $values;
  9. /**
  10. * @var string
  11. */
  12. private $name;
  13. public function __construct(string $name)
  14. {
  15. $this->values = new \SplObjectStorage();
  16. $this->name = $name;
  17. }
  18. public function addValue(Value $value)
  19. {
  20. $this->values->attach($value);
  21. }
  22. /**
  23. * @return \SplObjectStorage
  24. */
  25. public function getValues(): \SplObjectStorage
  26. {
  27. return $this->values;
  28. }
  29. public function __toString(): string
  30. {
  31. return $this->name;
  32. }
  33. }

Value.php

  1. <?php
  2. namespace DesignPatterns\More\EAV;
  3. class Value
  4. {
  5. /**
  6. * @var Attribute
  7. */
  8. private $attribute;
  9. /**
  10. * @var string
  11. */
  12. private $name;
  13. public function __construct(Attribute $attribute, string $name)
  14. {
  15. $this->name = $name;
  16. $this->attribute = $attribute;
  17. $attribute->addValue($this);
  18. }
  19. public function __toString(): string
  20. {
  21. return sprintf('%s: %s', $this->attribute, $this->name);
  22. }
  23. }

测试

Tests/EAVTest.php

  1. <?php
  2. namespace DesignPatterns\More\EAV\Tests;
  3. use DesignPatterns\More\EAV\Attribute;
  4. use DesignPatterns\More\EAV\Entity;
  5. use DesignPatterns\More\EAV\Value;
  6. use PHPUnit\Framework\TestCase;
  7. class EAVTest extends TestCase
  8. {
  9. public function testCanAddAttributeToEntity()
  10. {
  11. $colorAttribute = new Attribute('color');
  12. $colorSilver = new Value($colorAttribute, 'silver');
  13. $colorBlack = new Value($colorAttribute, 'black');
  14. $memoryAttribute = new Attribute('memory');
  15. $memory8Gb = new Value($memoryAttribute, '8GB');
  16. $entity = new Entity('MacBook Pro', [$colorSilver, $colorBlack, $memory8Gb]);
  17. $this->assertEquals('MacBook Pro, color: silver, color: black, memory: 8GB', (string) $entity);
  18. }
  19. }