实体-属性-值模式

实体-属性-值模式(EAV)的目标是用 PHP 实现 EAV 模型。

目的

实体-属性-值模型(EAV 模型),是一种描述实体的数据模型。在这种模型中,用于描述实体属性(特性、参数)的数量可能非常多,但实际应用于某个实体的数量却相对较少。

UML 类图

实体-属性-值模式类图

代码

Entity.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
<?php declare(strict_types = 1);

namespace DesignPatterns\Extend\EAV;

use SplObjectStorage;

class Entity
{
/**
* @var SplObjectStorage<Value,Value>
*/
private $values;

/**
* @var string
*/
private string $name;

/**
* @param string $name
* @param Value[] $values
*/
public function __construct(string $name, $values)
{
/** @var SplObjectStorage<Value,Value> values */
$this->values = new SplObjectStorage();
$this->name = $name;

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<?php declare(strict_types = 1);

namespace DesignPatterns\Extend\EAV;

use SplObjectStorage;

class Attribute
{
private SplObjectStorage $values;
private string $name;

public function __construct(string $name)
{
$this->values = new SplObjectStorage();
$this->name = $name;
}

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php declare(strict_types = 1);

namespace DesignPatterns\Extend\EAV;

class Value
{
private Attribute $attribute;
private string $name;

public function __construct(Attribute $attribute, string $name)
{
$this->name = $name;
$this->attribute = $attribute;

$attribute->addValue($this);
}

public function __toString(): string
{
return sprintf('%s: %s', (string) $this->attribute, $this->name);
}
}

测试

Tests/EAVTest.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<?php declare(strict_types = 1);

namespace DesignPatterns\Extend\EAV\Tests;

use DesignPatterns\Extend\EAV\Attribute;
use DesignPatterns\Extend\EAV\Entity;
use DesignPatterns\Extend\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);
}
}