Laravel Code Tips

Make your Laravel code cleaner, faster, and safer.

You can implement the ShouldBeEncrypted interface on your jobs to encrypt their payload before they get pushed to the queue

125

πŸ”₯ You can implement the ShouldBeEncrypted interface on your jobs to encrypt their payload before they get pushed to the queue

You can implement the ShouldBeEncrypted interface on your jobs to encrypt their payload before they get pushed to the queue

πŸ’‘ Since @laravelphp v8.19, there is a ShouldBeEncrypted interface that jobs can implement. This encrypts the payload, for example, in case the properties hold sensitive data.

As of v8.25, this works for Listeners, Mailables, and Notifications as well πŸ’«

#Laravel #PHP #webdev https://twitter.com/pascalbaljet/status/1462711618329055232

Use aggregate methods to count related models

123

πŸ”₯ Use aggregate methods to count related models

Use aggregate methods to count related models

When you're counting related models in @laravelphp, opt for aggregates!

πŸ‘Ž Using the count() method on a collection of related models is a tad slower.

Use prefetching to boost the perceived speed of Livewire apps

122

πŸ”₯ Use prefetching to boost the perceived speed of Livewire apps

Use prefetching to boost the perceived speed of Livewire apps

To boost perceived speed in your @LaravelLivewire apps when loading data, make use of prefetching.

The .prefetch modifier tells Livewire to fetch the result in the background on hover, and then displays the result when the button is actually clicked ✨

You can convert Eloquent Collections back to a Query Builder instance

120

πŸ”₯ You can convert Eloquent Collections back to a Query Builder instance

You can convert Eloquent Collections back to a Query Builder instance

A tiny tip about #laravel eloquent.

To retrieve the Query Builder after filtering the results: you can use ->toQuery().

The method internally use the first model of the collection and a whereKey comparison on the Collection models.

Create renderable exceptions

119

πŸ”₯ Create renderable exceptions

Create renderable exceptions

Laravel Tip: You can customize how your exceptions are rendered by adding a 'render' method to your exception.

For example, this allows you to return JSON instead of a Blade view when the request expects JSON.

You can use the data_get() method to safely access a nested array value

115

πŸ”₯ You can use the data_get() method to safely access a nested array value

You can use the data_get() method to safely access a nested array value

πŸ’‘#Laravel Tip: Dealing with deeply-nested arrays can result in missing key / value exceptions. Fortunately, Laravel's data_get() helper makes this easy to avoid. It also supports deeply-nested objects.

You can use the form="another-form" attribute on buttons to submit a different form

113

πŸ”₯ You can use the form="another-form" attribute on buttons to submit a different form

You can use the form="another-form" attribute on buttons to submit a different form

πŸ”₯ I sometimes forget you can use form="form-name" on input types to hook fields inside one form to another. This makes it as if those fields were inside that <form>-tag.

This is super useful if the fields are rendered in the wrong form, but UI wise it makes sense.

Including a unique value, like now() or Str::random(), in the Blade template of a Livewire component is a great way to check if that part of the DOM is getting re-rendered

112

πŸ”₯ Including a unique value, like now() or Str::random(), in the Blade template of a Livewire component is a great way to check if that part of the DOM is getting re-rendered

Including a unique value, like now() or Str::random(), in the Blade template of a Livewire component is a great way to check if that part of the DOM is getting re-rendered

A quick and easy way to check if @LaravelLivewire components are re-rendering when you don't want/need them to.

Add now() or now()->timestamp to your component template. The time value will increment if there's a re-render side effect!

Use the *quietly() methods to create models without firing events using your factories

110

πŸ”₯ Use the *quietly() methods to create models without firing events using your factories

Use the *quietly() methods to create models without firing events using your factories

πŸ“ Here's part 2 of the new Database and Eloquent ORM features in @laravelphp 8.x since the release in September 2020.

One of my favorites is the ability in Model Factories to create models without dispatching any events πŸ”₯

Blog post: https://protone.media/en/blog/database-and-eloquent-orm-new-features-and-improvements-since-the-original-laravel-8-release-22

