DEV Community

david duymelinck
david duymelinck

Posted on

How to validate constructor arguments when using constructor property promotion

I have written a post about the php 8.4 property hooks. Where I didn't understand what it did.

And I added validation code examples that have nothing to do with it. So I did rewrite the post. But I didn't want to lose the valid example code. And that is why this post exists.

What is the desired result?

We want to create a user by first and last name. The name parts should not be empty because we assume everyone has a first and last name.

Validation with a class method

class User
{
    public function __construct(private string $firstName, private string $lastName) {
        $this->validate($firstName, 'firstName');
        $this->validate($lastName, 'lastName');
    }

    public function validate(string $value, $argumentName) {
        if (strlen($value) === 0) {
            throw new ValueError("$argumentName must be non-empty");
        }
   }
}
Enter fullscreen mode Exit fullscreen mode

This is the method I use when there are one-off validations

Validation with trait

trait Validation {
    private function notEmpty(mixed $value, $argumentName) {
        if(is_string($value) && strlen($value) === 0) {
            throw new ValueError("$argumentName must be non-empty");
        }
    }

}

class User
{
    use Validation;

    public function __construct(private string $firstName, private string $lastName) {
        $this->notEmpty($firstName, 'firstName');
        $this->notEmpty($lastName, 'lastName');
    }
}
Enter fullscreen mode Exit fullscreen mode

This is the method that I use to centralize validation methods, because there are patterns that are recurring.

Validation with attributes

When your code has a lifecycle event in place that can process attributes, or you use a package like laravel-data. This is how the code might look like.

use Spatie\LaravelData\Data;

class User extends Data
{
    public function __construct(
      #[Min(1)]
      private string $firstName, 
      #[Min(1)]
      private string $lastName
    ) {}
}
Enter fullscreen mode Exit fullscreen mode

When I have multiple cases with multiple repeating patterns, then this is the method I use.

Top comments (1)

Collapse
 
icolomina profile image
Nacho Colomina Torregrosa

I like using the last one. While the attributes of the User class describes which rules the properties must match , an external service is in charge of performing the validations.