Using some magic methods can integrate validation without having to implement get and set methods everywhere.
class ValidationException extends Exception {
}
abstract class DomainModel {
private $validationErrors = array();
final public function __get($field) {
$getMethodName = 'get' . ucfirst($field);
if (method_exists($this, $getMethodName)) {
return call_user_func(array($this, $getMethodName));
} elseif (isset($this->$field)) {
return $this->$field;
}
}
final public function __set($field, $value) {
$setMethodName = 'set' . ucfirst($field);
if (array_key_exists($field, $this->validationErrors)) {
unset($this->validationErrors[$field]);
}
if (method_exists($this, $setMethodName)) {
try {
call_user_func(array($this, $setMethodName), $value);
} catch (ValidationException $e) {
$this->validationErrors[$field] = $e->getMessage();
}
} elseif (array_key_exists($field, get_object_vars($this))) {
$this->$field = $value;
}
}
final public function isValid() {
return count($this->validationErrors) == 0;
}
final public function getValidationErrors() {
return array_values($this->validationErrors);
}
final public function setData($data) {
foreach ($data as $field => $value) {
$this->__set($field, $value);
}
}
final public function getData() {
return get_object_vars($this);
}
}
class Test extends DomainModel {
protected $message;
public function setMessage($msg) {
if ($msg == null || strlen(trim($msg)) == 0) {
throw new ValidationException("Message must not be empty");
}
$this->message = $msg;
}
}
$obj = new Test();
$obj->message = "Hello!";
echo $obj->message . "\n";
$obj->message = " ";
if (!$obj->isValid()) {
foreach ($obj->getValidationErrors() as $error) {
echo $error . "\n";
}
}