CSCFA csr 分区 PHP 实现

1.0.0 2017-03-19 16:41 UTC

This package is not auto-updated.

Last update: 2024-09-18 20:07:20 UTC


README

本项目是 csr3 规范 的 PHP 实现。

数据传输对象是当数据必须通过应用中的多个元素时使用的元素。DTO 作为容器。

SensioLabsInsight

基本用法

CSR3 项目定义了一个通用的 DTO 对象

use CSDT\CSR3\CSR3GenericDTO;

$dto = new CSR3GenericDTO();

Csr3GenericDTO 是一个实现 CSR3DTOInterface 的实例。此接口扩展了 ArrayAccess 和 Iterator 接口。

ArrayAccess 实现

通过使用 ArrayAccess 接口,CSR3GenericDTO 允许像数组一样使用。

// ...

if (isset($user) && !empty($user)) {
    $dto['user_instance'] = $user;
}

// ...

if (isset($dto['user_instance']) {
    $user = $dto['user_instance'];
    
    if ($user->isLocked()) {
        unset($dto['user_instance']);
    }
}
Iterator 实现

通过使用 Iterator 接口,CSR3GenericDTO 允许像迭代器一样使用。

$dto['hell'] = 'o w';
$dto['or'] = 'ld';

foreach ($dto as $key => $value) {
    echo $key . $value;
}

// Output : "hello world"
Csr3DTOInterface 实现

Csr3DTOInterface 是 CSR3 DTO 的默认访问功能。它允许设置和获取属性。

$dto->setAttributes(['a' => 1, 'b' => 2]);

var_dump($dto->getAttributes());
/* array(2) {
  ["a"]=>
  int(1)
  ["b"]=>
  int(2)
} */


$dto->setAttribute('a', 3);

var_dump($dto->getAttribute('b')); // int(2)
var_dump($dto->getAttributes());
/* array(2) {
  ["a"]=>
  int(3)
  ["b"]=>
  int(2)
} */

添加自定义方法

Csr3GenericDTO 是一个 final 类,不能直接扩展。但它扩展了一个抽象类:AbstractCSR3DTO,该类定义了实现 CSR3DTOInterface 所需的所有逻辑。

想象你想要创建一个存储特定上下文并可以通过方法调用来检索的 DTO。你可以创建一个如下所示的 DTO 类

use CSDT\CSR3\Abstracts\AbstractCSR3DTO;

class ContextDTO extends AbstractCSR3DTO
{
    public function setContext($context)
    {
        $this['context'] = $context;
    }
    
    public function getContext($context)
    {
        return $this['context'] ?? [];
    }
}

使用自定义类属性

如自定义方法添加所示,你必须创建自己的类

use CSDT\CSR3\Abstracts\AbstractCSR3DTO;

class ContextDTO extends AbstractCSR3DTO
{
    protected $context = [];

    public function setContext($context)
    {
        $this->context = $context;
    }
    
    public function getContext($context)
    {
        return $this->context;
    }
}

使用此自定义类时,你会遇到的问题是无法处理 $context 属性。为了避免这个问题,你需要扩展 AbstractCSR3PropertyDTO 而不是 AbstractCSR3DTO

use CSDT\CSR3\Abstracts\AbstractCSR3DTO;

class ContextDTO extends AbstractCSR3PropertyDTO
{
    protected $context = [];

    public function setContext($context)
    {
        $this->['context'] = $context;
    }
    
    public function getContext($context)
    {
        return $this['context'];
    }
}

💢 注意 AbstractCSR3PropertyDTO 不能处理私有属性,这是 PHP 的 OOP 结构。

使用私有属性

为了能够管理 DTO 的私有属性,你必须覆盖 AbstractCSR3PropertyDTO 的三个方法

use CSDT\CSR3\Abstracts\AbstractCSR3DTO;

class ContextDTO extends AbstractCSR3PropertyDTO
{
    private $context = [];
    
    protected function getProperties() : array
    {
        return array_merge(
            parent::getProperties(),
            ['context']
        );
    }
    
    protected function setProperty(string $propertyName, $propertyValue)
    {
        if ($propertyName == 'context') {
            $this->setContext($propertyValue);
            return $this;
        }

        return parent::setProperty($propertyName, $propertyValue);
    }

    protected function getProperty(string $propertyName)
    {
        if (propertyName == 'context') {
            return $this->getContext();
        }

        return parent::getProperty($propertyName);
    }

    public function setContext($context)
    {
        $this->context = $context;
    }
    
    public function getContext($context)
    {
        return $this->context;
    }
}

❕ 这三个方法协同工作,不能单独覆盖,以启用完全的私有属性支持。

内部关键字及其覆盖方法

AbstractCSR3DTOAbstractCSR3PropertyDTO 定义了 attributestraversingPosition 属性。第一个存储 DTO 的属性,第二个存储内部迭代指针。可以通过设置存储要使用的属性名称的 attributeContainerpositionContainer 属性来覆盖它们,而不是使用两个初始属性。

💢 attributeContainerpositionContainer 属性是关键字,不能被覆盖。

在不使用 CSR3 接口的情况下使用逻辑

此实现的完整逻辑封装在 CSR3DTOTraitCSR3PropertyDTOTrait 中。

use CSDT\CSR3\Traits\CSR3DTOTrait;

class AttributeDTO
{
    use CSR3DTOTrait;

    private $attributes = [];
    
    private $traversingPosition = 0;
}
use CSDT\CSR3\Traits\CSR3DTOPropertyTrait;

class ContextDTO
{
    use CSR3DTOPropertyTrait;

    private $attributes = [];
    
    private $traversingPosition = 0;
    
    private $context = [];
    
    protected function getProperties() : array
    {
        return array_merge(
            parent::getProperties(),
            ['context']
        );
    }
    
    protected function setProperty(string $propertyName, $propertyValue)
    {
        if ($propertyName == 'context') {
            $this->setContext($propertyValue);
            return $this;
        }

        return parent::setProperty($propertyName, $propertyValue);
    }

    protected function getProperty(string $propertyName)
    {
        if (propertyName == 'context') {
            return $this->getContext();
        }

        return parent::getProperty($propertyName);
    }

    public function setContext($context)
    {
        $this->context = $context;
    }
    
    public function getContext($context)
    {
        return $this->context;
    }
}