DRY:如何在Symfony2项目中的几个实体中使用此代码?特点?

时间:2015-01-23 12:26:58

标签: php symfony lifecycle traits

我有这个重复的代码片段,将在我的Symfony2项目中的多个实体中使用,因此可以应用某种DRY,如果可能的话,我可以使用在PHP Traits中思考。

private static $preDeletedEntities;// static array that will contain entities due to deletion.
private static $deletedEntities;// static array that will contain entities that were deleted (well, at least the SQL was thrown).

/**
 * This callback will be called on the preRemove event
 * @ORM\PreRemove
 */
public function entityDueToDeletion()
{
    // This entity is due to be deleted though not deleted yet.
    self::$preDeletedEntities[] = $this->getId();
}

/**
 * This callback will be called in the postRemove event
 * @ORM\PostRemove
 */
public function entityDeleted()
{
    // The SQL to delete the entity has been issued. Could fail and trigger the rollback in which case the id doesn't get stored in the array.
    self::$deletedEntities[] = $this->getId();
}

public static function getDeletedEntities()
{
    return array_slice(self::$preDeletedEntities, 0, count(self::$deletedEntities));
}

public static function getNotDeletedEntities()
{
    return array_slice(self::$preDeletedEntities, count(self::$deletedEntities)+1, count(self::$preDeletedEntities));
}

public static function getFailedToDeleteEntity()
{
    if(count(self::$preDeletedEntities) == count(self::$deletedEntities)) {
        return NULL; // Everything went ok
    }

    return self::$preDeletedEntities[count(self::$deletedEntities)]; // We return the id of the entity that failed.
}

public static function prepareArrays()
{
    self::$preDeletedEntities = array();
    self::$deletedEntities = array();
}

这是我想到的代码:

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\HasLifecycleCallbacks()
 */
trait DeleteLifeCycleCallbacksTrait
{
    // write things here
}

但是将Annotation应用于实体吗?那很好吗?你会做什么来避免不重复代码?

编辑:试图找到最佳方法

@Cerad 用户那里得到一些想法,因为正如文档所说生命周期事件监听器比简单的生命周期回调更强大,那么我将开始玩他们。

所以,首先,这个Lifecycle Callbacks|Listener|Suscribers的目的是存储每个持久化对象的ID,这样我就可以以某种方式获取它并从控制器发送回视图。作为一个简单的可视化示例,让我说我从视图向控制器发送这个值数组(1, 2, 3, 4, 5),并且对于某些X原因,只有1,4和5被持久化(意思是从DB完全删除)到DB,对?

让我们说我将在Producto实体中使用事件监听器。因此,在没有测试并且只是从示例中获取代码的情况下,Listener的代码应该是这样的:

use Doctrine\ORM\Event\LifecycleEventArgs;
use Entity\Producto;

class StoreDeletedIds
{
    private $deletedItems = []; 

    public function postDelete(LifecycleEventArgs $args)
    {
        $entity = $args->getEntity();
        $entityManager = $args->getEntityManager();

        if ($entity instanceof Producto) {
            array_push($deletedItems, $entity->getId());
        }
    }
}

我对这方面的疑问是:

  • 代码是否正常或不是<?li>
  • 每次Doctrine调用侦听器时都清除$deletedItems吗?
  • 如何返回$deletedItems以便在控制器上捕获它并发送回视图?
  • 我是否还需要定义一个Suscriber?为什么?

这是我不熟悉的主题,所以我需要一些建议

2 个答案:

答案 0 :(得分:1)

关注 @PeterPopelyshko 评论这是我提供的解决方案,只需定义一个抽象类Model\DeleteLifeCycleCallbacks.php并将代码放入其中:

use Doctrine\ORM\Mapping as ORM; // not so sure if this is need here

abstract class DeleteLifeCycleCallbacks
{
    private static $preDeletedEntities;// static array that will contain entities due to deletion.
    private static $deletedEntities;// static array that will contain entities that were deleted (well, at least the SQL was thrown).

    /**
     * This callback will be called on the preRemove event
     * @ORM\PreRemove
     */
    public function entityDueToDeletion()
    {
        // This entity is due to be deleted though not deleted yet.
        self::$preDeletedEntities[] = $this->getId();
    }

    /**
     * This callback will be called in the postRemove event
     * @ORM\PostRemove
     */
    public function entityDeleted()
    {
        // The SQL to delete the entity has been issued. Could fail and trigger the rollback in which case the id doesn't get stored in the array.
        self::$deletedEntities[] = $this->getId();
    }

    public static function getDeletedEntities()
    {
        return array_slice(self::$preDeletedEntities, 0, count(self::$deletedEntities));
    }

    public static function getNotDeletedEntities()
    {
        return array_slice(self::$preDeletedEntities, count(self::$deletedEntities)+1, count(self::$preDeletedEntities));
    }

    public static function getFailedToDeleteEntity()
    {
        if(count(self::$preDeletedEntities) == count(self::$deletedEntities)) {
            return NULL; // Everything went ok
        }

        return self::$preDeletedEntities[count(self::$deletedEntities)]; // We return the id of the entity that failed.
    }

    public static function prepareArrays()
    {
        self::$preDeletedEntities = array();
        self::$deletedEntities = array();
    }
}

然后按如下方式使用:

/**
 * @ORM\Entity
 * @ORM\HasLifecycleCallbacks()
 */
class Producto extends Model\DeleteLifeCycleCallbacks
{
    // entity methods and properties here
}

答案 1 :(得分:0)

不要

业务逻辑不会影响实体。

Traits对你也没有帮助,因为复制代码是件坏事,滥用特征 imo 更糟糕。

我曾经想知道我应该使用特征并在codereview(https://codereview.stackexchange.com/a/74195/56686)上发布一个问题。我还没有偶然发现我的应用程序中的特征的有效用例。

提供服务

我建议您提供服务并将您的逻辑放在那里。 文档:http://symfony.com/doc/current/book/service_container.html

因为您无法从doctrine lifecyclecallbacks调用symfony服务,所以您必须删除它们。

您可能不会激发您选择的搜索引擎来寻找分步教程。