#Laravel #PHP

Use the --requests flag when creating models to also create form requests

106

πŸ”₯ Use the --requests flag when creating models to also create form requests

Use the --requests flag when creating models to also create form requests

This release of Laravel also includes a "--requests" flag when making models via Artisan. This option will create a "Store{Model}Request" and "Update{Model}Request" form request + update the controller to use those requests on their respective methods. πŸ”₯

Thanks @PovilasKorop!

Use Common Table Expressions to refine your data in complex Eloquent queries

105

πŸ”₯ Use Common Table Expressions to refine your data in complex Eloquent queries

Use Common Table Expressions to refine your data in complex Eloquent queries

⚑️ Database Tip

Sometimes you have very complex queries involving multiple calculation steps. Instead of nesting queries or doing it in application code you can use Common Table Expressions (CTE) to refine your data in every step and even reuse former steps.

Use the Str::headline() method to convert strings to studly words

103

πŸ”₯ Use the Str::headline() method to convert strings to studly words

Use the Str::headline() method to convert strings to studly words

πŸ’‘It's refactor time!

Laravel 8.65 introduces the Str::headline() method, this method converts a string into studly words!

A small change like this results in less noise in my code.

Thanks @SteveTheBauman for this implementation! πŸ™Œ

Use the withAggregate() method to add related values to Eloquent queries using subselects

99

πŸ”₯ Use the withAggregate() method to add related values to Eloquent queries using subselects

Use the withAggregate() method to add related values to Eloquent queries using subselects

πŸ’‘ A little #Laravel tip from the latest blog post to get the week started!

Under the hood, the withAvg/withCount/withSum and other methods in Eloquent use the 'withAggregate' method. You can use this method to add a subselect based on a relationship πŸ’«

#PHP #webdev #OpenSource

You can create text-based tables in Laravel even outside CLI commands

96

πŸ”₯ You can create text-based tables in Laravel even outside CLI commands

You can create text-based tables in Laravel even outside CLI commands

If you ever need to generate text-based tables for sending in text messages, outputting in console, or in logs, @symfony provides an awesome "Table" class, just for that! πŸ’… Such a cool utility! 🀩

You can use valueOrFail() to fetch a value from the database, or abort the request if the queried record does not exist

93

πŸ”₯ You can use valueOrFail() to fetch a value from the database, or abort the request if the queried record does not exist

You can use valueOrFail() to fetch a value from the database, or abort the request if the queried record does not exist

In the next blog posts, I'll cover Database and Eloquent improvements and new features in #Laravel 8.x.

Here's a great little feature that got added in v8.60 πŸ”₯

PR: https://github.com/laravel/framework/pull/38707

Yesterday's post about Collections: https://protone.media/en/blog/a-look-at-new-features-and-improvements-since-the-original-laravel-80-release-collections

#PHP #webdev #opensource

Use declare(strict_types=1) to enable strict mode for type checking

87

πŸ”₯ Use declare(strict_types=1) to enable strict mode for type checking

Use declare(strict_types=1) to enable strict mode for type checking

PHP reminder: The "declare(strict_types = 1);" directive enables strict mode. In strict mode, only a variable of exact type of the β€œtype declaration” will be accepted, or a "TypeError" will be thrown. βœ…

You can make the Http client throw exceptions to terminate execution on any received errors

80

πŸ”₯ You can make the Http client throw exceptions to terminate execution on any received errors

You can make the Http client throw exceptions to terminate execution on any received errors

πŸ’‘ By default, the @laravelphp HTTP client doesn't throw exceptions on client and server errors.

However, you can make it do that by using the 'throw' method, and this method is chainable πŸ”₯

Documentation: https://laravel.com/docs/8.x/http-client#throwing-exceptions

#Laravel #PHP #webdev #webdevelopment

Readonly properties

77

πŸ”₯ Readonly properties

Readonly properties

They're a great way to make your components safer and faster.

Say you have a component for editing some resource.

You enforce the ACL in mount().

But if the user could change the currently edited resource, you'd need to enforce ACL on all requests!

Replace children with a custom directive

76

