SoftDeleteable使用背后的连贯逻辑


Coherent logic behind the use of SoftDeleteable

每个人都知道SoftDeleteable是一个条令扩展:

这允许行为"软删除"对象,在通过将时间戳标记为而非显式标记来选择时间从数据库中删除它们。

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

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

执行"INSERT INTO fos_user(username,用户名_canonical,电子邮件,电子邮件_canonic,已启用,salt,密码,last_login,已锁定,已过期,expires_at,confirmation_token,password_requested_at,角色,凭据已过期,credentials_expire_at、deletedAt、createdAt、updatedAt)值("admin1"admin"、"admin",1,"8ycal2xeewwg0gw0o0gcw884oossg","886mLvLTi1yPdSBTR9Cfi++a3lvideQ4pw89ZHDOWVz86kJqXjx7C11ZIwTvzET7N1Fk''/yHsw10z3Cjm9k+m''/g==",null,0,0,null,null,null,'a:2:{i:0;s:16:''"ROLE_PROFILE_ONE''"i:1,s:16:''"ROLE_file_TWO''";}",0,null,null,"2014年12月9日18:16:01"2014年9月12日18:16:01"]:

SQLSTATE[23000]:完整性约束冲突:1062重复条目密钥"UNIQ_957A6479992FC23A8"的"admin1"

我的问题是,如何处理SoftdDeleteable以输入新记录?一个你所做的或更少想法的例子会很好地出现在我面前,并会有所帮助。

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

默认情况下,UniqueEntity使用findBy和类的存储库集,但创建自己的方法时默认禁用筛选器是有意义的,这样可以避免在保留常规方法不变的情况下处理约束。

当您使用FOSUserBundle时(或者从表名fos_user中可以看出),您可以在映射中设置repositoryClass(XML是一堆混乱的东西,但您可以在这里看到它)。。。

// 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);
    }
}

更新

我忘了这一点。

然后,您需要创建自己的验证文件,该文件将引用这个新的验证约束。(对于FOSUserBundle和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约束的更多信息,请参阅文档,特别是。。

字段
type:array|string[默认选项]

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

如果您需要两个字段单独唯一(例如,一封唯一的电子邮件和一个唯一的用户名),您可以使用两个UniqueEntity条目,每个条目都有一个字段