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");
}
}
}
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');
}
}
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
) {}
}
When I have multiple cases with multiple repeating patterns, then this is the method I use.
Top comments (1)
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.