πŸ”₯ Replace children with a custom directive

Replace children with a custom directive

Imagine that you have a nested component that depends on the parent state. You don't need to sync child state into parent, you just want to replace the child when the parent state changes.

You can use my custom directive for that.

Quick tip: Use $wire.entangle() instead of @entangle

74

πŸ”₯ Quick tip: Use $wire.entangle() instead of @entangle

Quick tip: Use $wire.entangle() instead of @entangle

It's good to get into the habit of using $wire, since it provides a full communication layer for your Livewire component.

It also doesn't run into issues when you use it inside single quoted attributes.

Advanced notifications

73

πŸ”₯ Advanced notifications

Advanced notifications

This trait allows dispatching notifications:

  • on the current page
  • on the next page (after redirect)
  • from any part of your code: you can run Lean::notify() in an action class, a model method, or anywhere else β€” and it will be sent to the browser
Advanced trait design

72

πŸ”₯ Advanced trait design

Advanced trait design

Let's look at the same trait again. It does two interesting things.

  1. Livewire::listen() is superior to hydrate* and dehydrate* when you need access to specific parts of the lifecycle

  2. The instanceof self check scopes the listener to the component

Custom response effects

71

πŸ”₯ Custom response effects

Custom response effects

You can add custom data to response effects. Those are separate from component data, and act more like events.

You can use them when you have some JS code that looks at Livewire responses, and when you want more control than dispatching browser events

Compose components using traits

70

πŸ”₯ Compose components using traits

Compose components using traits

Traits are a powerful way to reuse functionality between Livewire components.

They're generally better than component nesting, since that comes with more complexity and worse performance.

Next up: Advanced trait examples

Call methods from JavaScript

69

πŸ”₯ Call methods from JavaScript

Call methods from JavaScript

Livewire's properties are extremely powerful, which often makes us forget that we can also call methods from the frontend.

Livewire gives you a full component API. Use it!

Use wire:replace

68

πŸ”₯ Use wire:replace

Use wire:replace

As you know, Livewire sometimes runs into painful DOM diffing issues. They can usually be solved with simple workarounds, but sometimes those workarounds get quite complex.

So I built a package that adds a wire:replace directive, telling Livewire to replace an entire chunk of the DOM, instead of trying to diff individual changes.

This one is less obscure

65

πŸ”₯ This one is less obscure

This one is less obscure

The $loop variable.

It greatly complements Tailwind-styled tables.

Striped tables done easily πŸŽ‰

Laravel migrations have a very nice syntax for foreign keys

60

πŸ”₯ Laravel migrations have a very nice syntax for foreign keys

I didn't know about this for so long.

Instead of: $table->unsignedBigInteger('user_id'); $table->foreign('user_id')->references('id')->on('users');

You do: $table->foreignId('user_id')->constrained();

Comparing changes on 'saving' using:

56

πŸ”₯ Comparing changes on 'saving' using:

Comparing changes on 'saving' using:

$model->getOriginal()

in Eloquent event listeners can be very useful.

One such use case is checking whether an order is locked. If it is, the only write action we permit is unlocking it. Only then can changes be made.

Laravel Telescope is great for so many things

52

πŸ”₯ Laravel Telescope is great for so many things

Laravel Telescope is great for so many things

One of them is examining sent emails βœ‰οΈ

You usually don't need a service like Mailtrap. Just use the log mail driver and install Telescope.

(image stolen from the internet)

Relevant for people building packages πŸ“¦

50

πŸ”₯ Relevant for people building packages πŸ“¦

Relevant for people building packages πŸ“¦

It's IMO better to use static properties and have "self-contained" behavior & configuration. Than to have a billion config keys. Especially when building large packages.

Makes the package more extensible, by consisting of atomic parts

People underutilize the exception handler

44

πŸ”₯ People underutilize the exception handler

People underutilize the exception handler

You can tell the app what response to return when a specific exception is encountered.

This is the simplest example. There's many more use cases.

Write functional code when it benefits you

41

πŸ”₯ Write functional code when it benefits you

Write functional code when it benefits you

