Back to Course |
PHP for Laravel Developers

Variable Types and Return Types

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); // true
var_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.