【问题标题】:Assigning ids to relationships in Laravel在 Laravel 中为关系分配 id
【发布时间】:2019-08-07 14:53:29
【问题描述】:

我有一个雄辩的模型,叫做“客户”。客户与另一个模型“图像”具有一对多的关系。我想对客户拥有的图像进行分组,以便我可以将它们分配给不同的用例 - 例如,客户将有一个徽标图像,但他们的画廊部分有很多图像。

如何将用例分配给 Laravel 中的关系?

我想我会创建一个名为“Usecase”的中间模型,然后使用hasManyThrough 方法访问图像。我系统中的许多关系都需要定义它们的用例。我是 laravel 的新手,这是框架中已经涵盖的东西吗?

编辑: 我还希望在不使用时将图像分配给客户-因此我可以上传一堆图像并说它们属于特定客户,但是在我们分配“用例”之前它们不会在任何地方使用(即、“标志”或“画廊”)。这样,我将拥有分配给客户的所有图像的图库,然后是分配为“图库”的图像的图库。 Bleh,这有意义吗?

【问题讨论】:

  • 你可能想看看spatie media library package。它允许您将图像“附加”到模型,并且您可以为每个模型拥有多个图像集合(例如:徽标集合(可以强制执行单个图像)、图库集合等)。即使你不需要它的功能,你至少可以看一下代码,看看它们是如何组织模型和关系的。

标签: laravel eloquent


【解决方案1】:

我可以想到 3 种方法来实现这一点。

1:您将“徽标”变成“客户”列而不是单独的模型,并为所有图库图像保留“图像”。

2:您将“Logo”变成一个单独的模型,“Customer”和“Image”也是如此

3:您将生活复杂化并将“徽标”和画廊图像保留为“图像”,然后添加一种区分两者的方法(可能是一个标志:is_logo 或一个枚举列:image_type)。

如果你问我,第二个选项是最吸引人的。

【讨论】:

  • 在 Laravel 中扩展课程可以吗?就像如果我选择选项 2,我仍然可以拥有我的 Image 模型,然后在我的 logo 模型中我会 Logo extends Image?我是否需要运行工匠命令来创建该扩展模型? php artisan make:model Logo extends Image?
  • @AbrahamBrookes 是的,您可以手动扩展 Image(我不认为工匠会为您做这件事) - 但是您为什么要这样做呢?也试试这个:tighten.co/blog/extending-models-in-eloquent
【解决方案2】:

您可以为此使用Polymorphic Relationships 关系或分隔 2 个图像表

  1. 客户
  2. 徽标
  3. 图片

客户可以拥有 1 个徽标 客户可以有 1 个或多个图像

$customer = new Customer; 
$customer->with('images', 'logo')->get();

这将帮助您查询所有图像和徽标的一组结果。

【讨论】:

    【解决方案3】:

    您可以为同一个模型使用 2 个关系。

    型号:

    class Customer extends Model
    {
        public function gallery()
        {
            return $this->hasMany(Image::class)->where('type', 'gallery');
        }
    
        public function logo()
        {
            return $this->hasOne(Image::class)->where('type', 'logo');
        }
    }
    

    检索:

    $customer = Customer::with(['gallery', 'logo'])->get();
    

    输出:

    @foreach($customer->gallery as $image)
        {{ $image->some_attribute }}
    @endforeach
    
    {{ $customer->logo->some_attribute }}
    

    【讨论】:

    • 你测试过这个吗?恐怕这会产生外键问题。你会有类似'customer_id, customer_id2'的东西
    【解决方案4】:

    我认为最干净的方法是……

    1) 有一个“UseCase”表,可以定义所有类型的用例。这允许简单的可扩展性和可读性,而不会用一堆新的 VARCHAR 或其他东西弄乱图像表。

    2) 在“Image”表中创建一个“use_case”列,并为每张图片从上面的“UseCase”表中分配相应的 ID。

    3) 在 UseCase.id = Image.use_case 上创建“Image”和“UseCase”之间的 hasOne/belongsTo 关系

    4) 在您的“客户”表中创建一个范围,如下所示...

    public function scopeUseCase($query, $case){
        $query->with(['Image.UseCase' => function($relationQuery) use ($case) {
             return $relationQuery->where('name', '=', $case);
        }]);
    }
    

    5) 最后,在使用范围的查询中按名称引用案例...

    Customer::useCase('logo')->get();
    

    从那里开始应该是一个非常干净和直接的过程。很抱歉卡在移动设备上的格式问题。

    【讨论】:

    • 虽然这种方法可行 - 它会显着增加查询复杂性并导致关系出现某些问题 - 除非完全省略关系。
    • 你是对的。中间立场是将 UseCase 表加载到另一个变量中并从中引用值,而不是通过两个关系急切加载。
    • 是的,正是@SavvyK
    猜你喜欢
    • 2013-09-13
    • 2018-08-05
    • 1970-01-01
    • 1970-01-01
    • 2014-12-09
    • 2022-08-17
    • 2019-11-30
    • 1970-01-01
    • 2021-05-06
    相关资源
    最近更新 更多