Functional code can both clean things up and make them impossible to understand. Refactor common loops into functional calls, but don't write stupidly complex reduce()s just to avoid writing a loop. There's a use case for both.

Context matters

40

πŸ”₯ Context matters

Context matters

Above I said that moving business logic to action/service classes is good. But context matters

Here's code design advice from a popular "Laravel best practices" repo. There's absolutely no reason to put a 3-line check into a class. That's just overengineered

Use collections when they can clean up your code

39

πŸ”₯ Use collections when they can clean up your code

Use collections when they can clean up your code

Don't turn all arrays into collections just because Laravel offers them, but DO turn arrays into collections when you can make use of collection syntax to clean up your code.

Use docblocks only when they clarify things

37

πŸ”₯ Use docblocks only when they clarify things

Use docblocks only when they clarify things

Many people will disagree with this, because they do it. But it makes no sense.

There's no point in using docblocks when they don't give any extra information. If the typehint is enough, don't add a docblock.

That's just noise.

Create custom Blade directives for business logic

36

πŸ”₯ Create custom Blade directives for business logic

Create custom Blade directives for business logic

You can make your Blade templates more expressive by creating custom directives. For example, rather than checking if the user has the admin role, you could use @admin.

Use strict comparison

35

πŸ”₯ Use strict comparison

Use strict comparison

ALWAYS use strict comparison (=== and !==). If needed, cast things go the correct type before comparing. Better than weird == results

Also consider enabling strict types in your code. This will prevent passing variables of wrong data types to functions

Avoid queries in Blade when possible

34

πŸ”₯ Avoid queries in Blade when possible

Avoid queries in Blade when possible

Sometimes you may want to execute DB queries in blade. There are some ok use cases for this, such as in layout files.

But if it's a view returned by a controller, pass the data in the view data instead.

Consider using helpers instead of facades. They can clean things up

33

πŸ”₯ Consider using helpers instead of facades. They can clean things up

Consider using helpers instead of facades. They can clean things up

This is largely a matter of personal preference, but calling a global function instead of having to import a class and statically call a method feels nicer to me.

Bonus points for session('key') syntax.

Be friends with your IDE

32

πŸ”₯ Be friends with your IDE

Be friends with your IDE

Install extensions, write annotations, use typehints. Your IDE will help you with getting your code working correctly, which lets you spend more energy on writing code that's also readable.

Use short operators

31

πŸ”₯ Use short operators

Use short operators

PHP has many great operators that can replace ugly if checks. Memorize them.

Consider single-action controllers

30

πŸ”₯ Consider single-action controllers

Consider single-action controllers

If you have a complex route action, consider moving it to a separate controller.

For OrderController::create, you'd create CreateOrderController.

Another solution is to move that logic to an action class β€” do what works best in your case.

Don't use a controller namespace

29

πŸ”₯ Don't use a controller namespace

Don't use a controller namespace

Instead of writing controller actions like [email protected], use the callable array syntax [PostController::class, 'index'].

You will be able to navigate to the class by clicking PostController.

Don't use model methods to retrieve data

28

πŸ”₯ Don't use model methods to retrieve data

Don't use model methods to retrieve data

If you want to retrieve some data from a model, create an accessor.

Keep methods for things that change the model in some way.

Use custom config files

27

πŸ”₯ Use custom config files

Use custom config files

You can store things like "results per page" in config files. Don't add them to the app config file though. Create your own. In my e-commerce project, I use config/shop.php.

Create single-use Blade includes

26

πŸ”₯ Create single-use Blade includes

Similar to single-use traits.

This tactic is great when you have a very long template and you want to make it more manageable.

There's nothing wrong with @including headers and footers in layouts, or things like complex forms in page views.

Create query scopes for complex where()s

25

πŸ”₯ Create query scopes for complex where()s

Create query scopes for complex where()s

Rather than writing complex where() clauses, create query scopes with expressive names.

This will make your e.g. controllers have to know less about the database structure and your code will be cleaner.

Import namespaces instead of using aliases

24

πŸ”₯ Import namespaces instead of using aliases

Import namespaces instead of using aliases

