欢迎各位兄弟 发布技术文章

这里的技术是共享的

You are here

many to many where 多对多条件 搜索查询 有大用 有大大用 有大大大用

up vote7down votefavorite                    
2                    

In my application I have updated a relationship from one-to-many to many-to-many and I'm trying to figure out a way to persist associated functionality.

Let's say I have two related tables, e.g. dogs and owners. If I have an array of owners and I'm trying to get a list of dogs id's for those owners, how should I do it eloquently?

Similar question was asked here: https://laracasts.com/discuss/channels/laravel/getting-many-to-many-related-data-for-an-array-of-elements                    

annaoleksiuk
Jun 17, 2015

Getting many to many related data for an array of elements

Let's say I have two related tables, e.g. dogs and owners. If I had few owners which dogs names I'd like to get, how should I do it eloquently and dynamically?

gwp
Level 2

Have you looked at the documentation? There are examples there.

http://laravel.com/docs/5.0/eloquent#relationships

More specifically:

http://laravel.com/docs/5.0/eloquent#many-to-many


You will need to define their relationships:

class Owners extends Model {

    public function dogs()
    {
        return $this->belongsToMany('App\Dogs');
    }

}


class Dogs extends Model {

    public function owners()
    {
        return $this->belongsToMany('App\Owners');
    }

}

You also need a dog_owner pivot table, with two columns:

  • dog_id

  • owner_id

mstnorris
Level 50
mstnorrisJun 17, 2015
  • Laracasts Tutor Achievement

  • Top 50 Achievement

  • Chatty Cathy Achievement

  • Laracasts Veteran Achievement

  • Ten Thousand Strong Achievement

@annaoleksiuk

Owner::with('dogs')->get(); // will return all owners and their dogs
annaoleksiuk
Level 1

@gwp Yes, I have, and somehow I couldn't get an answer from there, therefore I look for some examples.

@mstnorris Thanks! Well, my intention was to narrow down the result to owners with a specific id, and I did as follows:

Owner::with('dogs')->whereNested( function($query) use ($ownerIdsArray)
{
    foreach($ownerIdsArray as $id)
    {
        $query->orWhere('id',$reg);
    }
})->get();

It works, but is it efficient?

来自  https://laracasts.com/discuss/channels/laravel/getting-many-to-many-related-data-for-an-array-of-ele...

So, How would I get the Dog models where Owner is in an array ?

Same thing as $associatedDogs = Dog::whereIn('owner_id',$ListOfOwners)->get(); is for a One-To-Many relationship, but for Many-to-Many.

                      
shareimprove this question                            

add a comment                
       

2 Answers 正确答案                 

activeoldestvotes                    
       
up vote18down voteaccepted                    

Use the whereHas() method:

$dogs = Dog::whereHas('owners', function($q) use($ownerIds) {
    $q->whereIn('id', $ownerIds);
})->get();
                   

  • Should I choose the whereHas over with ? What is the difference between them in this case? Does it even make any difference? – Angelin Calu Mar 9 '17 at 10:01                                    
  • Nevermind, I found the explaination here: stackoverflow.com/a/30232227/2012740 – Angelin Calu Mar 9 '17 at 10:28                                    
  • @AngelinCalu yes, with() will not work for you, since it loads relation data. – Alexey Mezenin Mar 9 '17 at 13:15                                     
  • @ I haven't actually tried the with method because of what I have read. So if I understood correctly, that it will probably work also, however it will eager load the owners associated with the dogs – Angelin CaluMar 9 '17 at 13:20                                    
  • 1                                    
    @AngelinCalu no with() will not work. It will load all dogs and filtered owners. whereHas() will load only dogs with owners which are in the list. Just try both and you'll see the difference. – Alexey Mezenin Mar 9 '17 at 13:28                                     

add a comment                    


                   


                   

           
       
up vote1down vote                    

Try

$associateDogs = Dog::with(['owners' => function($query) use ($listOfOwners) {
    $query->whereIn('id', $listOfOwners);
}])->get();
                   

add a comment                    
       

来自  https://stackoverflow.com/questions/42691421/laravel-eloquent-many-to-many-query-wherein          


I've found the concept and meaning behind these methods to be a little confusing, is it possible for somebody to explain to me what the difference between has and with is, in the context of an example (if possible)?

1 Answer 

正确答案

up vote353down voteaccepted

With

