Php 使用SoftDeleteable后的一致逻辑
众所周知,这是一种学说的延伸: 这允许行为“软删除”对象,同时对它们进行过滤 通过使用时间戳将时间标记为,而不是显式地选择时间 从数据库中删除它们 考虑到这一点,在表中插入新行并将上面标记为已删除但实际存在时,哪种逻辑是一致的 问题是,我最近被迫在应用程序中使用此行为,但当我插入新记录时,逻辑上,当一条记录存在时,我会出现如下错误: 执行“插入fos_用户(用户名、, 用户名\u规范、电子邮件、电子邮件\u规范、已启用、salt、密码、, 上次登录、锁定、过期、过期、确认令牌、, 密码\u已请求\u在,角色,凭据\u已过期, 凭据(过期时间、删除日期、创建日期、更新日期)值 (?,?,?,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,)带参数[“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\u PROFILE\u ONE\'i:1,s:16:\ “角色简介”,0,空,空,“09/12/2014 18:16:01 “2014年9月12日18:16:01”]: SQLSTATE[23000]:完整性约束冲突:1062重复项 键“UNIQ_957A647992FC23A8”的“admin1”Php 使用SoftDeleteable后的一致逻辑,php,symfony,soft-delete,stofdoctrineextensions,Php,Symfony,Soft Delete,Stofdoctrineextensions,众所周知,这是一种学说的延伸: 这允许行为“软删除”对象,同时对它们进行过滤 通过使用时间戳将时间标记为,而不是显式地选择时间 从数据库中删除它们 考虑到这一点,在表中插入新行并将上面标记为已删除但实际存在时,哪种逻辑是一致的 问题是,我最近被迫在应用程序中使用此行为,但当我插入新记录时,逻辑上,当一条记录存在时,我会出现如下错误: 执行“插入fos_用户(用户名、, 用户名\u规范、电子邮件、电子邮件\u规范、已启用、salt、密码、, 上次登录、锁定、过期、过期、确认令牌、, 密码\u已请求
我的问题是,您如何处理SoftdDeleteable以输入新记录?举一个例子,说明你所做的事情或更少的想法,对我来说会很有帮助 如果您想保留原始字段,那么您需要找到某种方法来确保以前没有使用过唯一字段。我认为最简单的方法是为用户字段使用自定义存储库,并在搜索之前禁用softdeleteable过滤器 默认情况下,uniquentity使用findBy和为类设置的存储库,但创建自己的方法时默认禁用过滤器是有意义的,这样可以避免在保留常规方法不变的情况下处理约束 当您使用FOSUserBundle时(或者从表名
fos\u user
),您可以在映射中设置repositoryClass(XML是一堆乱七八糟的东西,但您可以看到它)
然后在您的UserRepository
中添加您的findingludingsoftdeletedby
方法禁用softdeletable过滤器,如
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在我的屏幕上看起来像一本物理书)
有关Uniquentity约束的更多信息,请参见,特别是 字段
类型:数组|字符串[默认选项] 此必填选项是此实体应唯一的字段(或字段列表)。例如,如果在单个Uniquentity约束中同时指定了“电子邮件”和“名称”字段,则将强制使用“唯一”的组合值(例如,两个用户可以拥有相同的电子邮件,只要他们没有相同的名称)
如果您需要要求两个字段单独唯一(例如,唯一的电子邮件和唯一的用户名),您可以使用两个Uniquentity条目,每个条目都有一个字段。是否要保留原始的“softdeleted”字段行,不允许重复用户名或删除原始用户名并完全替换?@Qoop好吧,我的想法是保留原始用户名,这是SoftDeleteable背后的想法还是not?我认为这背后没有具体的想法,它可以允许您先软删除,然后硬删除,或者软删除并保留记录。我已经添加了一个答案。这种方法只适用于一个专栏,但是如果其他专栏也是独一无二的,会发生什么呢?我需要把同样的代码重复几次,对吗?例如,在FOSUserBundle中,正如您之前所说,我使用的,
username
和email
是唯一的,但是我也有其他字段,因为我的User
类从BaseUser
扩展而来,那么在这种情况下如何使用呢?从您在对象中设置的字段及其值,然后将uniquentity
约束构建和$criteria
数组传递给方法,你所要做的就是把已经存在的东西背起来,并将禁用功能添加到softdeleteable过滤器中。因此,只需以通常的方式使用uniquentity
约束,但要使用方法集。它不起作用!因为在您的代码中我看不到$em
是在哪里定义的,所以我将您的代码行更改为:$this->getEntityManager()->getFilters()->disable('soft-deletable')返回此筛选器“软可删除”的code>未启用。
因此某些内容不起作用。另一方面,如果我对这行进行注释,则会显示重复的相同错误,有什么建议吗?对不起,可能不好。那只是文件的复制和粘贴。我不知道为什么它不起作用。这可能是因为您禁用了过滤器两次(每次调用一次,但已禁用)。检查过滤器是否已启用可以为您完成此工作。我会更新。也可能是因为您使用的是StofDoctrineExtensionsBundle
,它将过滤器注册为softdeletable
,而不是像原始Gedmo
文档那样的softdeletable
。请让我知道,我会相应地更新我的答案。
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);
}
}
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 ]