Policies
Policies allow you to create sets of rules how to transform your data to and from Entity and sub-Entities. There are three types of policies: Global, Local and inherited from parent. You can define them depending on the type. Note: all the examples use relative namespaces.
Global policies are defined in php documentation comments:
/** @Policy\To\Auto
* @Policy\From\Skip */
protected $propertyName;
Global policies have lower priority level than local and same level as inherited from parent.
Local policies are defined inside Policy class:
$policy = (new Policy\Auto)->inside([
'propertyName' => new Policy\To\Skip
])
Local policies always override global and inherited from parent if specified.
If you specify a policy for entity and it has 'propagating' option set to true, it is passed to sub-entities with lower priority:
/** @ORM\Entity */
class A implements ITransformable {
use Transformable;
/** @ORM\Column(type="datetime") */
protected $dt;
// ...
}
/** @ORM\Entity */
class B implements ITransformable {
use Transformable;
/** @ORM\OneToOne(targetEntity="A") */
protected $a;
/** @ORM\Column(type="datetime") */
protected $dt;
// ...
}
$e = (new B())->setA(new A());
$result = $e->toArray(
(new Policy\To\FormatDateTime())->format('Y-m')
)
Here Policy\To\FormatDateTime will be used for B::dt, passed to A with lower priority and will be used for A::dt.
But if Policy's 'propagating' option is set to false, a new Auto policy with lower priority will be passed.
Combines Policy\To\Auto and Policy\From\Auto together. Automatically decides what to store, it typically uses getter/setter of the field.
Global policy: the same behaviour when field isn't specified.
Local policy: overrides and ignores all the global policy parameters.
Combines Policy\To\Skip and Policy\From\Skip together.
Skips the field in both ITransformabe::fromArray and ITransformabe::toArray.
These policies are used in ITransformabe::toArray and ignored in ITransformabe::fromArray.
Automatically decides what to store, it typically uses getter/setter
Global policy: the same behaviour when field isn't specified.
Local policy: overrides and ignores all the global policy parameters.
Uses closure to override the default formatting behaviour.
/** Sets closure to format the SCALAR field.
* @param \Closure $handler function($value, $columnType)
* The $value is passed to closure BEFORE any transformation.
* $columnType can be one of Doctrine DBAL types or null for non-doctrine type.
* @see http://docs.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/types.html#mapping-matrix
* The closure function MUST return a new value that will be placed at the result array.
*
* @return Custom */
public function format(\Closure $handler)
/** Sets closure to transform the RELATION (Entity or Collection) field into array.
* @param \Closure $handler function($original, $transformed)
* $original can be an Entity, Collection or null
* $transformed is a transformation result, it can be changed and returned.
* The closure function MUST return a new value that will be placed at the result array.
*
* @return Custom */
public function transform(\Closure $handler)
Local (only):
$formatted = (new Policy\To\Custom())->format(function($value, $columnType) {
return $value * 1000;
});
$transformed = (new Policy\To\Custom())->transform(function($original, $transformed) {
$transformed['value'] = $original->getValue() * 1000;
return $transformed;
});
$nulled = (new Policy\To\Custom())->transform(function($original, $transformed) {
return null;
});
Sets the fetch offset and limit for the result collection.
It works with OneToMany and ManyToMany associations ONLY!
It works effectively when "fetch" option is set to "EXTRA_LAZY" - sends offset and limit instruction directly to the database.
It's not inherited from parent's global policy.
It's not inherited from parent's policy (!). Specify inside() to change behaviour.
Formats datetime according to \DateTime::format schema
@see http://php.net/manual/en/function.date.php#refsect1-function.date-parameters
Note: ITransformable always works in UTC timezone.
/** @return FormatDateTime */
public function format($f)
Global:
/** @Policy\To\FormatDateTime
* @ORM\Column(type="datetime") */
protected $dt1;
/** @Policy\To\FormatDateTime(format="Y_m_d_H_i_s")
* @ORM\Column(type="datetime") */
protected $dt2;
Local:
$policy = (new Policy\To\Auto)->inside([
'dt1' => new Policy\To\FormatDateTime,
'dt2' => new Policy\To\FormatDateTime(['format' => "Y_m_d_H_i_s"])
]);
Don't convert \DateTime to ISO8601 string in ITransformabe::toArray
@see http://www.iso.org/iso/catalogue_detail?csnumber=40874
Note: ITransformable always works in UTC timezone.
Excludes the field from result.
These policies are used in ITransformabe::fromArray and ignored in ITransformabe::toArray.
Automatically decides what to store, it typically uses getter/setter of the field.
Global policy: the same behaviour when field isn't specified.
Local policy: overrides and ignores all the global policy parameters.
Uses closure to manually parse the field into Entity.
/** Sets closure to prove if the field should be changed or skipped.
* @param \Closure $c function($value,
* $propertyName,
* \Indaxia\OTR\ITransformable $entity,
* \Doctrine\ORM\EntityManagerInterface $em)
* The closure function MUST return TRUE if the field has been processed
* or FALSE to let OTR process it using Auto policy.
*
* @return Custom */
public function parse(\Closure $c)
Local (only):
(new Policy\From\Custom())->parse(function($value, $propertyName, $e, $em) {
return (!$e->isAdmin() || $e->isBlocked()); // false = process automaticaly
});
Don't create a new sub-Entity or scalar when it needed, skip instead in ITransformabe::fromArray.
It's applicable to Collection too.
It's applicable to scalar fields: it denies to set the new value if the value is empty.
Note: it won't work with non-nullable numbers. Numbers cannot be "empty". @see DenyUpdate
It's not inherited from parent's policy (!). Specify inside() to change behaviour.
Don't null the existent sub-Entity or scalars when it needed, skip instead in ITransformabe::fromArray.
It's applicable to Collection too, but it works really slow when "fetch" option is set to "LAZY". Use fetch options "EAGER" or "EXTRA_LAZY" instead.
It's applicable to scalar fields: it denies to clear the value if it is set.
Note: it won't work with non-nullable numbers. Numbers cannot be "empty".
It's not inherited from parent's policy (!). Specify inside() to change behaviour.
Warning: it allows to assign new entities instead of existent. Use Skip to deny any changes.
Don't update the existent scalar or sub-Entity when it needed in ITransformabe::fromArray.
It's applicable to scalar fields: it denies to change new value if the value is already set.
It's applicable to numbers even when numbers are 0, 0.0, "0.0" etc.
It's applicable to Collection and Entity relations.
It's not inherited from parent's policy (!). Specify inside() to change behaviour.
Set $allowExternal to true to allow RETRIEVING of external entities from the database.
Set $allowExistent to true to allow UPDATING of external or existent entity.
/** Allows updating of any entity from the given source array, regardless of where it retrieved from. */
public $allowExistent = false;
/** If a new id is specified, it calls $entityManager->getReference()
* to retrieve the required entity from the database. */
public $allowExternal = false;
Use it to combine DenyNew and DenyUnset.
Keep in mind that DenyFrom policies are not merged automatically.
Use it to combine DenyNew and DenyUpdate.
Keep in mind that DenyFrom policies are not merged automatically.
Use it to combine DenyUnset and DenyUpdate.
Keep in mind that DenyFrom policies are not merged automatically.
Skips the field from parsing.