Laravel eloquent 关系 table 前缀

Laravel eloquent relation table prefix

Late Comment

The only way for this to work seems to be defining the foreign key columns in table_name_primary_key format. If they don't fit this format, the relations simply doesn't work without specifying the column names.

我正在尝试学习如何通过 reliese/laravel 代码生成器(它从数据库生成模型)使用外键,但我遇到了一个问题,它迫使我重新指定所有外键生成的代码中的名称。这是我的迁移代码和生成的关系代码:

//迁移

Schema::create('hotels', function(Blueprint $table) {
    $table->increments('hotel_id');
    $table->string('name', 64);
    $table->string('description', 512);
    $table->softDeletes();
    $table->timestamps();
});

Schema::create('floors', function(Blueprint $table){
    $table->increments('floor_id');
    $table->integer('hotel_id')->unsigned();
    $table->string('label', 128);
    $table->softDeletes();
    $table->timestamps();

    $table->foreign('hotel_id')->references('hotel_id')->on('hotels')->onDelete('cascade');
});

//关系

// Hotel.php contains

public function floors()
{
    return $this->hasMany(\Otellier\Floor::class);
}

// Floor.php contains

public function hotel()
{
    return $this->belongsTo(\Otellier\Hotel::class);
}

现在,当我和 Faker 一起创造地板时:

$hotel = factory(App\Hotel::class)->make();
$floor = factory(App\Floor::class)->make([ "label" => "Floor #" . $floor_number ]);
$hotel->floors()->save($floor);

在最后一行,我得到这个错误:

Illuminate\Database\QueryException : SQLSTATE[42S22]: Column not found: 1054 Unknown column 'hotel_hotel_id' in 'field list' (SQL: insert into floors (label, hotel_hotel_id, updated_at, created_at) values (Floor #1, 8, 2018-03-22 12:37:39, 2018-03-22 12:37:39))

显然,它在 floors table 中搜索 hotel_hotel_id 字段作为列,我怀疑这是将 table 名称作为前缀添加到该列姓名。为什么会发生这种情况以及如何防止这种情况并强制整个系统不为任何列添加前缀

不这样做:

public function hotel()
{
    return $this->belongsTo(\Otellier\Hotel::class, "hotels", "hotel_id", "hotel_id");
}

您需要在模型中定义自己的主键:

protected $primaryKey='floor_id';

另一个:

protected $primaryKey='hotel_id';

Laravel 使用 Model.php 中的 getForiegnKey() 方法来预测关系的外键。

/**
 * Get the default foreign key name for the model.
 *
 * @return string
 */
public function getForeignKey()
{
    return Str::snake(class_basename($this)).'_'.$this->primaryKey;
}

您可以在您的模型中覆盖它或基类来改变它的行为。在你的情况下,它可以像

public function getForeignKey()
{
    return $this->primaryKey;
}

它将return你的$primaryKey作为外键,当一个关系尝试访问对应的外键时。

注意:如果您在关系中指定外键,则此方法将无效。

默认情况下eloquent根据模型名称确定关系的外键。在这种情况下,Floor 模型被​​自动假定为具有 hotel_id 外键。此外,Eloquent 假定外键的值应与父项的 id(或自定义 $primaryKey)列相匹配。换句话说,Eloquent 将在 Floorhotel_id 列中查找酒店的 id 列的值。如果您希望关系使用其他值比 id,您可以将第三个参数传递给指定自定义 local key

的 hasMany 方法
public function floors()
{
    return $this->hasMany(\Otellier\Floor::class, 'hotel_id', 'hotel_id');
}