调用Factory时Laravel记录被删除

Posted

技术标签:

【中文标题】调用Factory时Laravel记录被删除【英文标题】:Laravel record being deleted when calling Factory 【发布时间】:2019-06-02 19:17:18 【问题描述】:

我有两个表 - RolesUsers。在 Roles 内部,我只有一条记录。


  id: 1, name: Employee, timestamps: blahblah

奇怪的是,每当我调用我的用户工厂(它有一个字段 role_id 的外键)时,它都会删除 Roles 表中的记录。它也使工厂实例化的创建失败,说 role_id 外键约束失败。我不知道为什么会这样。

这是用户工厂的代码。我已经对值进行了硬编码,直到我弄明白为止。

$factory->define(App\User::class, function (Faker $faker) 
 return [
    'name' => $faker->name,
    'email' => $faker->unique()->safeEmail,
    'email_verified_at' => now(),
    'password' => Hash::make("12341234"),
    'remember_token' => str_random(10),
    'company_id' => 1,
    'role_id' => 1,
 ];
);

还有错误:

Doctrine\DBAL\Driver\PDOException: SQLSTATE[23000]: 完整性 违反约束:1452 无法添加或更新子行:外国 键约束失败 (app.users, CONSTRAINT users_role_id_foreign 外键 (role_id) 引用 roles (id))

任何帮助将不胜感激。

【问题讨论】:

这个错误说明找不到角色表。此工厂代码在执行角色表之前执行。如果可以使用外键,只需更改数据库表的执行顺序即可。 你执行的命令是什么? 不知道你说的执行顺序是什么意思。我知道它可以找到角色表,因为我可以在 Tinker 中创建和细化角色记录。 【参考方案1】:

您的外键验证似乎是您错误所说的问题。

给定的上下文你的 role_id 似乎是外键,你只是传递一个你永远不会工作的任意值。

要解决此问题,您必须创建一个创建新角色的工厂方法并执行以下操作

$factory->define(App\User::class, function (Faker $faker) 
 return [
    'name' => $faker->name,
    'email' => $faker->unique()->safeEmail,
    'email_verified_at' => now(),
    'password' => Hash::make("12341234"),
    'remember_token' => str_random(10),
    'company_id' => 1,
    'role_id' => factory(Role::class)->create()->id,
 ];
);

PS 确保您的批量分配包含 role_id

【讨论】:

但是在这种假设情况下,如果... factory(Role::class)->create()->id == 1,为什么不将其替换为 1(即当前在表中的记录)有效吗? 你听说过YAGNI吗?其次,您应该能够像factory(Role::class)->create(['role_id' =>1)->id 一样传递role_id。你用你的模型工厂做什么?看看laravel-news.com/learn-to-use-model-factories-in-laravel-5-1 我在特性测试中使用工厂 - 从未听说过 YAGNI,但这只是标准 TDD。我正在使用模型工厂作为用户执行各种功能。这里的主要怪异再次是调用工厂删除角色表中具有匹配 id 的记录,然后抛出错误。 当你运行测试时,laravel 使用RefreshDatabase trait,它会在你每次运行测试时刷新数据库。确保您有不同的数据库用于测试或内存存储。看看这个***.com/questions/49503921/… 如何设置你的测试 希望我的评论有意义。我推荐拉拉卡斯特。学习 laravel 的所有内容并使用 laravel 进行测试的好地方。祝你好运【参考方案2】:

虽然我无法弄清楚与此相关的确切奇怪之处,但我相信它与 phpUnit 的数据库配置有关。我在我的 phpunit.xml 中添加了以下几行,解决了这个问题。

还值得一提的是,role 实体已被删除,因为测试使用的是 RefreshDatabase

    <env name="DB_CONNECTION" value="sqlite" />
    <env name="DB_DATABASE" value=":memory:" />

【讨论】:

@usrNotFound 指出您通常使用不同的数据库进行测试。 是的 - 我假设 phpunit 的默认数据库配置与 Laravel 的不同,这可能是导致问题的原因。话虽如此,外国约束为何特别失败仍然令人困惑。 它与硬编码 vs 工厂生成的 role_id 无关。

以上是关于调用Factory时Laravel记录被删除的主要内容,如果未能解决你的问题,请参考以下文章

从 laravel 调用 HTTPS 请求到外部 API

计数记录多表的最佳方法 - Laravel

在 Factory Laravel 中创建 JWTAuth 令牌

Laravel - 软删除没有生效

在运行 laravel phpunit testcase 时,我在 Model.php 第 1249 行收到错误“调用 null 上的成员函数 connection()”

在 Laravel JetStream 中删除 Bootstrap 并安装 TailwindCSS 的正确方法