ang3/doctrine-orm-batch-process

Doctrine ORM 批处理组件

v1.0.0 2023-06-19 14:58 UTC

This package is auto-updated.

Last update: 2024-09-19 17:51:39 UTC


README

Code Quality PHPUnit Tests Latest Stable Version Latest Unstable Version Total Downloads

此组件帮助您在 Doctrine ORM 事务的上下文中处理 批处理

批量操作的主要问题通常不是耗尽内存,这正是这里提出的策略提供的帮助。 -- Doctrine ORM 文档

批处理组件允许您使用一些高级特性轻松构建批量操作。

安装

打开命令行控制台,进入您的项目目录,并执行以下命令以下载此捆绑包的最新稳定版本

$ composer require ang3/doctrine-orm-batch-process

此命令需要您全局安装了 Composer,具体请参阅 Composer 文档中的安装章节

使用方法

批处理是一个使用 迭代器 执行一些逻辑的 循环,其中 处理器 是可选的。迭代器是强制性的,处理器是可选的。

在所有情况下,当缓冲区大小达到(默认为20)时,实体管理器都会被刷新和清除。

创建一个过程

要创建一个过程,使用带有实体管理器和迭代器的构造函数,或者使用定义的静态快捷方法之一来满足您的需求

use Ang3\Doctrine\ORM\Batch\BatchProcess;

$myProcess = new BatchProcess($entityManager, $myIterator, $myHandler = null, $bufferSize = 20);

// For chaining calls
$myProcess = BatchProcess::create($entityManager, $myIterator);

/*
 * SHORTCUT METHODS FOR BUILT-IN ITERATORS
 */

// Iterate from identified entities
$myProcess = BatchProcess::iterateEntities($entityManager, $entityFqcn, array $identifiers);

// Iterate from an ORM query or query builder instance
$myProcess = BatchProcess::iterateQueryResult($query);

// Iterate from iterable or callable
$myProcess = BatchProcess::iterateData($entityManager, iterable|\Closure $data);

执行过程

$nbIterations = $myProcess->execute();

高级选项

此组件提供了一些有用的高级选项。

处理器

处理器是一个实现了接口 Ang3\Doctrine\ORM\Batch\Handler\BatchHandlerInterface 的类。这个类在每次迭代时被调用。它允许您持久化/删除实体,或者使用自定义处理器执行任何操作。

此接口描述了批处理过程调用的方法:__invoke(\Ang3\Doctrine\ORM\Batch\BatchIteration $iteration)

该组件提供了一些有用的内置处理器。

持久化实体处理器

此处理器将实体持久化到数据库中。

use Ang3\Doctrine\ORM\Batch\Handler\PersistEntityHandler;

$myHandler = PersistEntityHandler::new()
    // Handler options...
    ->skipInsertions() // Ignore new entities (without ID)
    ->skipUpdates() // Ignore stored entities (with ID)
    ->onPrePersist($myCallable) // This callable is called BEFORE each persist.
    ->onPostPersist($myCallable) // This callable is called AFTER each persist.
;

可调用参数

  1. object 实体
  2. Ang3\Doctrine\ORM\Batch\BatchIteration 迭代

删除实体处理器

此处理器将实体从数据库中删除。

use Ang3\Doctrine\ORM\Batch\Handler\RemoveEntityHandler;

$myHandler = RemoveEntityHandler::new()
    // Handler options...
    ->onPreRemove($myCallable) // This callable is called BEFORE each removing.
    ->onPostRemove($myCallable) // This callable is called AFTER each removing.
;

可调用参数

  1. object 实体
  2. Ang3\Doctrine\ORM\Batch\BatchIteration 迭代

可调用处理器

此处理器包含一个简单的可调用对象。

use Ang3\Doctrine\ORM\Batch\Handler\CallableHandler;

$myHandler = CallableHandler::new($myCallable);

可调用参数

  1. mixed 迭代器数据
  2. Ang3\Doctrine\ORM\Batch\BatchIteration 迭代

链式处理器

此处理器允许您按特定顺序链式调用处理器。

use Ang3\Doctrine\ORM\Batch\Handler\ChainHandler;

$myHandler = ChainHandler::new()
    // Handler options...
    ->append($myHandler1) // Add a handler at the end of the chain
    ->prepend($myHandler2) // Add a handler at the beginning of the chain
    ->clear() // Remove all handlers from the chain
;

自定义处理器

创建一个实现接口 Ang3\Doctrine\ORM\Batch\Handler\BatchHandlerInterface 的类。

namespace App\Doctrine\Batch\Handler;

use Ang3\Doctrine\ORM\Batch\Handler\BatchHandlerInterface;

final class MyHandler implements BatchHandlerInterface
{
    public function __invoke(Iteration $iteration): void
    {
        // Data from the process iterator
        $data = $iteration->getData();
        
        // You can retrieve the entity manager from the iteration.
        $em = $iteration->getEntityManager();
    }
}

使用 Ang3\Doctrine\ORM\Batch\Handler\BatchHandlerTrait 特性来启用选项

// ...
final class MyHandler implements BatchHandlerInterface
{
    // If you want to add options:
    use BatchHandlerTrait;
    
    // Internal constants used to define options
    private const OPTION_ENABLED = 'enabled';
    
    public function __invoke(Iteration $iteration): void
    {
        // Retrieves option values
        $enabled = $this->getOption(self::OPTION_ENABLED);
        
        // your logic with the option...
    }

    // Return the handler to allow chaining calls
    public function enableOption(bool $enabled = true): self
    {
       $this->setOption(self::OPTION_ENABLED, $enabled);
    
       return $this;
    }
}

缓冲区大小

您可以修改默认的缓冲区大小

$myProcess->setBufferSize(50); // By default: 20

禁用 ID 生成器

您可以关闭一个或多个实体的 ID 生成器,这对于迁移数据很有用。

$myProcess->disableIdGenerator(MyClass1::class, MyClass2::class/*, ...*/);

您可以恢复以下禁用的 ID 生成器

$myProcess->restoreIdGenerator(MyClass1::class, MyClass2::class/*, ...*/);

// ... Or restore all directly
$myProcess->restoreAllIdGenerators();

事务实体

实体管理器可能会多次被清除。这就是为什么在执行过程中,所有在执行前加载的实体都将从管理器中分离。

$myLoadedEntity; // attached
$myProcess->execute();
dump($myLoadedEntity); // Probably detached - If you persist, a new entity could be created!

为了避免重新加载您的实体,此组件可以帮助您通过 变量引用 将实体保持在内存中,以便自动重新加载它。

$myLoadedEntity; // attached
$myProcess
    ->addTransactionalEntity($myLoadedEntity) // This variable is passed by reference
    ->execute();
dump($myLoadedEntity); // reloaded by the process on each flush/clear

在刷新时

您可以将一个可调用对象传递给批处理,以便在每次刷新/清除操作上执行一些逻辑。

$myProcess->onFlush($myCallable);

可调用参数

  1. Ang3\Doctrine\ORM\Batch\BatchProcess 当前批处理
  2. Ang3\Doctrine\ORM\Batch\BatchIteration|null 迭代(在最后刷新/清空时为NULL)。