If you want to enforce certain values in your models, you can use simple value objects for this job. This class helps to reuse some of the logic:
/**
* Representation of a simple value object with a single attribute that should be validated
*
* @package Demo
*/
abstract class ValueObject {
/**
* @var mixed
*/
protected $value;
/**
* @param mixed $value
*/
function __construct($value) {
$this->validateValue($value);
$this->value = $value;
}
/**
* Checks if $value is valid
*
* @param mixed $value
* @throws \InvalidArgumentException if value validation fails
*/
abstract protected function validateValue($value);
/**
* Returns the raw $value
*
* @return mixed
*/
public function value() {
return $this->value;
}
/**
* Returns the string representation of $value
*
* @return string
*/
public function __toString() {
return (string)$this->value;
}
}
Just extends ValueObject
and implement the validateValue()
:
class EmailAddress extends ValueObject {
protected function validateValue($value) {
if (!filter_var($value, FILTER_VALIDATE_EMAIL)) {
throw new \InvalidArgumentException('Email address is invalid.');
}
}
}
Then, in your model, use the value object like so:
use Illuminate\Database\Eloquent\Model;
class Student extends Model {
protected $fillable = ['name', 'email', 'score'];
public static function register($name, EmailAddress $email) {
$score = new Score(100);
$student = new static(compact('name', 'email', 'score'));
$student->save();
return $student;
}
public function getEmailAttribute($email) {
return new EmailAddress($email);
}
public function setEmailAttribute(EmailAddress $email) {
$this->attributes['email'] = $email->value();
}
}
Finally, use the model like this:
$student = Student::register(
'John Doe',
new EmailAddress('[email protected])
);
or as an object instance:
$student = new Student;
$student->name = 'John Doe';
$student->email = new EmailAddress('[email protected]');
$student->save();
More info here in the Laracast forums.