4.3. Entity-Attribute-Value (EAV)

The Entity–attribute–value (EAV) pattern in order to implement EAV model with PHP.

4.3.1. Purpose

The Entity–attribute–value (EAV) model is a data model to describe entitieswhere the number of attributes (properties, parameters) that can be usedto describe them is potentially vast, but the number that will actually applyto a given entity is relatively modest.

4.3.2. UML Diagram

EAV UML Diagram

4.3.3. Code

You can also find this code on GitHub

Entity.php

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

Attribute.php

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

Value.php

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

4.3.4. Test

Tests/EAVTest.php

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