Doing stricter checks in PHP
Tags: php, laravel, refactoring, webdev
Published: 2023-04-09 10:41:36

A nice refactoring I've learned recently is to utilize types in conditionals.

For years I’ve been doing `if (!empty($posts))`, but [Rector](https://getrector.com/), a tool to automatically refactor code, changed that to `if ($posts === [])`. The main advantage of using `$posts === []` is that it is more explicit and less prone to unexpected behavior.

It might not seem like much, but it's quite telling of the codebase you're working with. Using `$posts === []` demonstrates a higher level of attention to detail and a commitment to writing more reliable and predictable code. It shows that you are thinking about the specific requirements of your code and taking steps to ensure that it behaves as expected.

On the other hand, using `!empty($posts)` can suggest a more casual approach to programming, where you are relying on PHP's default behavior rather than explicitly defining the expected behavior of your code. While this may be acceptable for smaller projects, it can lead to unexpected bugs and difficulties as your codebase grows and becomes more complex.

Here are some other refactorings I've learned that make me feel like I'm in charge of the code, and not the way around.

## Using strict comparison to check for null or empty strings:
```php
// Before
if ($username == null) {}
if (!$username) {}

// After
if ($username === null) {}
```
The first two conditions check if `$user` is not truthy, which includes checking if it's `null`, `false`, 0, or an empty string. With the after example, we can use the strict comparison operator `===` to specifically check if `$username` is `null`.

## Type hints in function parameters:
```php
function calculate(int $x, int $y) {
    // Do something
}
```
In this example, the `int` type hint ensures that `$x` and `$y` are integers. If a non-integer value is passed to the function, PHP will throw a `TypeError`. 

## Using `array_key_exists()` to check for array keys:
```php
// Before
if (isset($data['username'])) {
    // Do something
}

// After
if (array_key_exists('username', $data)) {
    // Do something
}
```
In the before example, we're using the `isset()` function to check if `$userData['username']` exists. With the after example, we can use the `array_key_exists()` function to specifically check if the `'username'` key exists in `$userData`.

## Null coalescing operator and null coalescing assignment operator:
```php
// Before
if (isset($userData['username'])) {
    $username = $userData['username'];
} else {
    $username = 'Guest';
}

// After
$username = $userData['username'] ?? 'Guest';
```

In the before example, we're using an `if` statement to check if `$userData['username']` exists and setting `$username` accordingly. With the after example, we can use the null coalescing operator `??` to set `$username` to `$userData['username']` if it exists, and `'Guest'` if it doesn't. Additionally, we can use the null coalescing assignment operator `??=` to assign the default value to `$username` only if it's not already set.

These stricter checks help us write more reliable and predictable code, catch errors early, and save ourselves from potential headaches in the future. While some of these refactorings may take some getting used to, they are worth the effort to improve the quality of our code. Or, just install Rector and let it handle them for you. Happy coding!