自我加入Eloquent - 如何打电话

时间:2015-06-02 11:44:31

标签: laravel laravel-4 eloquent laravel-5

我最近问了一个关于自我加入的问题

SO

我得到了一个很好的答案,但我不确定如何称呼它。

我需要执行此查询:

SELECT t2.title FROM products t1, products t2
WHERE t1.id = $id 
AND t2.color_id = t1.color_id AND
t2.id != $id

我现在在我的产品型号上有这个:

public function parent()
{
    return $this->belongsTo(self::class, 'color_id');
}

public function children()
{
    return $this->hasMany(self::class, 'color_id');
}

但我怎么称呼它?

Product::with('children')->find(1);

以上获取id为1的产品,但也会获得color_id为1的子项,我需要让color_id与id为product 1的孩子相同。

例如

产品

id | title | color_id
 1    dvd       2

当我选择第1行时,它应该选择color_id为2的所有其他产品。

4 个答案:

答案 0 :(得分:8)

我相信你们的关系不是他们应该的样子。通常它是一列(外键 - 在你的情况下为color_id),其值为另一个(通常是主键 - 在你的情况下为id)。

您所拥有的基本上是记录共享的值或"类别"。所以你的产品不是"孩子"而是兄弟姐妹(具有相同的父母颜色)。

由于with方法不是作为JOIN语句构建的,而是作为急切加载(单独查询),因此您可以手动执行此操作。

可能是最直接的方式:

$product1 = Product::find(1);
$children = Product::where('id', '<>', $product1->id)->
    where('color_id', $product1->color_id)->
    get();

您可以将select('title')添加到第二个&#34;构建器&#34;获得唯一的标题但不再是你的模型了。或者,您可以使用lists('title')仅提取标题,如果您需要的话。

<强>更新

如果您确定需要JOIN,我建议使用原始查询构建器并将Eloquent从中删除:

$res = DB::table('products as t1')->
    select('t2.title')->
    join('products AS t2', 't2.color_id', '=', 't1.color_id')->
    where('t1.id', 1)->
    where('td2.id', '<>', 't1.id')->
    get();

我相信它应该构建类似于你需要的东西。

答案 1 :(得分:1)

您可能需要执行以下操作:

$id = 1;
$product = Product::with('children')->whereHas('children', function($q) use ($id)
{
    $q->where('color_id', $id);
})->find($id);

答案 2 :(得分:0)

请参阅Advanced Join Clauses并改编自我的示例。

我花了很长时间把头包裹在Laravel连接处。

这:

$postIds = DB::table('comments as t1')
     ->select('t1.*')
            ->leftJoin('comments as t2', function ($join) {
                $join->on('t1.postId', '=', 't2.postId')
                ->on('t1.created_at', '<', 't2.created_at');
            })
            ->where('t2.id', '=', null)
            ->orderBy('t1.created_at', 'DESC')
            ->simplePaginate(20)
            ->pluck('postId');

似乎是获取将由此显示的postIds数组的方法:

SELECT     t1.* 
FROM     comments a         
LEFT OUTER JOIN     comments b
 ON t1.postId = t2.postId        
 AND t1.created_at < t2.created_at 
WHERE     t2.id IS NULL     
ORDER BY t1.created_at DESC

答案 3 :(得分:0)

您可以尝试这种方式:

// Category.php

public function children()
{
    return $this->hasMany(Category::class, 'parent_id');
}

public function parent()
{
    return $this->belongsTo(Category::class, 'parent_id');
}

// To access
$category->children; // sub-categories collection

$category->parent; // parent instance

基于:https://laracasts.com/discuss/channels/eloquent/self-join-in-eloquent-model?page=1