Skip to content

Instantly share code, notes, and snippets.

@cmaas
Last active October 24, 2017 10:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save cmaas/fa2071a1da9062b395bb to your computer and use it in GitHub Desktop.
Save cmaas/fa2071a1da9062b395bb to your computer and use it in GitHub Desktop.
Laravel: Basic Value Object

Laravel: Basic Value Object

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;
    }
}

Basic Usage

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('john@example.com)
);

or as an object instance:

$student = new Student;
$student->name = 'John Doe';
$student->email = new EmailAddress('john@example.com');
$student->save();

Discussion & Explanation

More info here in the Laracast forums.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment