From 46b2c030dc47ea9fa3eca42ec79e336368585bea Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Wed, 24 Jul 2024 16:39:36 +0200 Subject: [PATCH] Force nullable data to be always nulled --- src/Hydrator.php | 2 ++ src/Model.php | 56 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+) diff --git a/src/Hydrator.php b/src/Hydrator.php index 63b3ff2..bee33a8 100644 --- a/src/Hydrator.php +++ b/src/Hydrator.php @@ -140,6 +140,7 @@ public function hydrate(array $data, Model $model) } else { $subjectClass = $relation->getTargetClass(); $subject = new $subjectClass(); + $subject->setRelation($relation); $parent->$relationName = $subject; } } @@ -187,6 +188,7 @@ public function hydrate(array $data, Model $model) if (! $subject->hasProperty($step)) { $stepClass = $relation->getTargetClass(); $subject->$step = new $stepClass(); + $subject->$step->setRelation($relation); } $subject = $subject->$step; diff --git a/src/Model.php b/src/Model.php index 44baff7..5f4638c 100644 --- a/src/Model.php +++ b/src/Model.php @@ -14,6 +14,15 @@ abstract class Model implements \ArrayAccess, \IteratorAggregate { use PropertiesWithDefaults; + private $relation; + + public function setRelation(Relation $relation) + { + $this->relation = $relation; + } + + private $nullableProperties; + final public function __construct(array $properties = null) { if ($this->hasProperties()) { @@ -140,4 +149,51 @@ public function createRelations(Relations $relations) protected function init() { } + + private function nullableColumns() + { + if ($this->nullableProperties !== null) { + return $this->nullableProperties; + } + + if ($this->relation === null) { + $this->nullableProperties = (function (): array { + $ref = new \ReflectionClass($this); + $doc = $ref->getDocComment(); + preg_match_all('/@property\s+([^\s]+)\s+\$([^\s]+)/', $doc, $matches); + $cols = []; + foreach ($matches[1] as $i => $type) { + if (strpos($type, '?') === 0 || preg_match('~\|?null\|?~', $type)) { + $cols[] = $matches[2][$i]; + } + } + + return $cols; + })(); + } elseif ($this->relation->getJoinType() === 'LEFT') { + $this->nullableProperties = array_merge($this->getColumns(), (array) $this->getKeyName()); + } else { + $this->nullableProperties = []; + } + + return $this->nullableProperties; + } + + public function __get($key) + { + if (in_array($key, $this->nullableColumns(), true)) { + return null; + } + + return $this->getProperty($key); + } + + public function __isset($key) + { + if (in_array($key, $this->nullableColumns(), true)) { + return false; + } + + return $this->hasProperty($key); + } }