vog

php code generator for immutable value objects

View the Project on GitHub MarvinWank/vog

ValueObject

A value object is an object that once constructed cannot be changed. It has getters, but no setters. Also, it doesn’t do any business logic at all. It truly is an object that holds values - and nothing more.

Properties

name data type default optionality description
type string - required for all defines the type of object to be generated. valid types are ‘enum’, ‘nullableEnum’, ‘valueObject’ and ‘set’
name string - required for all defines both the php class name and file name of the value object to be generated
values object - required for all except set defines the values to be represented by the value object to be generated. Syntax and effect vary by type.
extends ?string ”” optional Optionally states the name of the class this object should extend
implements array [] optional Optionally states the name(s) of the interface(s) this object should implement
mutable bool false optional for value objects Optionally states the mutability of the object. If so, the object will have setters.
dateTimeFormat string global value optional for value objects Optionally defines an object-specific DateTime-Format

Example

    {
      "type": "valueObject",
      "name": "Recipe",
      "values": {
        "title": "string",
        "minutesToPrepare": "?int",
        "rating": "float",
        "dietStyle": "DietStyle"
      },
      "string_value": "title"
    }

If you don’t want to specify a datatype, simply provide an empty string.

Notice that you may also define nullable types and object types. You’ll have to provide the namespace to the object, but in this case, “DietStyle” hast the same namespace as “Recipe”.

Example Result

Vog will generate private class members according to the definition in the value file.

final class Recipe
{
    private string $title;
    private ?int $minutesToPrepare;
    private float $rating;
    private DietStyle $dietStyle;

The members are available by getter functions:

    public function getTitle(): string {
        return $this->title;
    }

As it is an immutable value object per default, there are no setters. Instead, you’ll have to create entirely new objects if you want to alter a value. This is made easy by the with_ methods:

    public function withTitle (string $title):self
    {
        return new self($title,$this->minutes_to_prepare,$this->rating,$this->diet_style,);
    }

with methods will be generated for each member defined in the value file.

If you declare your object "mutable": true, it will have with methods in addition to setters setTitle(string $title) to ensure compatibility.

Instantiating a generated valueObject

You can use the constructor to create a new instance providing all required parameters.

    public function __construct (string $title, ?int $minutesToPrepare, float $rating, DietStyle $dietStyle)
    {
        $this->title = $title;
        $this->minutesToPrepare = $minutesToPrepare;
        $this->rating = $rating;
        $this->dietStyle = $dietStyle;
    }

fromArray

A value object can also be created from the static fromArray() method. The keys of the array must match the property names.

$obj = new Recipe::fromArray([
    'title' => 'Title',
    'minutesToPrepare' => null,
    'rating' => 10,
    'dietStyle' => DietStyle::VEGAN()
]);

toArray

A value object may also be converted into an associative array, for example for data transfer purposes. The method will produce different results, depending on the configuration value of toArrayMode.

This is ensured by first checking the non-primitive member for a toArray() function. If it does have one, this function is called. If it does not have one, the value is casted to string.

Since all elements generated by vog either have a toArray method or a fitting implementation of __toString(), no strange effects occur when building vog value objects solely on vog generated elements. However, use that function with caution when mixing other objects into vog value objects!

Example:


        {
            "type": "valueObject",
            "name": "Recipe",
            "values": {
                "title": "string",
                "cuisine": "CuisineEnum",
                "ingredients": "IngredientSet"
            }
        }

toArray() with the DEEP setting:

array(3) {
  [title] => "Spaghetti Carbonara",
  [cuisine] => "MEDITERRANEAN",
  [ingredients] =>
    array(3) {
      array(3) => {
        [name] => "Spagehtti",
        [amount] => "200",
        [unit] => "g",
      },
      array(3) => {
        [name] => "Eggs",
        [amount] => "3",
        [unit] => "pieces",
      },
      array(3) => {
        [name] => "Parmesan",
        [amount] => "150",
        [unit] => "g",
      }
    }
}

toArray() with SHALLOW setting:

array(3) {
  [title] => "Spaghetti Carbonara",
  [cuisine] => "CuisineEnum",
  [ingredients] => IngredientSet
}

other methods

    /** Compares two enums of the same type for equality */
    public function equals(?self $other): bool

If you define string_value for your value object the following methods are added.

    /** Returns the string_value of the value object*/
    public function toString(): string

    /** Same as toString() */
    public function __toString(): string

DateTime Support

Vog does support DateTimeImmutables as strings in toArray and fromArray! Just set \\DateTimeImmutable (double backslash necessary for escaping) as the data type and vog takes care of the rest.

The default format is Y-m-d, yet that can be changed both globally and individually

for each object.

\\\DateTime is also possible, but only when the value object is explicitly declared mutable. Otherwise vog will throw an exception.