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.