This is an archived post from my previous blog. Some content may be outdated. FYI!


Introduction

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!

1. Chain 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!

3. Try and see if polymorphic views can clean up your controller logic

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,
    ]);
}

Conclusion

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!