Query if relation is defined before whereHas - laravel

Consider the following eloquent model:
$itemModel->whereHas('location.country', function($q2) use ($value){
$q2->where('id', $value);
});
When I run this, I get an (expected) exception saying
Call to undefined method Illuminate\Database\Query\Builder::country()
Is there any way I can check the existence of this relation before I execute the whereHas query?

That's not the correct way to use whereHas, multiple relations in the query is for eager loading.
You can try :
$item->whereHas('location',function($query) use ($value){
$query->whereHas('country')->where('id',$value);
});
Relations nesting was not implemented for whereHas

Related

Laravel eager loading with value of current model?

Hi guys is it possible to do this in an eager loading?
Client::with(['relationship' => function($query){
$query->whereBetween('created_at', [$client->failed_date, Carbon::now()->endOfDay()])
}])->get();
Basically I want to put the failed_date column from my CLIENT model into the eager loading query.
Since all types of Eloquent relationships are defined via methods, you may call those methods to obtain an instance of the relationship without actually executing the relationship queries. In addition, all types of Eloquent relationships also serve as query builders, allowing you to continue to chain constraints onto the relationship query before finally executing the SQL against your database.
For example.
$clients = Client::where('status', 1)->get();
foreach($clients as $client) {
$relationships = $client->relationship()
->whereBetween('created_at', [$client->failed_date, $client->pass_date]);
}
This way you can solve your problem.
If you're trying to eagerly load your relationships, As eager load will perform a separate query you don't have direct access to the parent table, so you need to join it.
public function relationship()
{
return $this->belongsTo(Client::class)
->selectRaw('clients.*')
->join('relationships', 'clients.id', '=', 'relationships.client_id')
->whereRaw("....");
}

Laravel isNotEmpty() not working on Eloquent model

I'm probably confused by Eloquent (again...) but I thought that this should work:
$test_row = Test::
where('status', 'active')
->where('condition2', 'value')
->orderBy('order', 'asc')
->first();
if($test_row->isNotEmpty())
return $test_row;
But is it throwing the following error: Call to undefined method App\Test::isNotEmpty().
By using first() it will return an Eloquent model right? And isNotEmpty(), as well as isEmpty(), should be able to be used on the returned model?
You are trying to call isNotEmpty() on a model object and not a collection, when you use first() it returns an object not a collection.
Use
if($test_row)
{
return $test_row
}
The method isNotEmpty() is actually returned by Laravels Collection class and not by an Eloquent model. Since you're not asking for multiple results, only the model is returned instead of a collection.
Simply use
if ($test_row) {
return $test_row;
}
to check if the query had any results and the model exists.

How to use Laravel Eloquent whereIn function on another table?

If two tables have relationship between them, I am using with function to get records considering value within condition from another table. For example:
Table::where('column1', 'text1')->with('table2.column2', 'text2')
My question is, how can I use whereIn function to set array of allowed values in table2?
Table::where('column1', 'text1')->whereIn('table2.column2', ['text2', 'text3'])
Try this
Table::where('column1', 'text1')
->whereHas('table2',function($q) {
$q->whereIn('column2', ['text2','text3']);
});
You must have to define relationship in model
This is the best practice
Refer: Laravel Eloquent Relationship
Refer: Query On Relationship
I would go with Laravel's Constrained eager load to load your relationship.
Example
Table::where('column1', 'text1')
->with(['table2' => function ($query) {
$query->whereIn('column2', ['text2', 'text3'])
}])
->get();
If you don't need to load the relationship, then going with the whereHas solution provided by #bhavinjr is the best.
From the documentation :
Eager Loading Multiple Relationships
Sometimes you may need to eager load several different relationships in a single operation. To do so, just pass additional arguments to the with method:
$books = App\Book::with(['author', 'publisher'])->get();
Constraining Eager Loads
Sometimes you may wish to eager load a relationship, but also specify additional query conditions for the eager loading query. Here's an example:
$users = App\User::with(['posts' => function ($query) {
$query->where('title', 'like', '%first%');
}])->get();`
You can take a look at Laravel API to have a deeper understanding of the with method.

Eloquent relationship - whereNotNull does not exist

I have a relationship in Eloquent that I'm trying to query.
$deliveryOverride = $product->days->whereNotNull('margin')
->where('price_id', $order['price_id'])
->where('product_id', $product->id)
->where('sale_at', date('Y-m-d', strtotime($day)))
->first();
I keep getting the the error
Method whereNotNull does not exist.
Any ideas?
When you call a relation property directly on an Eloquent object, the query is executed and a Collection is returned. There is no WhereNotNull function on collections.
If you want to query the relation using that function, you will have to call the relation function directly. This will also be better for performance as the query will happen on the database.
$deliveryOverride = $product->days() // Call relation function here
->whereNotNull('margin')
->where('price_id', $order['price_id'])
->where('product_id', $product->id)
->where('sale_at', date('Y-m-d', strtotime($day)))
->first();
More information about this can be found in the documentation right here: https://laravel.com/docs/5.7/eloquent-relationships#querying-relations

Where clause inside whereHas being ignored in Eloquent

Im trying to make a query using whereHas with eloquent. The query is like this:
$projects = Project::whereHas('investments', function($q) {
$q->where('status','=','paid');
})
->with('investments')
->get();
Im using Laravel 5.2 using a Postgres driver.
The Project model is:
public function investments()
{
return $this->hasMany('App\Investment');
}
The investments model has:
public function project() {
return $this->belongsTo('App\Project');
}
The projects table has fields id,fields...
The investments table has the fields id,project_id,status,created_at
My issue is that the query runs and returns a collection of the projects which have at least one investment, however the where clause inside the whereHas is ignored, because the resulting collection includes investments with status values different than paid.
Does anyone has any idea of what is going on?
I believe this is what you need
$projects = Project::whereHas('investments', function($q) {
$q->where('status','=','paid');
})->with(['investments' => function($q) {
$q->where('status','=','paid');
}])->get();
whereHas wil check all projects that have paid investments, with will eagerload all those investments.
You're confusing whereHas and with.
The with method will let you load the relationship only if the query returns true.
The whereHas method will let you get only the models which have the relationship which returns true to the query.
So you need to only use with and not mix with with whereHas:
$projects = Project::with(['investments' =>
function($query){ $query->where('status','=','paid'); }])
->get();
Try like this:
$projects = Project::with('investments')->whereHas('investments', function($q) {
$q->where('status','like','paid'); //strings are compared with wildcards.
})
->get();
Change the order. Use with() before the whereHas(). I had a similar problem few weeks ago. Btw, is the only real difference between the problem and the functional example that you made.

Resources