php code generator for immutable value objects
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.
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 |
{
"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”.
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.
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;
}
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()
]);
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",
}
}
}
title
was a primitive type to begin with.CuisineEnum
was converted to a string by calling the strval()
function on it.IngredientSet
was converted to an array of arrays by calling the toArray()
method on the set and the set calling
the toArray()
method on each ingredient.toArray()
with SHALLOW
setting:
array(3) {
[title] => "Spaghetti Carbonara",
[cuisine] => "CuisineEnum",
[ingredients] => IngredientSet
}
/** 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
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.