DRY:如何在 Symfony2 项目的多个实体中使用此代码?特质?
DRY: how to use this code in several entities accross Symfony2 project? 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 被持久化(意味着从数据库中完全删除)到数据库,对吧?
还可以说我将在 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());
}
}
}
我的问题|对此有疑问:
- 上面的代码是否正确?
- Doctrine 每次调用监听器时是否
$deletedItems
清理?
- 如何return
$deletedItems
以便在控制器上捕获它并发送回视图?
- 我是否也需要定义订阅者?为什么?
这对我来说是新话题,所以我需要一些建议
关注@PeterPopelyshko评论这是我的解决方案,只需定义一个抽象class 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
}
不要
业务逻辑不属于实体。
Traits 也不会帮助你,因为虽然复制代码是一件坏事,但滥用 traits 是 imo 更糟的。
我曾经想知道我是否应该使用 traits 并在 codereview 上发布了一个问题 (https://codereview.stackexchange.com/a/74195/56686)。我还没有在我的应用程序中偶然发现特征的有效用例。
做一个服务
我建议你做一个服务,把你的逻辑放在那里。
文档:http://symfony.com/doc/current/book/service_container.html
因为你不能从 doctrine 生命周期回调中调用 symfony 服务,你必须放弃那些。
您可能不想启动您选择的搜索引擎来寻找分步教程。
我有这段重复的代码,将在我的 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 被持久化(意味着从数据库中完全删除)到数据库,对吧?
还可以说我将在 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());
}
}
}
我的问题|对此有疑问:
- 上面的代码是否正确?
- Doctrine 每次调用监听器时是否
$deletedItems
清理? - 如何return
$deletedItems
以便在控制器上捕获它并发送回视图? - 我是否也需要定义订阅者?为什么?
这对我来说是新话题,所以我需要一些建议
关注@PeterPopelyshko评论这是我的解决方案,只需定义一个抽象class 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
}
不要
业务逻辑不属于实体。
Traits 也不会帮助你,因为虽然复制代码是一件坏事,但滥用 traits 是 imo 更糟的。
我曾经想知道我是否应该使用 traits 并在 codereview 上发布了一个问题 (https://codereview.stackexchange.com/a/74195/56686)。我还没有在我的应用程序中偶然发现特征的有效用例。
做一个服务
我建议你做一个服务,把你的逻辑放在那里。 文档:http://symfony.com/doc/current/book/service_container.html
因为你不能从 doctrine 生命周期回调中调用 symfony 服务,你必须放弃那些。
您可能不想启动您选择的搜索引擎来寻找分步教程。