Laravel在播种期间没有防备

roejwanj  于 2022-12-14  发布在  其他
关注(0)|答案(2)|浏览(134)

我的口才遇到了一个奇怪的问题。
我有两个有说服力的模型,一个User模型和一个Profile模型,它们都有单独的表,并且有一对一的关系。
我有一个表单,其中传递了这两个模型的数据,所以属于User和Profile的数据出现在表单中。
我尝试从控制器中尽可能干净地执行插入:

$user = $this->users->createUser($request->all());

createUser函数的定义如下

public function createUser(array $data)
{
    $user = new User($data);
    // set some non relevant user options here...
    $user->save();

    $profile = new Profile($data);
    $user->profile()->save($profile);

    return $user;
}

但这会产生一个sql错误,因为雄辩将表单中的所有值分配给两个模型,因此User和Profile都获得了相同的属性,因此雄辩试图插入到给定模型中不存在的列中。
我以为$fillable字段是用来防止这种情况发生的,但我确实在两个模型中都定义了$fillable字段:

// User
protected $fillable = ['email', 'password', ...];

// Profile
protected $fillable = ['first_name', 'last_name', ...];

我也试过这个:(new User)->fill($data),但这不起作用,也不应该起作用,因为fill方法也是从Model构造函数调用的。
在我看来,这不是预期的行为,但话又说回来,我可能误解了fillable的概念。任何见解都将受到赞赏。我知道这可以通过声明我想发送给构造函数的每个键来解决,但这对我来说似乎很混乱。另外,我使用的是laravel v5.2.29

编辑

经过进一步的测试,我得出了这样的结论:这只发生在我运行数据库seeders的时候,在那里我确实使用了这些函数。深入研究,我发现这是非常有意义的,因为运行seed命令“解除”了基本Model类。所以这是预期的行为。
我的问题是,有没有什么方法可以覆盖这个默认值,以便在运行seed命令时模型不会变得“不受保护”,这样我就可以使用我的helper函数来填充我的测试数据库,或者我必须在seeder类中手动正确定义每个数据记录?

vqlkdk9b

vqlkdk9b1#

是的,从一些版本的Laravel 5.2当使用播种模型是未加保护的,正如你所注意到的。事实上,这是相当合理的,它是未加保护的,但如果你想改变它,嗯,这是可能的,但不是那么简单。
以下是您应该执行的步骤:
1.在config/app.php行添加注解Illuminate\Foundation\Providers\ConsoleSupportServiceProvider::class,用你自定义的ConsoleSupportServiceProvider类添加行。
1.创建与原始ConsoleSupportServiceProvider相同的此类(实际上您可以扩展它),但在$providers属性中将Illuminate\Database\SeedServiceProvider更改为自定义类
1.再次创建扩展原始SeedServiceProvider的自定义SeedServiceProvider,现在重写registerSeedCommand以再次创建自定义SeedCommand
1.创建扩展原始SeedCommand的自定义SeedCommand类,现在您需要做的只是更改:

public function fire()
{
    if (! $this->confirmToProceed()) {
      return;
   }

   $this->resolver->setDefaultConnection($this->getDatabase());

   Model::unguarded(function () {
      $this->getSeeder()->run();
   });
}

进入

public function fire()
{
    if (! $this->confirmToProceed()) {
      return;
   }

   $this->resolver->setDefaultConnection($this->getDatabase());

   $this->getSeeder()->run();

}
nwsw7zdq

nwsw7zdq2#

当您手动将$unguarded变量添加到Model类中时,它将被保留。

protected static $unguarded = false;

在上下文中:

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Str;

class Order extends Model
{
    use HasFactory;

    protected static $unguarded = false;  // add this line to your code
    protected $fillable = ['name', 'email'];

    public function vouchers()
    {
        return $this->hasMany(Voucher::class);
    }
}

相关问题