Sometimes you may have multiple classes with the same name. Rather than importing them with an alias, import the namespaces.

Create single-use traits

23

πŸ”₯ Create single-use traits

Create single-use traits

Adding methods to classes where they belong is cleaner than creating action classes for everything, but it can make the classes grow big

Consider using traits. They're meant primarily for code reuse, but there's nothing wrong with single-use traits

Use custom collections

21

πŸ”₯ Use custom collections

Use custom collections

Creating custom collections can be a great way to achieve more expressive syntax. Consider this example with order totals.

Don't use abbreviations

20

πŸ”₯ Don't use abbreviations

Don't use abbreviations

Don't think that long variable/method names are wrong. They're not. They're expressive.

Better to call a longer method than a short one and check the docblock to understand what it does

Same with variables. Don't use nonsense 3-letters abbreviations

Use Data Transfer Objects (DTOs)

19

πŸ”₯ Use Data Transfer Objects (DTOs)

Use Data Transfer Objects (DTOs)

Rather than passing a huge amount of arguments in a specific order, consider creating an object with properties to store this data.

Bonus points if you can find that some behavior can be moved into to this object.

Create fluent objects

18

πŸ”₯ Create fluent objects

Create fluent objects

You can also create objects with fluent APIs. Gradually add data by with separate calls, and only require the absolute minimum in the constructor.

Each method will return $this, so you can stop at any call.

Don't just write procedural code in classes

17

πŸ”₯ Don't just write procedural code in classes

Don't just write procedural code in classes

This ties the previous tweet with the other tips here. OOP exists to make your code more readable, use it. Don't just write 400 line long procedural code in controller actions.

Here's code from my first Laravel project 😬

Dedicate a weekend towards learning proper OOP

16

πŸ”₯ Dedicate a weekend towards learning proper OOP

Know the difference between static/instance methods & variables and private/protected/public visibility. Also learn how Laravel uses magic methods.

You don't need this as a beginner, but as your code grows, it's crucial.

Create helper functions

15

πŸ”₯ Create helper functions

Create helper functions

If you repeat some code a lot, consider if extracting it to a helper function would make the code cleaner.

Avoid helper *classes*

14

πŸ”₯ Avoid helper *classes*

Avoid helper *classes*

Sometimes people put helpers into a class.

Beware, it can get messy. This is a class with only static methods used as helper functions. It's usually better to put these methods into classes with related logic or just keep them as global functions.

Extract methods

13

πŸ”₯ Extract methods

Extract methods

If some method is too long or complex, and it's hard to understand what exactly is happening, split the logic into multiple methods.

Use events

12

πŸ”₯ Use events

Use events

Consider offloading some logic from controllers to events. For example, when creating models.

The benefit is that creating these models will work the same everywhere (controllers, jobs, ...) and the controller has one less worry about the details of the DB schema

Consider using form requests

11

πŸ”₯ Consider using form requests

Consider using form requests

They're a great place to hide complex validation logic.

But beware of exactly that β€” hiding things. When your validation logic is simple, there's nothing wrong with doing it in the controller. Moving it to a form request makes it less explicit

Create model methods for business logic

10

πŸ”₯ Create model methods for business logic

Create model methods for business logic

Your controllers should be simple. They should say things like "create invoice for order". They shouldn't be concerned with the details of how your database is structured.

Leave that to the model.

Create action classes

9

πŸ”₯ Create action classes

Create action classes

Let's expand on the previous example. Sometimes, creating a class for a single action can clean things up.

Models should encapsulate the business logic related to them, but they shouldn't be too big.

Create variables when they improve readability

8

πŸ”₯ Create variables when they improve readability

Create variables when they improve readability

The opposite of the previous tip. Sometimes the value comes from a complex call and as such, creating a variable improves readability & removes the need for a comment.

Remember that context matters & your end goal is readability

It's about the *micro*

3

πŸ”₯ It's about the *micro*

Using some "macro" philosophy for structuring your code, like hexagonal architecture or DDD won't save you.

A clean codebase is the result of constant good decisions at the micro level.

We're writing a book, you can get it for free here.