Laravel一对多关系-对不存在字段的引用

时间:2018-07-24 17:36:54

标签: php laravel one-to-many relation

在拉瓦雷尔(Lavarel)进行迁移时,我忘了什么呢?展示我想要得到的是我要向用户分配他的订单并订购他订购的产品。因此,我有一个User表,Order表和OrderProduct表。与Order表具有一对多关系的Usera表,与OrderProduct表具有一对多关系的Order表。从关系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();
});

迁移OrderProduct:

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');
    }
}

Model OrderProduct表:

class OrderProductTable extends Model
{
    protected $table = 'order_products_tables';

    public function order()
    {
        return $this->belongsTo(OrderTable::class, 'id');
    }
}

我不明白为什么要对order_table_id进行引用。我已经按照相同的原则完成了其他关系,例如“用户”和“订单”,并且可以正常工作,突然间我遇到了这种情况。我应该在哪里寻找解决方案,为什么呢?

1 个答案:

答案 0 :(得分:1)

此错误来自使用错误的表名,或更准确地说,是未正确定义关系。以下关系定义将解决您的问题:

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形式,其中包含该关系的模型名按字母顺序排列:
    • 如果存在模型CategoryProduct(具有表categoriesproducts),并且存在多对多关系(belongsToMany())在它们之间,数据透视表的表应该称为order_product(而不是product_order,因为o在字母表中的p之前)。
  • 预计在以_id作为后缀表示的模型之后,将调用外键列:
    • 例如,在引用User模型上的BlogPost模型时,Laravel期望将user_id列作为BlogPost模型上的外键。 User模型上引用的主键来自$primaryKey属性,默认情况下为'id'

对于您的特定情况,这意味着我们希望使用以下模型,表和列:

  • 具有表User和列的模型users,例如在Laravel的默认迁移中。
  • 具有表Order和诸如ordersiduser_id,...之类的列的模型created_at
  • 具有表Product和诸如productsidname,...之类的列的模型price
  • 具有表OrderProduct和诸如order_productsidorder_idproduct_id,...之类的列的模型quantity

理论上,模型OrderProduct是不必要的。您还应该能够通过在$this->belongsToMany(Product::class)->withPivot('quantity')模型上定义Order和在$this->belongsToMany(Order::class)->withPivot('quantity')模型上定义Product来构建没有该系统的相同系统(请注意枢轴字段)。就个人而言,我更喜欢用于多对多关系的额外模型。

要了解雄辩的关系,请查看at the documentation。当需要覆盖关系的默认表名或列名时,将提供所有关系类型的示例以及其他参数的附加信息。

*此列表可能缺少重要信息。它是尽力而为。