gabrielelana/precious

构建值对象的库

0.1.0 2019-10-27 17:29 UTC

This package is auto-updated.

Last update: 2024-09-16 18:07:48 UTC


README

构建值对象的库。

原因

  • 值对象是 不可变的
  • 值对象应该有一组众所周知的属性
  • 如果两个值对象在结构上相等,即如果它们具有相同的属性和相同的值,则它们是相等的

在PHP中,没有原语来获取这一点,你可以做的是拥有具有私有属性、获取器的大量样板代码的对象。

用法

<?php

use Precious\Precious;

final class Point extends Precious
{
    public static function from(int $x, int $y) : self
    {
        return new self(['x' => $x, 'y' => $y]);
    }

    protected function init() : array
    {
        return [
            self::required('x', self::integerType()),
            self::required('y', self::integerType()),
        ];
    }
}

$p1 = Point::from(1, 1);
$p2 = Point::from(1, 1);
$p3 = Point::from(2, 1);

assert($p1 == $p2);
assert($p1 != $p3);
assert($p1->x === $p2->x);
assert($p1->y === $p2->y);

$p4 = $p3->set('x', 1);
assert($p3 != $p4);
assert(spl_object_hash($p3) !== spl_object_hash($p4));
assert($p1 != $p3);
assert($p1 == $p4);

安装

composer require gabrielelana/precious

PHPStan

基于某种定义生成属性的解决方案的另一个问题是,你将失去对这些属性类型的引用(通过手动定义访问器方法,你不会失去,但你将不得不编写大量的样板代码)。

PHPStan 支持自定义扩展,可以使用这些扩展在两种解决方案之间取得最佳效果:避免样板代码并保留类型信息。

安装建议的依赖项以充分利用 Precious

composer require --dev phpstan/phpstan
composer require --dev nikic/php-parser

如果你还安装了 phpstan/extension-installer

composer require phpstan/extension-installer

那么你就准备就绪了!

否则,请按照手动安装说明进行操作

如果你不想使用 phpstan/extension-installer,将自定义规则添加到你的项目 phpstan.neon 文件中

includes:
  - %currentWorkingDirectory%/vendor/gabrielelana/precious/rules.neon

parameters:
  level: 7

然后,这是你应该期待的

<?php

use Precious\Precious;

final class Point extends Precious
{
    public static function from(int $x, int $y) : self
    {
        return new self(['x' => $x, 'y' => $y]);
    }

    protected function init() : array
    {
        return [
            self::required('x', self::integerType()),
            self::required('y', self::integerType()),
        ];
    }
}

function doSomething() : void {
    $p = Point::from(1, 1);
    echo $p->x . PHP_EOL;
    echo $p->y . PHP_EOL;
    // Will raise: Access to an undefined property Point::$z
    echo $p->z . PHP_EOL;
    // Will raise: Property Point::$x is not writable
    $p->x = 2;
    // Will raise: Parameter #1 $s of function doSomethingWith expects string, int given
    doSomethingWith($p->x);
}

function doSomethingWith(string $s) : string {
    return $s;
}