Ray Lee | 李宗叡
Learn or Die
Published in
2 min readJul 15, 2023

--

Scenario

Assuming that today, I have a method sleep(). This method takes in the number of seconds as an argument. Typically, we would write it like this:

<?php
public function sleep(int $seconds)
{
//
}

However, what if a negative value is passed as an argument? This is obviously not valid, but it can be done, leading to unexpected exceptions being thrown.

Therefore, we would generally rewrite it as follows:

<?php
public function sleep(int $seconds)
{
if ($seconds < 0) {
throw new InvalidArgumentException();
}

//
}

Problem

While the above approach does solve the issue, what if we have many methods that take in $seconds as an argument? Do we need to write many if conditions to validate them all?

Solution

# Using types for validation

Perhaps, we can modify the code as follows:

<?php
public function sleep(Duration $seconds)
{
//
}

The core concept is that when we find an argument that has a special meaning, we can consider converting it into a simple class that represents a specific type. While being reusable, this class also increases readability.

# Type implementation

For PHP 7.4

<?php

use InvalidArgumentException;

final class Duration
{

public $seconds;

public function __construct(int $seconds)
{
if ($seconds < 0) {
throw new InvalidArgumentException();
}

$this->seconds = $seconds;
}

public static function seconds($seconds)
{
return new self($seconds);
}

}

For PHP 8.1

<?php

namespace App\Types;

use InvalidArgumentException;

final class Duration
{

public function __construct(public readonly int $seconds)
{
if ($this->seconds < 0) {
throw new InvalidArgumentException();
}
}

public static function seconds(int $seconds)
{
return new self($seconds);
}

}

Usage

<?php
sleep(Duration::seconds(5));

Throws exception

<?php
sleep(Duration::seconds(-5));

--

--

Ray Lee | 李宗叡
Learn or Die

It's Ray. I do both backend and frontend, but more focus on backend. I like coding, and would like to see the whole picture of a product.