【问题标题】:hasManyThrough laravel relationhasManyThrough laravel 关系
【发布时间】:2023-03-09 15:16:01
【问题描述】:

我有下面三个表。

+-----------------+   +---------------------+   +-------------+ 
|    products     |   |  product_countries  |   |  countries  |
+-----------------+   +---------------------+   +-------------+ 
|   id            |   |  id                 |   |   id        |
|   name          |   |  product_id         |   |   name      |
|   description   |   |  country_code       |   |   code      |
+-----------------+   |  other columns      |   +-------------+
                      +---------------------+

hasManyThrough 在 Country::class 模型中获取所有产品。

public function products()
{
    return $this->hasManyThrough(
        'App\Product',
        'App\ProductCountry',
        'product_id', // Foreign key on feeds table...
        'id', // Foreign key on articles table...
        'code', // Local key on users table...
        'country_code' // Local key on feeds table...
    );
}

我想要与国家或一个国家相关的产品:

$user = \App\Models\Country::find(1);
dd($user->products);

【问题讨论】:

标签: php laravel eloquent


【解决方案1】:

您所描述的关系最适合多对多,这通常在 Laravel 中写为双方的 belongsToMany

class Product extends Model
{
    public function countries()
    {
        return $this->belongsToMany(Country::class);
    }
}

class Country extends Model
{
    public function products()
    {
        return $this->belongsToMany(Product::class);
    }
}

如果你坚持 Laravel 的命名约定:

  • product_countries 重命名为country_product
  • country_product 中使用country_id 而不是country_code

...您应该能够以您期望的方式访问关系:

$country = \App\Models\Country::find(1);
dd($country->products);

$countries = \App\Models\Country::with('products')->where(...)->get();
foreach ($countries as $country) {
    dd($country->products);
}

如果您不想遵守约定,您可以自定义定义关系的方式。详情请见Laravel's documentation


在您的情况下,要使用您的自定义表名称和自定义字段名称指定您的关系,您可以这样做:

// In your Product model
return $this->belongsToMany(Country::class, 'product_countries', 'country_code', 'product_id');

// In your Country model
return $this->belongsToMany(Product::class, 'product_countries', 'product_id', 'country_code');

【讨论】:

  • 是的,谢谢你的回答..但我必须使用国家代码相关...我不知道为什么这种不工作的关系是正确的..但它显示在事物上
  • 我肯定会建议将关系更改为使用id 而不是country_code,它使事情更容易使用。如果您不想这样做,请查看有关如何指定数据透视表名称和自定义列名称的文档,如果您真的想坚持使用country_code
  • 查看我的更新答案,了解如何使用自定义表名和自定义字段名。
  • 是的,这是多对多关系。我犯了愚蠢的错误
【解决方案2】:

Many-to-many 是正确的模型关系。您需要在第二个参数中添加您的自定义表名,否则 Eloquent 会按字母顺序自动为您创建(如 country_product)。您不需要创建 ProductCountry 模型,因为它只是一个数据透视表。

你没有发布你的迁移文件,(只是猜测),推荐使用country_id,但如果你使用country_code/product_id作为外键,你还需要在参数中添加它以及像这样在您的迁移文件中(另请查看official documentation

 $table->foreign('product_id')->references('id')->on('products');
 $table->foreign('country_code')->references('code')->on('countries');

试试这个...

在您的产品模型中

class Product extends Model
{
   public function countries()
   {
      return $this->belongsToMany('App\Country','product_countries','product_id','country_code');
   }
}

在您的国家模式中

class Country extends Model
{
   public function products()
   {
      return $this->belongsToMany('App\Product','product_countries','country_code','product_id');
   }
}

在你的控制器中

use App\Country;

$products = Country::find(1)->products()->get(); //finding by id or

$products = Country::where('country_code',$value)->with('products')->get(); //finding by code

【讨论】:

    【解决方案3】:

    也许也没有真正链接到该问题,但在此示例中,您如何显示集合中的“其他列”? 我有相同的模型,我将在这样的资源中使用它:

    public function toArray($request)
    {
        return [
            'id' => (string)$this->id,
            'type' => 'team',
            'attributes' => [
                'name' => $this->name,
                'status'=> $this->status,
                'created_at' => $this->created_at,
                'updated_at' => $this->updated_at,
            ],
            'relationships' => $this->when(!$request->is('*/users*') && count($this->users) > 0,[
                'user' => [
                    'data' => UserResource::collection($this->whenLoaded('users')),
                ]
            ])
        ];
    }
    

    UserRessouce 是这样的:

    public function toArray($request)
    {
        return [
            'id' => (string)$this->id,
            'type' => 'user',
            'attributes' => [
                'name' => $this->name,
                'email'=> $this->email,
                'created_at' => $this->created_at,
                'updated_at' => $this->updated_at,
            ],
            'relationships' => $this->when(!$request->is('*/teams*') && count($this->teams) > 0,[
                'team' => [
                    'data' => TeamResource::collection($this->whenLoaded('teams')),
                ]
            ])
        ];
    }
    

    json 结果:

    {
        "data": {
            "id": "2",
            "type": "team",
            "attributes": {
                "name": "Kassulke and Sons",
                "status": "open",
                "created_at": "2022-04-08T12:13:32.000000Z",
                "updated_at": "2022-04-08T12:13:32.000000Z"
            },
            "relationships": {
                "user": {
                    "data": [
                        {
                            "id": "1",
                            "type": "user",
                            "attributes": {
                                "name": "John Doe",
                                "email": "john Doe",
                                "created_at": "2022-04-08T12:13:50.000000Z",
                                "updated_at": "2022-04-08T12:13:50.000000Z"
                            }
                        }
                    ]
                }
            }
        }
    }
    

    在团队和用户之间的“middel”表中,我有“更多列”,如“角色”,我将在关系中显示。

    【讨论】:

      猜你喜欢
      • 2018-10-18
      • 2018-07-24
      • 2020-10-14
      • 1970-01-01
      • 1970-01-01
      • 2018-03-08
      • 2021-12-06
      • 2023-03-08
      • 2017-02-07
      相关资源
      最近更新 更多