Typed properties - feature request

php.internals

Benjamin Morel

7 years ago
Hi internals, I have a feature request related to upcoming typed properties, that I'd like to discuss here first. I'm building a data mapper that will target PHP 7.4, and will make heavy use of typed properties. One of the features that I want to have available, is allowing to load a partial object, by giving a list of properties to load: $user = $userRepo->load(123, ['status', 'followerCount']); Under the hood, load() will create a new User object using ReflectionClass:newInstanceWithoutConstructor(), get the data from the database and populate the requested fields using ReflectionProperty::setValue(). Now when I do: $userRepo->save($user); The repo will use the new ReflectionProperty::isInitialized() method to locate which fields are initialized, and only save these to the database. The problem is, newInstanceWithoutConstructor() *initializes properties to their default value*, so save() has no way to know whether initialized properties have been explicitly set during load(), or are just default value (note: repos are stateless). To overcome this problem, I can think of 2 possible options: *Option 1: add an optional parameter to ReflectionClass::newInstanceWithoutConstructor(), to not initialize properties to their default value:* function newInstanceWithoutConstructor(bool $initializeProperties = true) *Option 2: add a ReflectionProperty::unset() method:* function unset(string $property) This way, I could explicitly unset() every property that was not requested during load(). Currently, there is no way to unset() a protected property from outside the object (i.e. in the data mapper). Note that Option 1 would have a slight performance advantage in my case, while Option 2 may have more use cases outside of mine. What do you think? Cheers, Ben

Marco Pivetta

7 years ago
Hi Ben, Such logic is already possible by casting the object to `(array)`, and therefore receiving a list of all properties that are explicitly set. Also, this seems like something I've already started from Doctrine 3 (but couldn't pursue further due to time constraints). Marco Pivetta http://twitter.com/Ocramius http://ocramius.github.com/ On Thu, Dec 13, 2018 at 3:04 PM Benjamin Morel <benjamin.morel@gmail.com> wrote:

Benjamin Morel

7 years ago
Benjamin said: (...) Regarding your suggestion, unfortunately not, (array) also returns
> default values for properties:
Marco said: Yes, but that's where you should unset all properties upfront:
> class A { > protected $a = 1; > } > $r = new ReflectionClass('A'); > $a = $r->newInstanceWithoutConstructor(); > (function (A $a) { unset($a->a); })->bindTo(null, A::class)($a); > print_r((array) $a); > Array > ( > )
Ah, genius! I did not think we could already use Closures for this. Scratch that then, there is no need for an extra feature 👍 <https://emojipedia.org/thumbs-up-sign/> Thanks Marco. On Thu, 13 Dec 2018 at 16:54, Marco Pivetta <ocramius@gmail.com> wrote: