Have you noticed that Laravel 10 came with a big skeleton rewriting to use PHP types everywhere - for parameters, properties, variables, and method returns. But let's explore what are the possible types and their syntax details.
Let's look at two code samples:
Without types:
class UserService { public $data; public function processData($user) { // ... }}
With types:
use App\Models\User; class UserService { public array $data; public function processData(User $user): User { // ... }}
The second example is more readable, right? If a developer opens the first example for the first time, he would have questions like "What is $data?" and "What exactly should I pass into $user".
The second code snippet specifies that we're working with arrays and User models.
Of course, many of these issues can be solved by just naming things more clearly, but variable/return types may also help massively.
But it's not just for readability. The practical usage is that PHP would throw errors if the variable of the wrong type is passed.
What Are Possible PHP Types?
Here's a list of types from PHP 7:
- bool
- int
- float
- string
- array
- iterable
- object
- ? (nullable)
- self & parent
- Classes & interfaces
- void
Then, PHP 8 introduced static
and mixed
types. The static
type can only be used as a return type, and mixed
can be a return and property type.
The static
return type is used with fluent methods when returning $this
or static methods that return an instance of the class itself.
public function mutateRecordDataUsing(?Closure $callback): static{ $this->mutateRecordDataUsing = $callback; return $this;}
Then, PHP 8.1 introduced the never
return type. The method with the never
return type cannot return anything. It should throw an Exception or terminate with a die
/exit
call.
function redirect(string $url): never { header('Location: ' . $url); exit();}
Laravel Types and Dependency Resolving
In addition to the PHP types, you may use Laravel classes as types, like in the example above with (User $user)
.
On top of that, Laravel would help you with initializing and auto-resolving the variable of Controllers if you put the parameter with type:
use App\Services\UserService; class UserController{ public function index(UserService $service) { // With that parameter, under the hood, Laravel performs: // $service = new UserService(); $service->getUsers(); }}
Optional Types
You may sometimes see this syntax: ?string $variable
. This question mark signifies that the variable or return type can also be a null.
For example, in Filament, you can set the polling interval for charts as a string. But also, it can be set to null so that polling wouldn't happen.
protected static ?string $pollingInterval = '10s';
Multiple "Union" Types
You may sometimes see this syntax: function something(int|array|string $var)
. It is called Union Types and can be used for properties, function parameters, and return types.
This example shows that $noSearchResultsMessage
can have more than one type, and the method to set the $noSearchResultsMessage
accepts more than one type.
trait CanBeSearchable{ // ... protected string | Htmlable | Closure | null $noSearchResultsMessage = null; public function noSearchResultsMessage(string | Htmlable | Closure | null $message): static { $this->noSearchResultsMessage = $message; return $this; } // ...}
Converting Between Types
PHP has a reputation for "automatically converting everything to everything".
When comparing, there are two ways: loose comparison (==
) and strict comparison (===
).
For example:
$a = 5;$b = "5"; var_dump($a == $b); // truevar_dump($a === $b); // false
Because the $b
variable is a string, the strict comparison returns false.
But there can be cases when the variable type isn't the expected. For such cases, the variable can be cast.
For example:
$a = 5;$b = "5"; var_dump($a === (int)$b); // true
Now, we get true because we tell PHP to make $b
as an integer.
No comments yet…