Symfony+API Platform+Doctrine软删除子实体后父实体查询问题求助
解决方案:在关联实体上控制Gedmo软删除过滤器的生效范围
针对你的问题,核心是要让Gedmo软删除过滤器在单独查询OrderItem时生效,在查询Order关联的OrderItem时不生效,可以通过以下步骤配置:
1. 给Order实体的关联字段禁用软删除过滤
在Order实体的orderItems关联注解中,添加@Gedmo\SoftDeleteable(filterable=false),这样查询Order时,Doctrine不会过滤已被软删除的OrderItem,保证父实体能完整关联到所有子实体:
// src/Entity/Order.php use Gedmo\Mapping\Annotation as Gedmo; use Doctrine\ORM\Mapping as ORM; /** * @ORM\Entity(repositoryClass=OrderRepository::class) */ class Order { // ... /** * @ORM\OneToMany(targetEntity=OrderItem::class, mappedBy="order", cascade={"persist", "remove"}) * @Gedmo\SoftDeleteable(filterable=false) */ private $orderItems; // ... }
2. 保持OrderItem实体的软删除配置不变
确保OrderItem实体上的软删除注解正常启用,这样单独查询OrderItem列表时,自动过滤已标记删除的条目:
// src/Entity/OrderItem.php use Gedmo\SoftDeleteable\Traits\SoftDeleteableEntity; use Gedmo\Mapping\Annotation as Gedmo; use Doctrine\ORM\Mapping as ORM; /** * @ORM\Entity(repositoryClass=OrderItemRepository::class) * @Gedmo\SoftDeleteable(fieldName="deletedAt", timeAware=false) */ class OrderItem { use SoftDeleteableEntity; // 包含deletedAt字段和相关逻辑,也可手动定义该字段 /** * @ORM\ManyToOne(targetEntity=Order::class, inversedBy="orderItems") * @ORM\JoinColumn(nullable=false) */ private $order; // ... }
3. 配合API Platform的过滤控制(可选)
如果需要在API层面确保单独请求OrderItem资源时只返回未删除的条目,可以给OrderItem添加API Platform的搜索过滤器,强制过滤deletedAt为null的记录:
// src/Entity/OrderItem.php use ApiPlatform\Metadata\ApiFilter; use ApiPlatform\Doctrine\Orm\Filter\SearchFilter; /** * @ApiResource() * @ApiFilter(SearchFilter::class, properties={"deletedAt": "isNull"}) * @ORM\Entity(repositoryClass=OrderItemRepository::class) * @Gedmo\SoftDeleteable(fieldName="deletedAt", timeAware=false) */ class OrderItem { // ... }
4. 排查查询报错的额外注意点
如果之前查询Order时报错,大概率是因为懒加载OrderItem时触发了软删除过滤器,导致Doctrine无法找到被标记删除的实体。通过步骤1禁用关联字段的过滤后,查询Order时会加载所有关联的OrderItem(包括已删除的),就能解决这个问题。如果仍有报错,检查:
- 关联的
fetch模式,必要时设置fetch="EAGER"避免懒加载 - 确保OrderItem的
deletedAt字段正确映射,没有数据库层面的约束问题
内容的提问来源于stack exchange,提问作者AdiOverRide
相关产品推荐
相关产品推荐

