tp/ident

为对象添加身份的库

dev-master / 1.0.x-dev 2014-11-08 17:07 UTC

This package is not auto-updated.

Last update: 2024-09-24 02:47:27 UTC


README

Build Status Scrutinizer Code Quality Code Coverage

提供一个接口,用于处理对象的“身份和标识符”。

注意

此文档仍在进行中,可能会随时更改。

特性

  • 对象身份通用接口的POC
  • 各种标识符的实现(UuidIdentifierBinaryUuidIdentifierStringIdentifierNullIdentifier
  • 基于注解的对象标识符配置(YAML和XML正在开发中)(需要jms/metadata: >= 1.1doctrine/annotations: >= 1.0)。
  • Doctrine2 ORM集成(需要doctrine/orm: >= 2.x)。
  • BinaryUuidType DBAL类型(需要doctrine/dbal: >= 2.5.x-dev)以在底层数据库实现中节省一些存储空间(尽管您在使用它作为主键时应该注意索引碎片化)。
  • 一个HashFactory,可以轻松地基于随机字节数据生成各种算法的唯一哈希(需要symfony/security: >=2.3)。

简介

身份是我们日常生活中一个非常重要的概念。如果你想象一个Person类,很明显这个Person必须有一个身份。

有各种各样的Identity实现,这个库试图提供一个共同的接口来处理这个问题。

Person HasIdentity

<?php
namespace Ident;

interface HasIdentity
{
    /**
     * This method returns the, in its context, unique identifier.
     *
     * @return IdentifiesObjects
     */
    public function getIdentifier();
}

另一方面,Identifier IdentifiesObjects。想象一下这是身份的签名。或者用现实世界的话说,是一张护照或一张驾照

<?php
namespace Ident;

interface IdentifiesObjects
{
    /**
     * This method is a static factory that reconstitutes an identifier
     * from its signature.
     * 
     * @param string $signature
     * @return IdentifiesObjects
     * @throws \Ident\Exception\InvalidSignature
     */
    public static function fromSignature($signature);

    /**
     * This method returns a unique identity representation
     *
     * @return string
     */
    public function signature();

    /**
     * The __toString() method should also return the signature for
     * various compatibility reasons.
     *
     * @return string
     */
    public function __toString();
}

当然,需要有一种Registry。想想你搬到新城市后,市政府为你登记。

Registry RegistersIdentities

<?php
namespace Ident;

interface RegistersIdentities
{
    /**
     * @param HasIdentity $identity
     *
     * @return void
     */
    public function add(HasIdentity $identity);

    /**
     * @param HasIdentity $identity
     *
     * @return bool
     */
    public function contains(HasIdentity $identity);

    /**
     * @param HasIdentity $identity
     *
     * @return void
     */
    public function remove(HasIdentity $identity);

    /**
     * @param IdentifiesObjects $id
     *
     * @return HasIdentity $identity
     */
    public function get(IdentifiesObjects $id);

    /**
     * @return \Iterator
     */
    public function all();

    /**
     * @return void
     */
    public function clear();

    /**
     * @param callable $callable
     *
     * @return void
     */
    public function map(Callable $callable);

    /**
     * @param IdentifiesObjects $id
     *
     * @return bool
     */
    public function has(IdentifiesObjects $id);

    /**
     * @param IdentifiesObjects $id
     *
     * @return void
     */
    public function del(IdentifiesObjects $id);
}

现在,身份从哪里来?当你出生时,你是否自动继承它?在行政程序中,你只有在你的父母收到一份出生证明之前才被识别。这意味着有一些权威机构能够发行身份。

Issuer CreatesIdentities

<?php
namespace Ident;

interface CreatesIdentities
{
    /**
     * This method issues an Identity for a given context.
     * The context can hold any arbitrary data, and its contents should
     * be validated within the underlying implementations.
     * 
     * @param mixed $context
     * @return \Ident\IdentifiesObjects
     * @throws \Ident\Exception\IdentityNotResolvable
     */
    public function identify($context);
}

好,到目前为止一切顺利。几乎每个人都处于某种形式的权威控制之下,例如,因为你的车灯没有正常工作而被警察拦下。权威机构需要能够比较IdentityIdentifiers

<?php
namespace Ident;

interface IdentityCanBeCompared
{
    /**
     * This method compares itself to a given Identifier and returns
     * true or false if the Identifier is equal.
     *
     * @param IdentifiesObjects $id
     * @return bool
     */
    public function equals(IdentifiesObjects $id);
}

当然,这也适用于对象。想象一下你看到一些黑帮的照片,然后说:“是的,那是托马斯!”

<?php
namespace Ident;

interface ObjectCanBeCompared
{
    /**
     * @param HasIdentity $object
     * @return bool
     */
    public function equals(HasIdentity $object);
}

安装

此软件包通过Composer PHP包管理器安装。

php composer.phar require tp/ident "1.0.x-dev"

要求

  • PHP 5.5+(由于使用了生成器)

用法

使用IdType注解

IdType注解有两个参数

  • type (string) [必需]

    可以是映射别名(请参阅以下注解处理器配置示例)或实现Ident\IdentifiesObjects接口的类的FQCN。

  • factory (string|array)

    • 如果是string,则期望一个可调用的静态方法/函数名。
    • 如果是array,则数组有3个键
      • service: 在ServiceLocatorInterface中查找的服务键作为string
      • method: 在给定服务上调用的方法名作为string
      • params: 该方法的参数作为array
示例

假设我们有一个以下Identifier

<?php
namespace My\Orders;

use Ident\Identifiers\BinaryUuidIdentifier;

class OrderId extends BinaryUuidIdentifier
{
}

以及以下实现Ident\HasIdentity的域对象

<?php
namespace My\Orders;

use Ident\HasIdentity;
use Ident\Metadata\Annotation as Ident;

class Order implements HasIdentity
{
    /**
     * @Ident\IdType(
     *  type="My\Orders\OrderId",
     *  factory="Rhumsaa\Uuid\Uuid::uuid4"
     * )
     */
    private $identifier;

    /**
     * @Ident\IdType(
     *  type="Ident\Identifiers\StringIdentifier",
     *  factory={"service"="hash.factory", "method"="hash", "params"={"sha1"}}
     * )
     */
    private $transactionHash;

    /**
     * @return \Ident\IdentifiesObjects
     */
    public function getIdentifier()
    {
        return $this->identifier;
    }
    
    /**
     * @return \Ident\IdentifiesObjects
     */
    public function getTransactionHash()
    {
        return $this->transactionHash;
    }
}

然后,当在对象上调用时,处理器会自动设置这些值。

<?php
// Use the processor to identify objects with an annotation configuration
$domainObject = new My\Orders\Order(); // Has annotation config
$processor->identify($domainObject);

$domainObject->getIdentifier() instanceof My\Orders\OrderId; //true
$domainObject->getTransactionHash() instanceof Ident\Identifiers\StringIdentifier; //true

配置

这部分展示了如何集成这个库的一些示例。

创建元数据处理器

<?php
// Autoload composer
require VENDOR_PATH . '/autoload.php';

// Register annotations
\Doctrine\Common\Annotations\AnnotationRegistry::registerFile(
    VENDOR_PATH . "/tp/ident/src/Metadata/Annotation/Mapping/IdentAnnotations.php");

// Create the driver
$driver = new \Ident\Metadata\Driver\AnnotationDriver(
    new \Doctrine\Common\Annotations\AnnotationReader()
);

// Create the ServiceLocator, there is also a Symfony ans a Pimple ServiceLocator implementation
$services = [];
$services['my.service'] = new \My\Awsome\Service();
$container = new \Ident\ServiceLocator\SimpleArrayServiceLocator($services);

// Create an AliasToIdentityMapper (optional)
$mapper = new \Ident\Mapper\InMemoryClassToIdentityMapper();
$mapper->register('string', 'Ident\Identifiers\StringIdentifier');
$mapper->register('uuid_string', 'Ident\Identifiers\UuidIdentifier');
$mapper->registerMany(
    [
        'my_type',
        'another_type'
    ],
    'My\Identifier\Implementation'
);

// Finally, create the metadata processor
$processor = \Ident\Metadata\Processor\IdentityMetadataProcessor(
    new \Metadata\MetadataFactory($driver),
    $container,
    $mapper
);

// Use the processor to identify objects with an annotation configuration
$domainObject = new Order(); // Has annotation config
$processor->identify($domainObject);

启用Doctrine ORM集成

<?php
$em = $serviceLovator->get('doctrine.default_entity_manager');
$processor = $serviceLocator->get('ident.metadata.processor');
$em->getEventManager()
    ->addEventSubscriber(
        new IdentitySubscriber($processor)
    );

启用Doctrine DBAL Uuid类型

<?php
\Doctrine\DBAL\Types\Type::addType(
    \Ident\Doctrine\Type\BinaryUuidType::NAME, // 'uuid_binary'
    '\Ident\Doctrine\Type\BinaryUuidType'
);

\Doctrine\DBAL\Types\Type::addType(
    \Ident\Doctrine\Type\UuidType::NAME, // 'uuid_string'
    '\Ident\Doctrine\Type\UuidType'
);