php - Laravel 一对多关系 - 对不存在字段的引用
问题描述
我忘记了在 Lavarel 进行迁移时,一旦关系像这样和曾经那样对我起作用?展示我想要得到的是我想为用户分配他的订单并订购他订购的产品。所以我有一个 User 表、Order 表和 OrderProduct 表。Usera 表与 Order 表具有一对多关系, Order 表与 OrderProduct 表具有一对多关系。从关系 Order 和 OrderProduct 开始,我得到一个错误:
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'order_products_tables.order_table_id' in 'where clause' (SQL: select * from `order_products_tables` where `order_products_tables`.`order_table_id` = 1 and `order_products_tables`.`order_table_id` is not null)
这个错误清楚地表明他在 order_products_tables 表中找不到 order_table_id 列,我并不惊讶这听起来很傻,因为没有这样的字段但是有一个 order_id 字段,并且在迁移中描述了哪个字段是这种关系,我不明白为什么 Laravel 会尝试引用 order_products_tables。
迁移顺序:
Schema::create('order_tables', function (Blueprint $table) {
$table->increments('id');
$table->integer('user_id')->unsigned()->nullable();
$table->foreign('user_id')
->references('id')
->on('users');
$table->timestamps();
});
迁移订单产品:
Schema::create('order_products_tables', function (Blueprint $table) {
$table->increments('id');
$table->integer('order_id')->unsigned();
$table->integer('count')->unsigned();
$table->integer('price')->unsigned();
$table->foreign('order_id')
->references('id')
->on('order_tables');
$table->timestamps();
});
由于它是迁移的结果,order_products_tables 表存储来自 order_tables 表的记录 ID,并且关系基于该 ID。
型号订购表:
class OrderTable extends Model
{
protected $table = 'order_tables';
public function user()
{
return $this->belongsTo(User::class, 'id');
}
public function products()
{
return $this->hasMany('App\OrderProductTable');
}
}
型号订购产品表:
class OrderProductTable extends Model
{
protected $table = 'order_products_tables';
public function order()
{
return $this->belongsTo(OrderTable::class, 'id');
}
}
我不明白为什么要引用 order_table_id。我做过其他的关系,例如用户和订单,原理相同,它工作没有问题,突然这里我有这样的情况。我应该在哪里寻找解决方案,为什么会这样
解决方案
此错误来自使用错误的表名,或者更正确地说,是没有正确定义关系。以下关系定义将解决您的问题:
class OrderTable extends Model
{
protected $table = 'order_tables';
public function products()
{
return $this->hasMany('App\OrderProductTable', 'order_id', 'id');
}
}
class OrderProductTable extends Model
{
protected $table = 'order_products_tables';
public function order()
{
return $this->belongsTo(OrderTable::class, 'order_id', 'id');
}
}
您之前的代码不起作用的原因是 Laravel 使用默认值,这些默认值基本上是假设,并且要求您的数据库遵循某些命名约定。以下是您应遵循的约定列表*:
- 表应该以复数形式的模型名称和snake_case命名:
- 模型
User
应该有一个名为 的表users
。 - 模型
Category
应该有一个名为categories
(见英文复数)的表。 - 模型
AccountManager
应该有一个名为 的表account_managers
。
- 模型
- 如果表没有模型,即多对多关系表,则表名应为单数形式和snake_case,其中包含关系的模型名称按字母顺序排列:
- 如果存在模型
Category
andProduct
(带有表categories
andproducts
)并且它们之间存在多对多关系 (belongsToMany()
),则预计将调用数据透视表的表order_product
(而不是product_order
因为在字母表中o
出现在前面)。p
- 如果存在模型
- 外键列应该在它们表示
_id
为后缀的模型之后被调用:User
例如,当在模型上引用模型时BlogPost
,Laravel 期望将user_id
列作为BlogPost
模型上的外键。模型上引用的主键User
取自默认情况下的$primaryKey
属性。'id'
对于您的特定场景,这意味着我们需要以下模型、表格和列:
User
具有表和列的模型,users
如 Laravel 的默认迁移。Order
具有表格orders
和列的模型,例如id
,user_id
,created_at
, ...Product
具有表格products
和列的模型,例如id
,name
,price
, ...OrderProduct
具有表格order_products
和列的模型,如id
,order_id
,product_id
,quantity
, ...
理论上,该模型OrderProduct
是不必要的。$this->belongsToMany(Product::class)->withPivot('quantity')
通过在Order
模型和模型$this->belongsToMany(Order::class)->withPivot('quantity')
上定义Product
(注意枢轴字段),您还应该能够在没有它的情况下构建相同的系统。就个人而言,我更喜欢多对多关系的额外模型。
有关 Eloquent 关系的参考,请查看文档。当您需要覆盖关系的默认表或列名称时,有所有关系类型的示例和附加参数的附加信息。
* 此列表可能缺少重要信息。它是尽最大努力创建的。