It is nice to be able to set your data in a domain object like so:
$order->setId($id);
$order->setCustomer($customer);
$order->setItems($items);
And then be able to do
if( !$order->validate() ) {
// Invalid data
}
Which will validate all the set data and tell you if it was valid or not. I have an implementation of this I came up with but it is sort of messy and limited to only certain common validation rules like checking the type, length/range and format of the data.
I have been doing a lot of Javascript lately and I like the idea of the anonymous functions and I just found out you can do them in PHP 5.3+ and you can use the $this
keyword from PHP 5.4.
abstract class AbstractEntity {
private $id = 0;
private $validations = array();
public function setId($id) {
$this->id = $id;
// A function to validate the Id
$this->addValidation( function() {
return ( $this->id > 0 );
});
}
public function getId() {
return $this->id;
}
public function validate() {
foreach($this->validations as $validation) {
if( $validation() === false ) {
return false;
}
}
return true;
}
protected function addValidation($function) {
$this->validations[] = $function;
}
}
The Order
class:
class Order extends AbstractEntity {
private $customer;
private $items = array();
private $status;
public function setCustomer(Customer $customer) {
$this->customer = $customer;
// Make sure the customers account is active
$this->addValidation( function() {
return ( $this->customer->isActive() );
});
// Do as many complex validations as needed
}
public function setStatus($status) {
$this->status = $status;
// The status has to be 'Pending' or 'Complete'.
$this->addValidation( function() {
return ( ($this->status === 'Pending') || ($this->status === 'Complete') );
});
}
Doing it this way validations of all different levels of complexity can be done. I was thinking of adding in another parameter to the addValidation()
method so you can group validation rules together so they execute in a certain order.
It needs extra functionality like setting error messages but that should not be too hard to implement.
I was also thinking of maybe making the addValidation()
method public so you can add validations outside of the class that will execute when the validate()
method is called. This could be handy in some scenarios.
Is this a good or bad idea? I would like to see some opinions before I go and change all my code to using this sort of implementation.