with() is for eager loading. That basically means, along the main model, Laravel will preload the relationship(s) you specify. This is especially helpful if you have a collection of models and you want to load a relation for all of them. Because with eager loading you run only one additional DB query instead of one for every model in the collection.

Example:

User > hasMany > Post

$users = User::with('posts')->get();
foreach($users as $user){
    $users->posts; // posts is already loaded and no additional DB query is run
}

Has

has() is to filter the selecting model based on a relationship. So it acts very similarly to a normal WHERE condition. If you just use has('relation') that means you only want to get the models that have at least one related model in this relation.

Example:

User > hasMany > Post

$users = User::has('posts')->get();
// only users that have at least one post are contained in the collection

WhereHas

whereHas() works basically the same as has() but allows you to specify additional filters for the related model to check.

Example:

User > hasMany > Post

$users = User::whereHas('posts', function($q){
    $q->where('created_at', '>=', '2015-01-01 00:00:00');
})->get();
// only users that have posts from 2015 on forward are returned
  • 52
    +1, very helpful answer! Note also that while with('relation') will include the related table's data in the returned collection, has('relation') and whereHas('relation') will not include the related table's data. So you may need to call both with('relation') as well as has() or whereHas(). – SoulriserFeb 6 '16 at 16:08
  • Greet Answer, How to access parent model from relationship model for instance here how to search post model based on the attributes of user model – hussainfrotan May 12 '17 at 5:53
  • @BhojendraNepal Unfortunately there doesn't seem to be a lot about it in the docs... This is all I found (it's a few paragraphs down) – lukasgeiter Jul 25 '17 at 21:00
  • How many would be run in this case for N users? – peter Sep 21 '17 at 14:04 
  • @hussainfrotan the same way, use whereHas on user relation when querying post. – Michael Tsang Nov 12 at 5:35

来自  https://stackoverflow.com/questions/30231862/laravel-eloquent-has-with-wherehas-what-do-they-mean/30...


  


           


           

Laravel Many to Many Query                

Ask Question                
up vote0down votefavorite                            

So I have a products table and a categories table and a pivot table.

Product (products)

-- id

-- name

Category (categories)

-- id

-- name

CategoryProduct (category_product)

-- category_id

-- product_id

I want to get all products that belong to a certain category, I have managed to get it by doing the following query:

$products = Category::find(3)->products;
                               

But how can I access it off the product model?

$products = Product::?
                           
                                  

add a comment                            
                   

1 Answer  正确答案       

activeoldestvotes                                
                   
up vote0down voteaccepted                                

You need the whereHas clause. https://laravel.com/docs/5.4/eloquent-relationships#querying-relationship-existence                                    

$products = Product::whereHas('categories', function ($query) {
    return $query->where('id', 3);
})->get();
                                   

Or you can do it with a join instead.

$products = Product::select('products.*')
    ->join('category_product', 'products.id', '=', 'category_product.product_id')
    ->where('category_product.category_id', 3)
    ->groupBy('products.id')
    ->get();
                               

  • SQLSTATE[23000]: Integrity constraint violation: 1052 Column 'id' in where clause is ambiguous. That is the error I get when I run your code – robertmylne May 3 '17 at 5:18                                                
  • Which snippet gives that error? Did you add any other clauses, scopes, etc? – fubar May 3 '17 at 5:21                                                
  • The first snippet. – robertmylne May 3 '17 at 5:23                                                
  • The edit I made solves the issue. It then works – robertmylne May 3 '17 at 5:25                                                
  • @robertmylne What edit did you make? What was the problem? – fubar May 3 '17 at 5:26                                                
show 3 more comments                                
                                      


来自   https://stackoverflow.com/questions/43750866/laravel-many-to-many-query


up vote1down votefavorite                    
1                    

I have two main tables with relationships many to many and a pivot table.

Model 'Type'

    public function attributes()
    {
        return $this->belongsToMany('App\Attribute', 'attribute_type');
    }
                   

Model 'Attribute'

    public function types()
    {
        return $this->belongsToMany('App\Type', 'attribute_type');
    }
                   

Pivot table 'attribute_type'

    Schema::create('attribute_type', function (Blueprint $table) {
        $table->increments('id');
        $table->integer('type_id')->unsigned();
        $table->foreign('type_id')->references('id')->on('types');
        $table->integer('attribute_id')->unsigned();
        $table->foreign('attribute_id')->references('id')->on('attributes');
    });
                   

I want to show 5 attributes in random order which belong to the types of id < 10.

