在Symfony中处理ids值对象
Requires
- php: 8.2.*|8.3.*
- doctrine/dbal: ^2.13.8|^3.3.6
- symfony/framework-bundle: ^6.3|^7.0
- symfony/polyfill-uuid: ^1.26
- symfony/serializer: ^6.3|^7.0
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.3
- infection/infection: ^0.26.15
- phpstan/phpstan: ^1.9
- phpunit/phpunit: ^9.5
- vimeo/psalm: ^5.25
Suggests
- ext-uuid: Improves performance of id creation and validation. symfony/polyfill-uuid is used as a fallback.
- dev-main
- v1.2.1
- v1.2.0
- v1.1.0
- v1.0.0
- v0.15.0
- v0.14.0
- v0.13.0
- v0.12.0
- v0.11.0
- v0.10.0
- v0.9.0
- v0.8.0
- v0.7.0
- v0.6.0
- v0.5.1
- v0.5.0
- v0.4.0
- v0.3.3
- v0.3.2
- v0.3.1
- v0.3.0
- v0.2.0
- v0.1.0
- v0.1.0-beta.7
- v0.1.0-beta.6
- v0.1.0-beta.5
- v0.1.0-beta.4
- v0.1.0-beta.3
- v0.1.0-beta.2
- v0.1.0-beta.1
- v0.1.0-alpha.8
- v0.1.0-alpha.7
- v0.1.0-alpha.6
- v0.1.0-alpha.5
- v0.1.0-alpha.4
- v0.1.0-alpha.3
- v0.1.0-alpha.2
- v0.1.0-alpha.1
This package is auto-updated.
Last update: 2024-09-03 05:18:51 UTC
README
一个用于在Symfony中处理id和id列表值对象的Symfony包。它包括用于自动归一化和反归一化的Symfony规范化和Doctrine类型,可以直接在数据库中存储ids和id列表。
由于它是应用程序的核心部分,因此经过彻底测试(包括突变测试)。
安装和配置
通过composer安装包
composer require digital-craftsman/ids
建议安装uuid
PHP扩展以获得更好的id创建和验证性能。symfony/polyfill-uuid
用作后备。您可以在安装PHP扩展后防止安装polyfill。
处理ids
创建新的id
大部分逻辑在Id
类中。创建新的id就像创建一个新的final readonly class
并从中扩展一样,如下所示
<?php declare(strict_types=1); namespace App\ValueObject; use DigitalCraftsman\Ids\ValueObject\Id; final readonly class UserId extends Id { }
现在您已经可以在代码中使用它了,如下所示
$userId = UserId::generateRandom();
if ($userId->isEqualTo($command->userId)) { ... }
防止无效使用
$requestingUser->userId->mustNotBeEqualTo($command->targetUserId);
或使用自定义异常
$requestingUser->userId->mustNotBeEqualTo( $command->targetUserId, static fn () => new Exception\UserCanNotTargetItself(), );
Symfony序列化器
如果您直接注入SerializerInterface
,则无需执行任何操作。id的反序列化器将自动注册。
namespace App\DTO; final readonly class UserPayload { public function __construct( public UserId $userId, public string $firstName, public string $lastName, ) { } }
public function __construct( private SerializerInterface $serializer, ) { } public function handle(UserPayload $userPayload): string { return $this->serializer->serialize($userPayload, JsonEncoder::FORMAT); }
{ "userId": "15d6208b-7cf2-49e5-a193-301d594d98a7", "firstName": "Tomas", "lastName": "Bauer" }
这可以与CQRS包结合使用,以便在序列化id中。
Doctrine类型
要在实体中使用id,您只需为id注册一个新的类型。创建一个新的类来表示新的id,如下所示
<?php declare(strict_types=1); namespace App\Doctrine; use App\ValueObject\UserId; use DigitalCraftsman\Ids\Doctrine\IdType; final class UserIdType extends IdType { public static function getTypeName(): string { return 'user_id'; } public static function getClass(): string { return UserId::class; } }
然后,在您的config/packages/doctrine.yaml
文件中注册新类型
doctrine: dbal: types: user_id: App\Doctrine\UserIdType
或者,您还可以添加编译器传递以自动注册类型。
然后您就可以将其添加到实体中,如下所示
<?php declare(strict_types=1); namespace App\Entity; use App\ValueObject\UserId; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface; use Symfony\Component\Security\Core\User\UserInterface; #[ORM\Entity(repositoryClass: UserRepository::class)] #[ORM\Table(name: '`user`')] class User implements UserInterface, PasswordAuthenticatedUserInterface { #[ORM\Id] #[ORM\Column(name: 'id', type: 'user_id')] public UserId $id; ... }
处理id列表
id列表是id数组的包装器。它包含一些实用函数和改进的类型安全。
IdList
是不可变的。因此,突变方法(如add
、remove
等)始终返回列表的新实例。
创建新的id列表
大部分逻辑在IdList
类中。创建新的id列表就像创建一个新的final readonly class
并从中扩展一样,如下所示
<?php declare(strict_types=1); namespace App\ValueObject; use DigitalCraftsman\Ids\ValueObject\IdList; /** @extends IdList<UserId> */ final readonly class UserIdList extends IdLIst { public static function handlesIdClass(): string { return UserId::class; } }
现在您已经可以在代码中使用它了,如下所示
$userIdList = new UserIdList($userIds);
if ($idsOfEnabledUsers->contains($command->userId)) { ... }
防止无效使用
$idsOfEnabledUsers->mustContainId($command->targetUserId);
或使用自定义异常
$idsOfEnabledUsers->mustContainId( $command->targetUserId, static fn () => new Exception\UserIsNotEnabled(), );
Symfony序列化器
如果您直接注入SerializerInterface
,则无需执行任何操作。id列表的反序列化器将自动注册。
Doctrine类型
要在实体中使用id列表,您只需为id列表注册一个新的类型。创建一个新的类来表示新的id列表,如下所示
<?php declare(strict_types=1); namespace App\Doctrine; use App\ValueObject\UserId; use App\ValueObject\UserIdList; use DigitalCraftsman\Ids\Doctrine\IdListType; final class UserIdListType extends IdListType { protected function getTypeName(): string { return 'user_id_list'; } protected function getIdListClass(): string { return UserIdList::class; } protected function getIdClass(): string { return UserId::class; } }
然后,在您的config/packages/doctrine.yaml
文件中注册新类型
doctrine: dbal: types: user_id_list: App\Doctrine\UserIdListType
然后您就可以将其添加到实体中,如下所示
<?php declare(strict_types=1); namespace App\Entity; use App\ValueObject\UserIdList; use Doctrine\ORM\Mapping as ORM; #[ORM\Entity(repositoryClass: InvestorRepository::class)] #[ORM\Table(name: 'investor')] class Investor { #[ORM\Column(name: 'ids_of_users_with_access', type: 'user_id_list')] public UserIdList $idsOfUsersWithAccess; ... }