So here’s a quick one! Below are 3 of some features that I use regularly when I write some Laravel code, but I feel like isn’t that well known. Let’s get started!
Collection
methods with a model’s property.Here’s a static method from one of my projects that fetches and filters a student’s ““applications”” (think internship applications), wherein only the active ones (i.e. not cancelled) are returned.
public static function getActiveApplicationsSent(User $student)
{
return $student->applications->reject(function ($application) {
return $application->is_cancelled;
})->sortByDesc('created_at');
}
You can actually refactor the code above in a single, compact line by chaining the reject
with the relevant property (in this case is_cancelled
):
public static function getActiveApplicationsSent(User $student)
{
return $student->applications->reject->is_cancelled->sortByDesc('created_at');
}
Pretty neat, huh?
That’s a mouthful. Let’s give an example from a fictional library app:
$factory->define(Book::class, function (Faker $faker) {
return [
'title' => $faker->sentence,
'summary' => $faker->paragraphs(2),
'author_id' => function () {
return factory(Author::class)->create()->id
}
];
});
Even though the closure syntax is logical and easy to understand, it doesn’t quite describe what we want to do. All we care is that an Author
is generated from a factory for that Book
, right? Let me give you a clearer alternative:
$factory->define(Book::class, function (Faker $faker) {
return [
'title' => $faker->sentence,
'summary' => $faker->paragraphs(2),
'author_id' => factory(Author::class)
];
});
Short and sweet!
To conclude, let’s use another fictional app that handles multiple account types such as a marketplace application wherein a Merchant
and a Customer
account are at play. The gist is that when they view a merchant’s storefront, they’d see a different presentation (say, a ““Buy Now”” or ““Contact Merchant”” appears for a Customer
) that uses the same data source (i.e. that specific merchant’s product lists). Here’s a sample implementation:
// MerchantProductsController
public function index(User $merchant, Request $request)
{
$products = $merchant->products;
if ($request->user()->isMerchant()) {
return view('products.index.merchant', [
'products' => $products,
]);
}
if ($request->user()->isCustomer()) {
return view('products.index.customer', [
'products' => $products,
]);
}
}
Now clearly this is not scalable. What if we introduced another account type, say a Developer
account down the line? That means we need to add and duplicate the same code n + 1
times. To solve this, we can leverage polymorphism and infer the view name from the requesting user’s account type:
// MerchantProductsController
public function index(User $merchant, Request $request)
{
// account_type could be a database field, a computed property, etc...
return view('products.index.' $request->user()->account_type, [
'products' => $merchant->products,
]);
}
In this article, we covered some facilities to clean up your collection method chains, shorten relationship generation within factories, and utilize polymorphism for rendering views. I hope you got something useful :)
Got any feedback or suggestions? Feel free to send me an email or a tweet.
Ciao!