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 将在 Floor
的 hotel_id
列中查找酒店的 id
列的值。如果您希望关系使用其他值比 id
,您可以将第三个参数传递给指定自定义 local key
的 hasMany 方法
public function floors()
{
return $this->hasMany(\Otellier\Floor::class, 'hotel_id', 'hotel_id');
}
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 将在 Floor
的 hotel_id
列中查找酒店的 id
列的值。如果您希望关系使用其他值比 id
,您可以将第三个参数传递给指定自定义 local key
public function floors()
{
return $this->hasMany(\Otellier\Floor::class, 'hotel_id', 'hotel_id');
}