如何用setName创建多个Category?Doctrine Fixture数据异常排查
问题分析
你的代码核心问题是只创建了一个Category实例,循环中反复修改它的名称。Doctrine的持久化机制会把同一个对象的多次persist视为更新操作,所以最终数据库里只会保留最后一次设置的"cpu"分类,之前的"pc""laptop"分类不会被保存,对应的广告自然也关联不上。
修复方案
方案1:直接在循环内创建新Category实例
把new Category()放到循环内部,每次迭代生成一个全新的分类对象:
class AppFixtures extends Fixture { public function load(ObjectManager $manager): void { $names = ['pc', 'laptop', 'cpu']; // 先一次性创建足够的用户,避免循环内重复创建 UserFactory::createMany(9); foreach ($names as $name) { // 每次循环创建新的Category实例 $category = new Category(); $category->setName($name); $manager->persist($category); AdvertisementFactory::createMany(20, [ 'user' => UserFactory::random(), 'category' => $category ]); } $manager->flush(); } }
方案2:使用Foundry的CategoryFactory(更符合工具链)
如果你想改用CategoryFactory来创建指定名称的分类,只需定义Factory并在Fixture中调用即可:
1. 先创建CategoryFactory
namespace App\Factory; use App\Entity\Category; use Zenstruck\Foundry\ModelFactory; final class CategoryFactory extends ModelFactory { protected function getDefaults(): array { return [ 'name' => self::faker()->word(), ]; } protected static function getClass(): string { return Category::class; } }
2. 在Fixture中使用Factory创建指定名称的分类
class AppFixtures extends Fixture { public function load(ObjectManager $manager): void { $names = ['pc', 'laptop', 'cpu']; UserFactory::createMany(9); foreach ($names as $name) { // 创建指定名称的分类 $category = CategoryFactory::new()->create(['name' => $name]); AdvertisementFactory::createMany(20, [ 'user' => UserFactory::random(), 'category' => $category ]); } $manager->flush(); } }
额外说明
- 把用户创建放到循环外,避免每次循环重复生成用户,减少不必要的数据冗余。
- Foundry的
create()方法会自动处理实体的持久化,不需要手动调用$manager->persist(),不过手动调用也不会有冲突。
内容的提问来源于stack exchange,提问作者Tsolmonx
相关产品推荐
相关产品推荐

