I'm using Laravel 4; the models in question extend Eloquent
.
I've got a relationship between two models, listing
and photo
. I'm compiling a collection of listings
that do not have any corresponding photos
. Eloquent has a handy method for finding records that DO have related records:
$listings = Listing::has('photos')->get();
I'm unaware of the existence of an inverse of the has
method. If there is one, please let me know.
Anyway, this is how I solved the problem:
// fetch all the listings, eagerly loading the photos relationship
$listings = Listing::with('photos')->get();
foreach ($listings as $key => $listing)
{
// if the listing has photos, remove it from the collection
if (count($listing->photos) != 0)
{
unset($listings[$key]);
}
}
This works just fine, but I'm trying to expand my knowledge. Reading the Laravel documentation on collections, there is an example of filtering collections:
$users = $users->filter(function($user)
{
if($user->isAdmin())
{
return $user;
}
});
I rewrote my for
loop using this method:
$listings = $listings->filter(function($listing)
{
// Keep listings with no photos
if (count($listing->photos) == 0)
{
return $listing;
}
});
The resulting $listings
object is identical both cases. Is there any compelling reason to choose one method over the other, or is it simply a matter of personal preference?
The choice between the two is a matter of personal preference.
Some remarks anyway:
If backward compatibility is an issue, then don't use closures. They are a PHP 5.3 language construct. That shouldn't be a problem anymore these days, however.
The only other thing that could play a significant role, is performance. But for loops are more or less equally fast as closures in PHP. And if performance does become an issue, you should change the method altogether and only fetch the right records in the first place.
As for readability: the for loop approach will be easier to understand for unexperienced PHP programmers, while the closure approach is a bit clearer once you understand filtering with closures. Filtering with a closure is more "modern" anyway.