Laravel: One to Many to Many, retrieve distinct() values

ぐ巨炮叔叔 提交于 2019-12-08 23:48:56

问题


Laravel 4 Project, using Eloquent ORM.

I have three tables: customers, orders and products (+ 1 pivot table order_product). Customers are linked one-to-many to Orders. Orders are linked many-to-many to Products.

Customers  1-->N  Orders  N<-->N   Products

I would like to have a method on Customer model that retrieves a list of products that customer is buying.

To better understand this, assume products are consumable.

For example Customer #1 can place:

  • Order #1 for Products A, B and C;
  • Order #2 for Products A, C and D;
  • Order #3 for Products C and E;

...and the result I want to retrieve is a Collection with Products A, B, C, D and E.

Models are (pseudo-coded on the fly):

class Product extends Eloquent {

    public function orders()
    {
        return $this->belongsToMany('Order');
    }

}

class Orders extends Eloquent {

    public function customer()
    {
        return $this->belongsTo('Customer', 'customer_id');
    }

    public function products()
    {
        return $this->belongsToMany('Product');
    }

}

class Customers extends Eloquent {

    public function orders()
    {
        return $this->hasMany('Orders', 'customer_id');
    }

    public function products()
    {
        // What to put here ???
    }

}

回答1:


Thanks to @deczo's answer, I was able to put up a single query method to retrieve items:

public function items()
{
    $query = DB::table('items')->select('items.*')
        ->join('item_order', 'item_order.component_id', '=', 'items.id')
        ->leftJoin('orders', 'item_order.order_id', '=', 'orders.id')
        ->leftJoin('customers', 'customers.id' , '=', 'orders.customer_id')
        ->where('customers.id', $this->id)
        ->distinct()
        ->orderBy('items.id');

    $eloquent = new Illuminate\Database\Eloquent\Builder( $query );
    $eloquent->setModel( new Item );
    return $eloquent->get();
}



回答2:


This is a Many-to-Many relationship, but with the Orders table as the pivot table.

class Customers extends Eloquent {

    public function orders()
    {
        return $this->hasMany('Orders', 'customer_id');
    }

    public function products()
    {
        return $this->belongsToMany('Products', 'orders', 'customer_id', 'product_id');
    }
}

I've included the last two parameters, but if you follow the singular_id pattern they can be left out.




回答3:


I can't think of easy relation method for this one, but here's a workaround:

$productsIds = DB::table('customers')
    ->leftJoin('orders', 'orders.customer_id', '=', 'customers.id')
    ->join('order_item', 'order_item.order_id', '=', 'orders.id')
    ->leftJoin('items', 'order_item.item_id' , '=', 'items.id')
    ->distinct()
    ->get(['items.id']);

$productsIds = array_fetch($productsIds, 'id');

$productsCollection = Product::whereIn('id', $productsIds);



回答4:


@deczo's answer probably works fine, and is probably a lot more performant as all the data reduction is done in the database itself, but here's a 'pure Laravel' way that's undoubtedly more readable:

use Illuminate\Database\Eloquent\Collection;

class Customer extends Eloquent
{
    ...
    public function products()
    {
        $products = new Collection;
        foreach ($this->orders as $order) {
            $products = $products->merge($order->products);
        }

        return $products;
    }
}

Note that this method will not act like normal relationship methods - to get the resulting collection you call the method (i.e. $products = $customer->products();) and you can't access it as a property like you can with relationships (i.e. you can't do $products = $customer->products;).

Also, I'm kinda going on my understanding of the Illuminate\Database\Eloquent\Collection#merge() method here that it automatically does a DISTINCT-like thing. If not, you'll have to do a $collection->unique() kinda thing.



来源:https://stackoverflow.com/questions/22940091/laravel-one-to-many-to-many-retrieve-distinct-values

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!