Laravel eager loading with value of current model? - laravel

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("....");
}

Related

Get data from another model

$objects = Objects::where("id_host", $hostId)
->orderBy("id", "desc")
->get();
In the collection , each object has a type_id field . How can I use this field to get a record in another model and mix them into this object in the response
First thing is first, in order to show the relationship between the records, you'll need to set up a One-to-Many/Many-to-One relationship. This allows you to readily call those relationships from within Laravel and to load them together.
Without being able to see your Type and Object classes, I really can't give specific advice on this, but it should look something like this:
Objects
public function type(): BelongsTo
{
return $this->belongsTo(Type::class);
}
Type
public function objects(): HasMany
{
return $this->hasMany(Objects::class);
}
Once you've done that, you can add a with(...) call to your Eloquent query to eager load the relationship.
$objects = Objects::where("id_host", $hostId)
->orderBy("id", "desc")
->with('type')
->get();
Alternatively, if you don't want to eager load it for some reason, you can call $object->type to get the Type object.

create whare clause on model attribute

How to create where clause on laravel model attribute
I have the following relation between user and books. where user hasMany books and the book model belongs to single user
I want to select all books with pages > 100 that belongs to user_id = 2
I use laravel 5.2 with mysql and defined a model for User and another model for Book
When I want to get all books for specific user, I user
return User::find(2)->books;
and this works fine. But I want to get the books where pages > 100. I use:
return User::find(2)->books->where([['pages', '>', 100], ['chapters', '>', 3]]);
but doesn't work
User model:
class User extends Authenticatable
{
public function books()
{
return $this->hasMany('App\Book');
}
}
Book model
class Book extends Model
{
public function user()
{
return $this->belongsTo('App\User');
}
}
I expect to get all the books with user_id = 0 and pages > 100 and chapters > 3
You'll want to access the relationship method books(), not the property books. Some quotes from the documentation:
Querying Relations
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.
Relationship Methods Vs. Dynamic Properties
If you do not need to add additional constraints to an Eloquent relationship query, you may access the relationship as if it were a property.
Example solution:
return User::find(2)
->books()
->where([['pages', '>', 100], ['chapters', '>', 3]])
->get();
Note that we're using books() to access the HasMany relationship, and using the where() query builder method on it to create a constraint. Then, in order to complete and execute the query, we call get() at the end. If you don't, you'll just return the daisy chained query builder.
Your previous code might not error, because the value returned from User::find(2)->books will be a Collection object, which actually has a where() method. It just likely didn't have any matches because of the array format you passed.
To add where clouses on related models, we can use whereHas() function.
Since you want Books, Start from Book model.
$books = Book::where([
['pages', '>', 100],
['chapters', '>', 3],
])
->whereHas('user', function($query) {
$query->where('id', 2);
})
->get();

How to pluck unique relationships from query builder?

I need to pluck unique set of relation which are present in query set of models. I have model User with table 'users' and model Role with table 'roles', User hasMany Role.
//User.php
public function roles()
{
return $this->belongsToMany(Role::class);
}
//Role.php
public function users()
{
return $this->belongsToMany(User::class);
}
I managed it using collections, but it needs to run such a big query, what slowing whole request
//Controller
...
$users = User::query()->someChainOfScopes();
$uniqueRoles = $users->get()->pluck('roles')->flatten(1)->unique('id')->values();
...
This code returns collection which I need, but I would like to implement it using query builder to pluck unique roles for speed improvement
There are a few different ways you could do this using Laravel,
Joins could be an option to join the 2 tables in a DB::table() query and then find the users using the parameters you require and return the role_id.
To speed up users
$user_ids = DB::table('users')->select('id')->someChainOfScopes()->get();
The chained scopes you will have to change to standard where functions etc.
Then use this array to query the role_user table direct
$role_ids = DB::table('role_user')
->select('role_id')
->whereIn('user_id', $user_ids)
->distinct()
->get();
The problem with collections and plucking from collections is it has to iterate over the whole array of objects just to pull a field out. When that is a large collection then iis very costly.
I've not tested but hopefully it will get you going in the right direction.

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

Resources