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 <ocram...@gmail.com> wrote:

> 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.mo...@gmail.com>
> wrote:
>
>> 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
>>
>

Reply via email to