【问题标题】:Laravel Eloquent Relationships latestLaravel 雄辩的关系最新
【发布时间】:2018-08-14 11:33:20
【问题描述】:

我正在创建报价。我的表格看起来像这样:

quote:
    PK:id
    name
    FK:client_id
    FK:user_id
    created_at
quoteSkus:
    PK:id
    FK:quote_id
    FK:sku_id
    price
sku:
    PK:id
    name
    created_at

我的人际关系是这样的:

Quote.php

public function skus(){
    return $this->hasMany('\App\Http\Models\Quotesku','quote_id','id');
}
public function client(){
    return $this->hasOne('\App\Http\Models\Client', 'id','client_id');
}
public function contact(){
    return $this->hasOne('\App\Http\Models\Contact', 'id','contact_id');
}

QuotaSkus.php

public function sku(){
    return $this->hasOne("\App\Http\Models\Sku","id","sku_id");
}
public function quote(){
    return $this->hasOne("\App\Http\Models\Quote","id","quote_id");
}

sku.php

public function lastUsage(){
    return $this->hasOne('\App\Http\Models\Quotesku','sku_id','id');
}

我想获得此客户上次报价中为此 sku 设置的价格。

这个查询会告诉我:

SELECT * 
FROM `skus` as s 
RIGHT JOIN quoteskus as qs on qs.sku_id = s.id
RIGHT JOIN quotes as q on q.id = qs.quote_id
where s.id = 236
AND q.client_id = 2
order by q.created_at DESC

是否可以用雄辩的关系来建立这个关系? 这样我就可以了

$sku = new Sku();
$sku->find(1);
$sku->lastUsage->price;

$sku->lastUsage(client_id)->price;

抱歉代码转储,我尽力总结了。

任何建议都会有所帮助。谢谢你:)

【问题讨论】:

  • 模型一般放在app目录下,app\http目录一般用于控制器和中间件。你确定你的模型放在 app\http\models 里吗?
  • 您是否尝试将->orderBy('created_at', 'desc') 添加到您的lastUsage*() 方法中?
  • @NIKHILNEDIYODATH 是的,这是我的第一个 Laravel 项目,所以我不确定将模型文件放在哪里。这种设置有效,只是不够优雅。
  • @i-- 表 quotesku 没有 created_at 列。我不想保存这些数据,因为它已经保存在 quote 表中。
  • “你必须使用 php artisan 命令制作模型”@NIKHILNEDIYODATH 不,你没有。你应该?可能,但是将现有模型复制到另一个模型,重命名类和文件并使用并没有错。

标签: php database laravel eloquent relationship


【解决方案1】:

你可以使用下面的

$sku = Sku::find(1);
$quotesku = $sku->lastUsage->price;

还有sku.php

public function lastUsage(){
    return $this->hasMany('\App\Http\Models\Quotesku','sku_id','id')->orderBy('created_at', 'desc')->first();
}

【讨论】:

  • 返回第一次使用的价格,而不是最后一次使用的价格。它也不给我按客户过滤的选项。
  • 传递给find的参数是sku的id。也就是说,它将返回 id 为 1 的 sku 实例,并将其存储在 $sku 中。 lastusage 是一种hasone 关系,这意味着只有一个quotesku 对应于一个sku。那你要在哪里过滤呢?
  • lastuseage 设置为 hasOne 因为我只想取回 1 个,基于其配额的最小的一个。我没有任何过滤。我的问题是可以使用Eloquent Relationships 来完成。我已经使用原始帖子中的查询完成了此操作。
  • @DvirLevy 据我了解 - 你不能过滤关系(就像你想要的那样),因为它可以作为属性和方法互换使用。
【解决方案2】:

这里应该是你想要的:

public function lastUsageByClient($client_id) {
    return $this->join('quoteSkus', 'sku.id', '=', 'quoteSkus.sku_id')
        ->join('quote', 'quote.id', '=', 'quoteSkus.quote_id')
        ->select('sku.*', 'quoteSkus.price')
        ->where('quote.client_id', $client_id)
        ->orderBy('quote.created_at', 'desc')
        ->first();
}

不漂亮,但应该可以。

编辑:

public function lastUsage() {
    return $this->hasOne('\App\Http\Models\Quotesku','sku_id','id')
        ->join('quote', 'quote.id', 'quoteSkus.quote_id')
        ->orderBy('quote.created_at', 'desc');
}

您可能还想在此处指定要拉取的列。

【讨论】:

  • 这没有使用Eloquent Relationships。为什么这比仅运行我发布的查询更好?
  • 我实际上尝试避免在数据透视表上使用除外键以外的列,这样就无需为数据透视表创建模型,并且更容易编写代码。我稍微调整了代码以使其使用hasOne()
  • 如果您需要按 quotesku 表中的字段进行过滤,我认为您无法避免“非优雅”代码。
  • 是的,我想你是对的,这一定很混乱。在您的编辑中,您使用了hasOne,这正是我想要的,所以谢谢你!我不知道这个解决方案比我的查询更好或更差,但代码看起来更干净,所以我很高兴:)
猜你喜欢
  • 2015-03-14
  • 2018-11-28
  • 2015-01-11
  • 2021-06-03
  • 2020-03-26
  • 1970-01-01
相关资源
最近更新 更多