comstar / entity-audit-bundle
Doctrine 实体审计
Requires
- doctrine/orm: ~2.1
Requires (Dev)
- symfony/framework-bundle: ~2.0
This package is not auto-updated.
Last update: 2024-09-28 14:58:07 UTC
README
这个 Doctrine 2 扩展受到 Hibernate Envers 的启发,允许对实体及其关联进行完全版本控制。
Credits to simplethings/EntityAudit for a nice audit bundle for Symfony2 entities. This
fork was created to allow more extensability from the Event Listeners.
它如何工作?
有几种不同的方法可以对数据库表进行审计或版本控制。此扩展为每个审计的实体表创建一个后缀为 "_audit" 的镜像表。除了审计实体的所有列外,还有两个额外的字段
- rev - 包含从 "revisions" 表生成的全局修订号。
- revtype - 包含 'INS'、'UPD' 或 'DEL' 中的一个,作为该修订日志条目是由哪种数据库操作引起的提示。
全局修订表包含 id、时间戳、用户名和更改注释字段。
使用这种方法,可以在特定时间点对应用程序及其对关联的更改进行版本控制。
此扩展挂钩到 SchemaTool 生成过程,以便自动为您的审计实体创建必要的 DDL 语句。
安装(在 Symfony2 应用程序中)
在 AppKernel.php 中注册 Bundle
public function registerBundles()
{
$bundles = array(
//...
new Comstar\EntityAudit\ComstarEntityAuditBundle(),
//...
);
return $bundles;
}
自动加载
'Comstar\\EntityAudit' => __DIR__.'/../vendor/bundles/',
加载扩展 "comstar_entity_audit" 并指定要审计的实体(目前看起来很丑!)
comstar_entity_audit:
audited_entities:
- MyBundle\Entity\MyEntity
- MyBundle\Entity\MyEntity2
调用 ./app/console doctrine:schema:update --dump-sql 以查看更新方案队列中的新表。
注意:EntityAudit 目前仅支持名为 "default" 的 DBAL 连接和 EntityManager。
安装(独立使用)
对于独立使用,您必须将要审计的实体类名称传递给 MetadataFactory 实例,并配置两个事件监听器。
<?php
use Doctrine\ORM\EntityManager;
use Doctrine\Common\EventManager;
use Comstar\EntityAudit\AuditConfiguration;
use Comstar\EntityAudit\AuditManager;
$auditconfig = new AuditConfiguration();
$auditconfig->setAuditedEntityClasses(array(
'Cosmtar\EntityAudit\Tests\ArticleAudit',
'Comstar\EntityAudit\Tests\UserAudit'
));
$evm = new EventManager();
$auditManager = new AuditManager($auditconfig);
$auditManager->registerEvents($evm);
$config = new \Doctrine\ORM\Configuration();
// $config ...
$conn = array();
$em = EntityManager::create($conn, $config, $evm);
用法
使用 Comstar\EntityAudit\AuditReader 实例查询审计信息。
在 Symfony2 中,AuditReader 已注册为服务 "comstar_entityaudit.reader"
<?php
class DefaultController extends Controller
{
public function indexAction()
{
$auditReader = $this->container->get("comstar_entityaudit.reader");
}
}
在独立应用程序中,您可以从审计管理器创建审计读取器
<?php
$auditReader = $auditManager->createAuditReader($entityManager);
查找特定修订版本的实体状态
此命令还返回给定修订版本中实体的状态,即使该实体的最后一次更改发生在给定的修订版本之前
<?php
$articleAudit = $auditReader->find('Comstar\EntityAudit\Tests\ArticleAudit', $id = 1, $rev = 10);
通过 AuditReader#find() 创建的实例 不会 注入到 EntityManagers UnitOfWork 中,如果需要在旧版本中将它重新附加到持久化上下文,则需要将其合并到 EntityManager 中。
查找已审计实体的修订历史
<?php
$revisions = $auditReader->findRevisions('Comstar\EntityAudit\Tests\ArticleAudit', $id = 1);
修订版本具有以下 API
class Revision
{
public function getRev();
public function getTimestamp();
public function getUsername();
}
查找特定修订版本中更改的实体
<?php
$changedEntities = $auditReader->findEntitiesChangedAtRevision( 10 );
更改实体具有以下 API
<?php
class ChangedEntity
{
public function getClassName();
public function getId();
public function getRevisionType();
public function getEntity();
}
查找已审计实体的当前修订版本
<?php
$revision = $auditReader->getCurrentRevision('Comstar\EntityAudit\Tests\ArticleAudit', $id = 3);
设置当前用户名
每个修订版本都会自动保存更改它的用户名。为此,您必须设置用户名。在 Symfony2 网络上下文中,用户名自动设置为当前安全令牌中的用户名。
在独立应用程序或 Symfony 命令中,您必须使用 AuditConfiguration 将用户名设置为特定值
<?php
// Symfony2 Context
$container->get('comstar_entityaudit.config')->setCurrentUsername( "beberlei" );
// Standalone App
$auditConfig = new \Comstar\EntityAudit\AuditConfiguration();
$auditConfig->setCurrentUsername( "beberlei" );
查看审计
提供了一个默认的 Symfony2 控制器,它提供了基本查看审计数据的功能。
要使用此控制器,请导入路由 (别忘了确保您设置的名称是安全的,这样只有适当的用户才能访问)
# app/config/routing.yml
comstar_entity_audit:
resource: "@ComstarEntityAuditBundle/Resources/config/routing.yml"
prefix: /audit
这为您提供了几个不同的路由
- comstar_entity_audit_home -- 显示修订版本的分页列表,包括它们的日期和时间以及执行修订的用户
- comstar_entity_audit_viewrevision -- 显示在特定修订版本中修改的类
- comstar_entity_audit_viewentity -- 显示指定实体被修改的修订版本
- comstar_entity_audit_viewentity_detail -- 显示指定实体在指定修订版本的数据
- comstar_entity_audit_compare -- 允许您比较两个修订版本之间实体的更改
扩展以用于 Gedmo/SoftDeletable
而不是在 Gedmo/DoctrineExtensionsBundle 中内置捆绑要求,我决定在这里添加扩展此捆绑的说明。您首先需要在项目中创建一个新的捆绑,并通过 getParent() 方法扩展 ComstarEntityAuditBundle。您还需要扩展 build() 方法,以便我们可以添加一个编译器传递以覆盖 comstar_entityaudit.log_revisions_listener 并使用我们自己的相同版本。
# Acme/AcmeDemoBundle/AcmeDemoBundle.php
class AcmeDemoBundle extends Bundle
{
public function getParent()
{
return 'ComstarEntityAuditBundle';
}
public build(ContainerBuilder $container)
{
parent::build($container);
$container->addCompilerPass(new OverrideServiceCompilerPass());
}
}
现在我们需要在 AcmeDemoBundle 的 DependencyInjection 目录中创建编译器传递。
# Acme/AcmeDemoBundle/DependencyInjection/Compiler/OverrideCompilerPass.php
namespace Acme\AcmeDemoBundle\DependencyInjection\Compiler;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
class OverrideServiceCompilerPass implements CompilerPassInterface
{
public function process(ContainerBuilder $container)
{
$definition = $container->getDefinition('comstar_entityaudit.log_revisions_listener');
$definition->setClass('Acme\AcmeDemoBundle\EventListener\LogRevisionsListener');
}
}
随着服务容器类的更改,我们现在必须创建我们的事件监听器,并在 Acme/AcmeDemoBundle 的 EventListener 目录中执行此操作。我们必须更改 use 语句以添加 Gedmo SoftDeletableListener,更新 getSubscribedEvents() 方法,并添加 postSoftDelete() 方法。
# Acme/AcmeDemoBundle/EventListener/LogRevisionsListener.php
use Gedmo\SoftDeleteable\SoftDeleteableListener;
class LogRevisionsListener implements EventSubscriber
{
...
public function getSubscribedEvents()
{
return array(Events::onFlush, Events::postPersists, Events::postUpdate, SoftDeletableListener::POST_SOFT_DELETE);
}
public function postSoftDelete(LifecycleEventArgs $eventArgs)
{
// onFlush was not executed before, initialize everything
$this->em = $eventArgs->getEntityManager();
$this->conn = $this->em->getConnection();
$this->uow = $this->em->getUnitOfWork();
$this->platform = $this->conn->getDatabasePlatform();
$this->revisionId = null; // reset revision
$entity = $eventArgs->getEntity();
$class = $this->em->getClassMetadata(get_class($entity));
if (!$this->metadataFactory->isAudited($class->name)) {
return;
}
$entityData = array_merge($this->getOriginalEntityData($entity), $this->uow->getEntityIdentifier($entity));
$this->saveRevisionEntityData($class, $entityData, 'SDEL');
}
}
在数据库中软删除的实体现在将在修订表中记录带有 SDEL 标志,这样我们就可以知道谁软删除了记录以及何时删除。
待办事项
- 目前仅适用于自增数据库
- 需要适当的元数据映射,允许禁用字段和关联的版本控制。
- 它不与联合表继承(单表继承应该可以工作,但未测试)兼容
- 多对多关联未被版本化