Get object only when relation result is exist [laravel]

大兔子大兔子 提交于 2019-12-24 18:54:12

问题


I have a problem with get data only when relation query count is more than 0.

This is my model of customer with relation

class Customer extends Model
{
    protected $table = 'customers';

    public function contracts()
    {
        return $this->hasMany('App\Contract');
    }

This is my model of contracts

class Contract extends Model
{
    public function customer()
    {
        return $this->belongsTo('App\Customer');
    }
}

On the end i need only customers who they contracts beetwen some date

$customers = Customer::with(['contracts' => function($query)
     {
        $query->where('data_end','>=','2017-07-01')
              ->where('data_end','<=','2017-07-31') 
              ->where('typ','=','U') ;
     }
    ])->paginate(10);

But i have all customers. and it looks like this:

"Customer 1"
"Customer 2"
"Customer 3"
  *"Contract 1"
  *"Contract 2"
  *"Contract 3"
"Customer 4"
  *"Contract 1"
  *"Contract 2"
  *"Contract 3"  
"Customer 4"  

In this example i don't need customer 1,2, and 5. How can i do it with eager loading and object with relation on the end.

enter image description here

This is happen, i dont need customer with X on the screenshot - I mean, I don't need customer with 0 contracts from where query

-- Object from dd()--

end of this query 2 customer, 1st have 2 contracts, 2nd have 0 contracts

LengthAwarePaginator {#217 ▼
  #total: 75000
  #lastPage: 37500
  #items: Collection {#213 ▼
    #items: array:2 [▼
      0 => Customer {#220 ▼
        #table: "customers"
        #connection: null
        #primaryKey: "id"
        #keyType: "int"
        +incrementing: true
        #with: []
        #perPage: 15
        +exists: true
        +wasRecentlyCreated: false
        #attributes: array:5 [▼
          "id" => 1
          "customer_number" => "46071600600"
          "name" => "Nikodem Zalewski"
          "customer_contact" => "507614445"
          "customer_type" => "P"
        ]
        #original: array:5 [▶]
        #casts: []
        #dates: []
        #dateFormat: null
        #appends: []
        #events: []
        #observables: []
        #relations: array:1 [▼
          "contracts" => Collection {#224 ▼
            #items: array:2 [▼
              0 => Contract {#227 ▼
                #connection: null
                #table: null
                #primaryKey: "id"
                #keyType: "int"
                +incrementing: true
                #with: []
                #perPage: 15
                +exists: true
                +wasRecentlyCreated: false
                #attributes: array:10 [▶]
                #original: array:10 [▶]
                #casts: []
                #dates: []
                #dateFormat: null
                #appends: []
                #events: []
                #observables: []
                #relations: []
                #touches: []
                +timestamps: true
                #hidden: []
                #visible: []
                #fillable: []
                #guarded: array:1 [▶]
              }
              1 => Contract {#229 ▶}
            ]
          }
        ]
        #touches: []
        +timestamps: true
        #hidden: []
        #visible: []
        #fillable: []
        #guarded: array:1 [▶]
      }
      1 => Customer {#221 ▼
        #table: "customers"
        #connection: null
        #primaryKey: "id"
        #keyType: "int"
        +incrementing: true
        #with: []
        #perPage: 15
        +exists: true
        +wasRecentlyCreated: false
        #attributes: array:5 [▶]
        #original: array:5 [▼
          "id" => 2
          "customer_number" => "81050371854"
          "name" => "Adam Wróbel"
          "customer_contact" => "560047958"
          "customer_type" => "P"
        ]
        #casts: []
        #dates: []
        #dateFormat: null
        #appends: []
        #events: []
        #observables: []
        #relations: array:1 [▼
          "contracts" => Collection {#222 ▼
            #items: []
          }
        ]
        #touches: []
        +timestamps: true
        #hidden: []
        #visible: []
        #fillable: []
        #guarded: array:1 [▶]
      }
    ]
  }
  #perPage: 2
  #currentPage: 1
  #path: "*"
  #query: []
  #fragment: null
  #pageName: "page"
}

回答1:


You are almost there with your code.

You don't specify which version of Laravel you're using, but you should be looking at whereHas (This exists in Laravel since at least 5.0)

https://laravel.com/docs/5.0/eloquent#querying-relations (v5.0)

When accessing the records for a model, you may wish to limit your results based on the existence of a relationship. For example, you wish to pull all blog posts that have at least one comment. To do so, you may use the has method:

If you need even more power, you may use the whereHas and orWhereHas methods to put "where" conditions on your has queries:

Try the following code.

$customers = Customer::with('contracts')->whereHas('contracts', function($query)
 {
    $query->where('data_end','>=','2017-07-01')
          ->where('data_end','<=','2017-07-31') 
          ->where('typ','=','U') ;
 }
)->paginate(10);

This will load the contracts object with customers but only return customers who have contracts matching the query.



来源:https://stackoverflow.com/questions/45355201/get-object-only-when-relation-result-is-exist-laravel

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