whereHas
methodThe whereHas
operates on defined relationships in the model and allows for filtering rows based on queries of the relationship.
whereHas
method accepts the name of the relationship (implemented by methods in model) as its first argument and an anonymous function as its second argument.
<aside> 💡
Anonymous Functions in PHP are function expressions that have no name and are often passed as arguments to other functions.
function a(f) { f() } // this function accepts an anonymous function as argument
a(function () { // anonymous function passed to function a
echo 'this is an anonymous function';
});
Anonymous functions can be assigned to variables:
function a(f) { f() } // this function accepts an anonymous function as argument
$b = function () { // anonymous function assigned to variable b
echo 'this is an anonymous function';
};
a($b); // anonymous function b passed to function a
If an anonymous function needs to access variables outside of its scope, it must create a closure over those by leveraging the use
keyword:
$name = 'Laravel'
function a(f) { f() }
$b = function() use ($name) { // anonymous function b creating a closure
echo 'Hello' . $name;
};
a($b);
</aside>
<aside> 💡
Anonymous Functions can be written with the arrow function syntax starting with PHP version 7.4. They automatically create a closure over variables of the previous scope and eliminate the need for use
but are much more limited in their capabilities compared to regular anonymous functions.
$f = fn($n) => var_dump($n);
</aside>
<aside> 💡
Anonymous functions passed to whereHas
method as the second argument, take a query builder instance as their argument, this query builder can be used to query the relationship referenced in the first argument.
</aside>
$users_with_active_phone_query = User::whereHas(
'phone',
fn($q) => $q->where('is_active', true) // sub query on phone relationship
);
get
methodIn order to run the queries and retrieve information from the database, get
query must be invoked. By default, get
method automatically selects all properties of the model it was used on
$users_with_active_phone = User::whereHas(
'phone',
fn($q) => $q->where('is_active', true)
)->get();
get
method also accepts an optional array of property names select which columns must be selected in the database query. Properties of relationships are accessed by using dot notation in following format : relationship_name.property_name
<aside> 💡
In order to select all properties of a model or all columns of a table following notation is used: relationship_name.*
or table_name.*
. This normalizes the returned array and prevents creation of nested arrays.
</aside>
<aside> 💡
In order to rename a property when calling get
the following notation can be used : property_name as new_property_name
</aside>
$users_with_active_phone = User::whereHas(
'phone',
fn($q) => $q->where('is_active', true)
)->get(['name', 'phone.number']);
<aside> 💡
select
method will also filter the columns returned by the query, however, unlike get
it doesn’t invoke the query and must be followed with get
down the chain. It doesn’t use an array for property names.
$users_with_active_phone = User::whereHas(
'phone',
fn($q) => $q->where('is_active', true)
)->select('name', 'phone.number')
->get(); // must be called
</aside>
get
method runs the query and returns the result as a collection
<aside> 💡
Collections are powerful, flexible wrappers built around arrays and allow for running eloquent queries on themselves.
$users = User::all(); // returned as collection
$verified_users = $users->where('is_verified', true); // query on collection
<aside> ⚠️
Loading all rows and running queries on collections is an anti-pattern and should be avoided. Always run the query directly for better optimization and performance:
$verified_users = User::where('is_verified', true); // correct
</aside>
</aside>
save
methodsave
method is used to apply a change made on an object to the database. If not used after altering the object, the changes will not be made in the database.