$attributes = Attribute::whereHas('types', function ($query) {
            $query->where('id', '<', '10');
        })->orderByRaw("RAND()")->limit(5);
                   

and for example

$attribute->id
                   

gives me "Undefined property: Illuminate\Database\Eloquent\Builder::$id"

                        

add a comment                
       

1 Answer 

正确答案

activeoldestvotes                    
       
up vote2down voteaccepted                    

All you have to do is execute query and get the collection with get() method like this:

$attributes = Attribute::whereHas('types', function ($query) {
        $query->where('id', '<', '10');
    })->orderByRaw("RAND()")->limit(5)
    ->get();
                       

Now you are trying to iterate over the query builder which is giving you another query builder as a result of $attribute                        


  • also I changed where('id', '<', '10'); to where('type_id', '<', '10'); – Estern May 11 '16 at 13:59                                    
add a comment                    
       

来自   https://stackoverflow.com/questions/37148000/laravel-wherehas-on-many-to-many-relationships            


           


           

up vote2down votefavorite                            

look at the code first:

<?php

class User extends Eloquent {

    public function books() 
    {
        return $this->belongsToMany('Book');
    }
}

class Book extends Eloquent {

    public function users() 
    {
        return $this->belongsToMany('User');
    }
}
                               

I want to find some User with a id '1',and get the book name where is equal to something ,like this

  User::with(array('Book' => function($query) 
  {
      $query->where('bookname','www')->get();
  }));
                               

but it return a user information and the empty array , Users: { name: 'xxx', xxx: 'xxx', books: [] };

who can help me to fix this issue? thank you so much !

                                  
shareimprove this question                                        
asked Mar 8 '14 at 14:29                                            
                                               
                                           
Daniel.Woo                                                
3211617                                                
  • why you use get() method on inside where query? – revo Mar 8 '14 at 15:20                                            
  • but..with get() or not ,leads to the same query result – Daniel.Woo Mar 8 '14 at 15:24                                            
  • but when I query with 'www11' and others,It works ,I'm so confused – Daniel.Woo Mar 8 '14 at 15:27                                            
  • Do you have your pivot table setup correctly? – Craig Hooghiem Mar 8 '14 at 16:24                                            
add a comment                            
                   

2 Answers 

正确答案

activeoldestvotes                                
                   
up vote0down vote                                

Try:

$user = User::find($user_id)->books()->where('bookname', '=', 'www')->first();
                                   

Also these may help you as well:

Grabbing all users with books:

$users = User::with('books')->get();
                                   

Grabbing all users which have books:

$users = User::has('books')->get();
                                   

Grabbing a single user with books:

$user = User::with('books')->find($user_id);
                               

  • I know there is another way: User::find(1)->books()->where('xx','xx')->get()...But I want to use query scope – Daniel.Woo Mar 9 '14 at 12:52                                                
add a comment                                
                       
                   
up vote0down vote                                

If you want to use query scope, you may applying join on your specified scope.

class User extends Eloquent {

    public function books() 
    {
        return $this->belongsToMany('Book');
    }

    public function scopeByBookName($q, $bookName) {
        return $q->join('user_books as pivot', 'pivot.user_id', '=', 'users_id')
            ->join('books', 'books.id', '=', 'pivot.book_id')
            ->where('books.name', $bookName);
}
                               

add a comment                                

                   



 


来自  https://stackoverflow.com/questions/22270563/laravel-many-to-many-query-the-relation-with-where     




In my application I have updated a relationship from one-to-many to many-to-many and I'm trying to figure out a way to persist associated functionality.

Let's say I have two related tables, e.g. dogs and owners. If I have an array of owners and I'm trying to get a list of dogs id's for those owners, how should I do it eloquently?

Similar question was asked here: https://laracasts.com/discuss/channels/laravel/getting-many-to-many-related-data-for-an-array-of-elements

So, How would I get the Dog models where Owner is in an array ?

Same thing as $associatedDogs = Dog::whereIn('owner_id',$ListOfOwners)->get(); is for a One-To-Many relationship, but for Many-to-Many.


2 Answers 

正确答案 

Use the whereHas() method:

$dogs = Dog::whereHas('owners', function($q) use($ownerIds) {
    $q->whereIn('id', $ownerIds);
})->get();

Try

$associateDogs = Dog::with(['owners' => function($query) use ($listOfOwners) {
    $query->whereIn('id', $listOfOwners);
}])->get();

来自  https://stackoverflow.com/questions/42691421/laravel-eloquent-many-to-many-query-wherein


普通分类: