Laravel 变形关系

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/40817211/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-14 14:49:08  来源:igfitidea点击:

Laravel morph relationship

phpsqllaraveleloquentpolymorphism

提问by Bisgaard

I have a question regarding saving polymorphic relationships in Laravel. This is the model i would like to create in laravel.

我有一个关于在 Laravel 中保存多态关系的问题。这是我想在 Laravel 中创建的模型。

Class diagram

类图

A shop has many products, and a product can be either an "item" an "event" or a "service".

一个商店有很多产品,一个产品可以是“物品”、“事件”或“服务”。

I have the following tables:

我有以下表格:

  • shops
    • id
    • user_id
    • name
  • events
    • id
    • public
    • title
    • description
  • products
    • id
    • shop_id
    • productable_id
    • productable_type
  • 商店
    • ID
    • 用户身份
    • 姓名
  • 事件
    • ID
    • 民众
    • 标题
    • 描述
  • 产品
    • ID
    • 店铺编号
    • productable_id
    • 可生产类型

This is how i set up the models:

这是我设置模型的方式:

class Shop extends Model{
    public function products(){
        return $this->hasMany('App\Product');
    }
}

class Product extends Model{
    public function productable(){
        return $this->morphTo();   
    }
}

class Event extends Model{
    public function product(){
        return $this->morphOne('App\Product','productable');
    }
}

I want to be able to do the following:

我希望能够做到以下几点:

$shop = Shop::first()
$event = Event::create(['title'=>'Some event']);
$service = Service::create(['title' => 'Some service']);
$shop->products()->save($event);
$shop->products()->save($service);

But it doesn't work! When i try to save the relation i get:

但它不起作用!当我尝试保存关系时,我得到:

Illuminate\Database\QueryException with message 'SQLSTATE[HY000]: General error: 1 no such column: shop_id (SQL: update "accendo_events" set "updated_at" = 2016-11-26 10:11:02, "shop_id" = 1 where "id" = 1)'

Anyone have an idea of where this is going wrong? I probably misunderstood something about this type of relationship...

任何人都知道这是哪里出了问题?我可能对这种关系有一些误解......

回答by prateekkathal

First of all add a back relation to Shopfrom ProductModel

首先添加一个Shop来自模型的反向关系Product

class Shop extends Model
{
  public function products()
  {
    return $this->hasMany('App\Product');
  }
}

class Product extends Model
{
  public function shop()
  {
    return $this->belongsTo('App\Shop');
  }

  public function productable()
  {
    return $this->morphTo();
  }
}

class Event extends Model
{
  public function product()
  {
    return $this->morphOne('App\Product', 'productable');
  }
}

Now, I am not sure why you are trying to make an empty event and add it to all the products, but still if you want to do it for whatever use cases... please follow the below approach... :)

现在,我不确定您为什么要尝试创建一个空事件并将其添加到所有产品中,但是如果您想为任何用例执行此操作...请遵循以下方法... :)

$shop = Shop::first();            //or $shop = Shop::find(1);

foreach($shop->products as $product) {
  $event = Event::create([]);
  $service = Service::create([]);

  $product->productable()->saveMany([
    $event, $service
  ]);
}

Let me know in the comments below if something doesn't work :)

如果有什么不起作用,请在下面的评论中告诉我:)

-- Edit

- 编辑

First of all, please understand that you can not add an entry to productable_idor productable_typefrom a hasMany()relation. You need to make sure you are using a morphrelation for such purposes.

首先,请理解您不能在关系中添加条目productable_idproductable_typehasMany()关系中添加条目。您需要确保将morph关系用于此类目的。

Secondly, since you are trying to add products first and not events first, the insertion method is not working out for you. Please note that you must try to create an Event or Service firstand then try to associate with a shop.

其次,由于您尝试先添加产品而不是先添加事件,因此插入方法对您不起作用。请注意,您必须先尝试创建事件或服务,然后再尝试与商店关联。

The simplest approach to doing it would be

最简单的方法是

$shop = Shop::first();

$event = Event::create(['title' => 'Some Event']);
$event->product()->create(['shop_id' => $shop->id]);

$service = Service::create(['title' => 'Some Service']);
$service->product()->create(['shop_id' => $shop->id]);

You can also, try to follow my first approach, but the one I just mentioned is definitely supposed to work... and actually that is how it is meant to be inserted/created.

您也可以尝试遵循我的第一种方法,但我刚才提到的方法肯定可以工作……实际上这就是插入/创建的方式。