hostnet/entity-mutation-component

监听事件以进行突变

1.0.6 2022-05-02 18:22 UTC

This package is auto-updated.

Last update: 2024-08-30 01:11:26 UTC


README

文档

实体突变组件是什么?

实体突变组件是一个库,它利用实体跟踪组件,并允许您挂钩到实体变更事件。

该组件允许您根据两种不同的策略自动存储突变:复制当前状态和复制上一个状态。第一种将当前状态复制到突变实体中,而后者将上一个状态复制到突变实体中。

要求

实体突变组件需要至少php 7.3,并运行在Doctrine2上。对于具体要求,请检查composer.json

安装

安装非常简单,此软件包可在packagist上获取。您可以注册软件包并将其锁定到主要版本,因为我们遵循语义版本化2.0.0

示例

$ composer require hostnet/entity-mutation-component

文档

它是如何工作的?

它通过在您的实体上放置@Mutation注解并在实体变更事件上注册监听器来实现,假设您已经配置了实体跟踪组件

以下是一个使用示例。

设置

  • 您必须在您的实体上添加@Mutation
  • 您必须创建您的突变实体
  • 可选地,如果您您的实体知道自己的突变,您可以添加MutationAwareInterface

注册事件

以下是一个非常基本的设置示例。如果您使用具有依赖注入容器的框架,设置将会更容易。

设置可能看起来有点复杂,但实际上大部分是设置跟踪组件。如果您在框架中使用它,建议为此创建一个特定于框架的配置软件包以自动化此过程。

注意:如果您使用Symfony,可以查看hostnet/entity-tracker-bundle。此捆绑包旨在为您配置服务。

use Hostnet\Component\EntityMutation\Resolver\MutationResolver;
use Hostnet\Component\EntityTracker\Listener\EntityChangedListener;
use Hostnet\Component\EntityTracker\Provider\EntityAnnotationMetadataProvider;
use Hostnet\Component\EntityTracker\Provider\EntityMutationMetadataProvider;

/* @var $em \Doctrine\ORM\EntityManager */
$event_manager = $em->getEventManager();

// default doctrine annotation reader
$annotation_reader = new AnnotationReader();

// setup required providers
$annotation_metadata_provider = new EntityAnnotationMetadataProvider($annotation_reader);
$mutation_metadata_provider   = new EntityMutationMetadataProvider($annotation_reader);

// pre flush event listener that uses the @Mutation annotation
$entity_changed_listener = new EntityChangedListener(
    $annotation_metadata_provider,
    $mutation_metadata_provider
);

// the resolver is used to find the correct annotation, which
// fields are considered to be tracked and stored as mutation
// and which entity represents your Mutation entity.
$mutation_resolver = new MutationResolver($annotation_metadata_provider);

// creating the mutation listener
$mutation_listener = new MutationListener($mutation_resolver);

// register the events
$event_manager->addEventListener('prePersist', $entity_changed_listener);
$event_manager->addEventListener('preFlush', $entity_changed_listener);
$event_manager->addEventListener('entityChanged', $mutation_listener);

配置实体

现在我们只需要在实体上放置@Mutation注解。注解有2个选项

  • 策略;这将确定是存储当前状态还是上一个状态在突变中
  • 类;您的突变类的完整命名空间。默认情况下,它是当前类名后缀为Mutation(即Acme\MyEntity默认为Acme\MyEntityMutation)。

此外,您还可以配置实体以成为MutationAware,这是可选的。

use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Criteria;
use Doctrine\ORM\Mapping as ORM;
use Hostnet\Component\EntityMutation\Mutation;
use Hostnet\Component\EntityMutation\MutationAwareInterface;

/**
 * @ORM\Entity
 * @ORM\Table(name="users")
 * @Mutation(
 *     class    = "MyUserEntityMutation",
 *     strategy = "previous"
 * )
 * The above values are equal to the defaults. They are only
 * here to show how you can use them outside of this example
 */
class MyUserEntity implements MutationAwareInterface
{
    ...
    private $id;

    /**
     * @ORM\...
     */
    private $city;

    /**
     * @ORM\...
     */
    private $name;

    /**
     * @ORM\OneToMany...
     * @var ArrayCollection
     */
    private $mutations;

    public function setName($name) { ... }
    public function getName() { ... }

    public function addMutation($element)
    {
        $this->mutations->add($element);
    }

    public function getMutations()
    {
        return $this->mutations;
    }

    /**
     * Used to get the last mutation stored, you might want to change
     * it to return the one before that if your strategy is current.
     */
    public function getPreviousMutation()
    {
        $criteria = (new Criteria())
            ->orderBy(['id' => Criteria::DESC])
            ->setMaxResults(1);

        return $this->mutations->matching($criteria)->current() ? : null;
    }
}

创建突变实体

变异本身就是一个实体。在当前版本中,MutationResolver 仅会在实体和实体变异之间共享字段时返回变异字段。这可以通过添加一个包含共享字段的特性来轻松完成。在这个例子中,将用于存储变异的唯一属性是 $name

构造函数是您应该遵循的少数实际约定之一,以便使用变异。第一个参数是当前管理与实体,其中原始数据是上一个状态(如 doctrine 上次检索时那样处理)并且不受 doctrine 管理。

这样做是为了让您完全控制要存储的哪些字段以及如何存储变异。例如,在某些情况下,您可能想要总结或转换某些字段,如果自动完成而不使用复杂的数据转换器系统,则可能无法完成。

注意:$original_data 是一个非管理实体,仅应用于读取属性。使用第一个参数进行连接。

use Doctrine\ORM\Mapping as ORM;

class MyUserEntityMutation
{
    ...

    /**
     * @ORM\ManyToOne(targetEntity="MyUserEntity", inversedBy="mutations")
     */
    private $user;

    /**
     * @ORM\...
     */
    private $name;

    public function setName($name) { ... }
    public function getName() { ... }

    public function __construct(MyUserEntity $user, MyUserEntity $original_data)
    {
        // link our user to the mutation
        $this->user = $user;

        // populate the mutation with data from the previous state
        $this->name = $original_data->getName();
    }
}

一个完整的工作示例可以在我们的测试中找到,请参见:链接

接下来是什么?

$my_user_entity->setName('Henk'); // was Hans before
$em->flush();
var_dump($my_user_entity->getPreviousMutation()); // shows the state it had with Hans