-
-
Notifications
You must be signed in to change notification settings - Fork 60
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Reordered property type resolution to resolve typed properties before…
… untyped ones Due to how PHP 7.4 works, if you have a typed public property that does not support null values, whenever Doctrine tries to delete an entity with such properties, it raises a TypeError. This happens because of the new default "uninitialized" value for typed properties. In previous versions of PHP, the default uninitialized value was null. My fist idea was to just reverse the order, and while that worked, it introduced a BC break. Now, as per @guilliamxavier suggestion, I've moved the methods from the class TypedNoDefaultRuntimePublicReflectionProperty to a trait, then I proceeded to create a new class extending RuntimePublicReflectionProperty, that uses the new trait. With this, whenever Doctrine tries to access a public property with no default value set, it will properly unset the property instead of setting it as null getting a PHP TypeError. Reordered property type resolution so typed properties get resolved first, added tests for covering multiple scenarios Fixes #102 Fixes doctrine/orm#7999 Co-authored-by: Guilliam Xavier <guilliamxavier@users.noreply.github.com>
- Loading branch information
1 parent
79e97bc
commit dc3d9eb
Showing
5 changed files
with
117 additions
and
52 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
60 changes: 60 additions & 0 deletions
60
lib/Doctrine/Persistence/Reflection/TypedNoDefaultReflectionPropertyBase.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
<?php | ||
|
||
namespace Doctrine\Persistence\Reflection; | ||
|
||
use Closure; | ||
use ReturnTypeWillChange; | ||
|
||
use function assert; | ||
|
||
/** | ||
* PHP Typed No Default Reflection Property Base - special override for typed properties without a default value. | ||
*/ | ||
trait TypedNoDefaultReflectionPropertyBase | ||
{ | ||
/** | ||
* {@inheritDoc} | ||
* | ||
* Checks that a typed property is initialized before accessing its value. | ||
* This is necessary to avoid PHP error "Error: Typed property must not be accessed before initialization". | ||
* Should be used only for reflecting typed properties without a default value. | ||
* | ||
* @param object $object | ||
*/ | ||
#[ReturnTypeWillChange] | ||
public function getValue($object = null) | ||
{ | ||
return $object !== null && $this->isInitialized($object) ? parent::getValue($object) : null; | ||
} | ||
|
||
/** | ||
* {@inheritDoc} | ||
* | ||
* Works around the problem with setting typed no default properties to | ||
* NULL which is not supported, instead unset() to uninitialize. | ||
* | ||
* @link https://github.com/doctrine/orm/issues/7999 | ||
* | ||
* @param object $object | ||
*/ | ||
#[ReturnTypeWillChange] | ||
public function setValue($object, $value = null) | ||
{ | ||
if ($value === null && $this->hasType() && ! $this->getType()->allowsNull()) { | ||
$propertyName = $this->getName(); | ||
|
||
$unsetter = function () use ($propertyName): void { | ||
unset($this->$propertyName); | ||
}; | ||
$unsetter = $unsetter->bindTo($object, $this->getDeclaringClass()->getName()); | ||
|
||
assert($unsetter instanceof Closure); | ||
|
||
$unsetter(); | ||
|
||
return; | ||
} | ||
|
||
parent::setValue($object, $value); | ||
} | ||
} |
11 changes: 11 additions & 0 deletions
11
lib/Doctrine/Persistence/Reflection/TypedNoDefaultRuntimePublicReflectionProperty.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
<?php | ||
|
||
namespace Doctrine\Persistence\Reflection; | ||
|
||
/** | ||
* PHP Typed No Default Runtime Public Reflection Property - special override for public typed properties without a default value. | ||
*/ | ||
class TypedNoDefaultRuntimePublicReflectionProperty extends RuntimePublicReflectionProperty | ||
{ | ||
use TypedNoDefaultReflectionPropertyBase; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters