使用SoftDeleteable背后的连贯逻辑

时间:2014-09-17 00:40:23

标签: php symfony soft-delete stofdoctrineextensions

每个人都知道SoftDeleteable是一个学说延伸:

  

允许行为“软删除”对象,过滤它们   通过使用时间戳标记它们来选择时间,但不是显式   将它们从数据库中删除。

现在考虑到这一点,在表中插入新行并将上面标记为已删除但实际存在时,这将是一致的逻辑吗?

关键是我最近被迫在应用程序中使用这种行为,但是当我插入新记录时,逻辑上,当存在时,我得到了这样的错误:

  

执行“INSERT INTO fos_user(用户名,   username_canonical,email,email_canonical,enabled,salt,password,   last_login,locked,expired,expires_at,confirmation_token,   password_requested_at,roles,credentials_expired,   credentials_expire_at,deletedAt,createdAt,updatedAt)VALUES   (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)'与params [“admin1”   “admin1”“admin”,“admin”,1,“8ycal2x0eewwg0gw0o0gcw884ooossg”,   “886mLvLTi1yPdSBTR9Cfi + + a3lvideQ4pw89ZHDOWVz86kJqXjx7C1   1ZIwTvzET7N1Fk \ / yHsw10z3Cjm9k + m \ / g ==“,null,0,0,null,   null,null,'a:2:{i:0; s:16:\“ROLE_PROFILE_ONE \”i:1,s:16:\   “ROLE_PROFILE_TWO \”;}“,0,null,null,”09/12/2014 18:16:01   “”9/12/2014 18:16:01“]:

     

SQLSTATE [23000]:完整性约束违规:1062重复条目   'admin1'用于键'UNIQ_957A647992FC23A8'

我的问题是,你如何处理 SoftdDeleteable 来输入新记录?一个例子,你的工作或更少的想法会很好地来到我身边,并会有所帮助。

1 个答案:

答案 0 :(得分:2)

如果你想保留原版,那么你需要找到一些方法来确保以前没有使用过这个独特的领域。我认为最简单的方法是为您的用户字段使用自定义存储库,并在搜索之前禁用软删除过滤器。

默认情况下,UniqueEntity使用findBy和类的存储库集,但默认情况下禁用过滤器来创建自己的方法是有意义的,以避免在保持常规方法不变的情况下使用约束。

当您使用FOSUserBundle时(或者从表名fos_user看来似乎如此),您可以在映射中设置repositoryClass(XML是一大堆混乱,但您可以看到它here )...

// Annotation
@ORM\Entity(repositoryClass="Acme\StoreBundle\Entity\ProductRepository")

//YAML
Acme\UserBundle\Entity\User:
    type: entity
    repositoryClass: Acme\UserBundle\Entity\UserRepository

然后在您的UserRepository中添加findIncludingSoftdeletedBy方法,禁用软删除过滤器,如...

namespace Acme\UserBundle\Entity;

use Doctrine\ORM\EntityRepository;

class UserRepository extends EntityRepository
{
    /**
     * Finds users by a set of criteria including sofdeleted.
     *
     * @param array      $criteria
     * @param array|null $orderBy
     * @param int|null   $limit
     * @param int|null   $offset
     *
     * @return array The objects.
     */
    public function findIncludingSoftdeletedBy(
        array $criteria, array $orderBy = null, $limit = null, $offset = null
    )
    {
        // Get array of enabled filters
        $enabledFilters = $this->em->getFilters()->getEnabledFilters();

        // If softdeleteable (or soft-deleteable depending on config) 
        // is in array of enabled filters disable it
        if (array_key_exists('softdeleteable', $endabledFilters)) {
            // disabled softdeleteable filter ($this->em being entity manager)
            $this->_em->getFilters()->disable('softdeleteable');
        }

        // return regular "findBy" including softdeleted users
        return $this->findBy($criteria, $orderBy, $limit, $offset);
    }
}

<强>更新

我忘了这一点。

然后,您需要创建自己的验证文件,以引用此新验证约束。 (对于FOSU​​serBundle和YAML(我更喜欢YAML,XML看起来像是一本物理书在我的屏幕上生病了))。

Acme\UserBundle\Entity\User:
    constraints:
        - Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity:
            fields: usernameCanonical
            errorPath: username
            message: fos_user.username.already_used
            // Your method instead of the default "findBy"
            method: findIncludingSoftdeletedBy
            groups: [ Registration, Profile ]
        - Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity:
            fields: emailCanonical
            errorPath: email
            message: fos_user.email.already_used
            // Your method instead of the default "findBy"
            method: findIncludingSoftdeletedBy
            groups: [ Registration, Profile ]

有关UniqueEntity约束的更多信息,请参阅docs,具体为..

字段
类型:数组| string [默认选项]

此必填选项是此实体应该唯一的字段(或字段列表)。例如,如果您在单个UniqueEntity约束中同时指定了电子邮件和名称字段,那么它将强制使用唯一的组合值(例如,两个用户可以拥有相同的电子邮件,只要他们不具有相同的也是)。

如果您需要要求两个字段单独使用(例如,唯一的电子邮件和唯一的用户名),则使用两个UniqueEntity条目,每个条目都包含一个字段。