Re: [PHP-DEV] Allowing `(object)['key' => 'value']` in initializers?
On Sat, Sep 25, 2021 at 5:45 PM tyson andre wrote: > > Hi internals, > > In PHP 8.1, it is possible to allow constructing any class name in an > initializer, after the approval of > https://wiki.php.net/rfc/new_in_initializers > > ``` > php > static $x1 = new ArrayObject(['key' => 'value']); > php > static $x2 = new stdClass(); > php > static $x3 = (object)['key' => 'value']; > > Fatal error: Constant expression contains invalid operations in php shell > code on line 1 > ``` > > What are your thoughts on allowing the `(object)` cast in initializer > types where `new` was already allowed, but only when followed by an array > literal node. (e.g. continue to forbid `(object)SOME_CONSTANT`) (see > https://wiki.php.net/rfc/new_in_initializers) > > stdClass has never implemented a factory method such as `__set_state` > (which is not yet allowed). Instead, `(object)[]` or the `(object)array()` > shorthand is typically used when a generic object literal is needed. This > is also how php represents objects in var_export. > > ``` > php > var_export(new stdClass()); > (object) array( > ) > ``` > > Reasons: > - The ability to construct empty stdClass instances but not non-empty ones > is something users would find surprising, > and a lack of support for `(object)[]` be even more inconsistent if > factory methods were allowed in the future. > - stdClass is useful for some developers, e.g. in unit tests, when using > libraries requiring it for parameters, > when you need to ensure data is encoded as a JSON `{}` rather than `[]`, > etc. > - It would help developers write a clearer api contract for methods, > e.g. `function setData(stdClass $default = (object)['key' => 'value'])` > is clearer than `function setData(?stdClass $default = null) { $default > ??= (object)['key' => 'value']; ` > - stdClass may be the only efficient built-in way to represent objects > with arbitrary names if RFCs such as https://externals.io/message/115800 > passed > I'm not super convinced about the usefulness of (object)[] in particular, but I also think that we shouldn't artificially limit the types of expressions supported in constant expressions -- if there's no strong reason why something should be forbidden, it should be allowed. >From that perspective, I think the root issue here is that constant expressions currently don't support casts at all. It's not just a matter of being unable to write (object)[], you also can't write (int)X (but you can write +X). I think it's perfectly reasonable to support casts in constant expressions, and if we do, then I don't think we need to go out of the way to forbid object casts either, so support for (object)[] should just fall out as a special case. Regards, Nikita
Re: [PHP-DEV] Allowing `(object)['key' => 'value']` in initializers?
On Mon, Sep 27, 2021 at 3:15 PM Sara Golemon wrote: > I think for consistency's sake, we'd want to provide a base constructor to > stdClass to take an associative array that maps into dynamic properties, > e.g. > > class stdClass { > public function __construct(array $props) { > foreach ($prop as $name => $val) { > $this->$name = $val; > } > } > } > > Then you could: > php> static $x3 = new stdClass(['key' => 'value']); > If the structure of `$something = {};` would ever be allowed in PHP, the following could be done instead: `$something = { ...$array };`. This will reduce the dependency on the stdClass.
Re: [PHP-DEV] Allowing `(object)['key' => 'value']` in initializers?
On Sat, Sep 25, 2021 at 10:45 AM tyson andre wrote: > In PHP 8.1, it is possible to allow constructing any class name in an > initializer, after the approval of > https://wiki.php.net/rfc/new_in_initializers > > ``` > php > static $x1 = new ArrayObject(['key' => 'value']); > php > static $x2 = new stdClass(); > php > static $x3 = (object)['key' => 'value']; > > Fatal error: Constant expression contains invalid operations in php shell > code on line 1 > ``` > > What are your thoughts on allowing the `(object)` cast in initializer > types where `new` was already allowed, but only when followed by an array > literal node. > > I think for consistency's sake, we'd want to provide a base constructor to stdClass to take an associative array that maps into dynamic properties, e.g. class stdClass { public function __construct(array $props) { foreach ($prop as $name => $val) { $this->$name = $val; } } } Then you could: php> static $x3 = new stdClass(['key' => 'value']); This avoids special-casing object cases in the engine while making it clear that a stdClass is what you wind up with, and honestly I think it'd be a useful pattern to use when initializing stdClass with defaults elsewhere. As to whether or not we SHOULD: While using declared props is preferred in the vast majority of cases, both for performance and for readability, there are legitimate cases where a short lived container wants the flexibility and convenience of an untyped, dynamic structure like an associative array with the visually clean aesthetic of object access. stdClass does that, and even if deprecation of dynamic properties passes it will continue to do that. I started this paragraph ambivalent about the feature, but I think I convinced myself around to a +1, though in the constructor form, not the cast form. -Sara
Re: [PHP-DEV] Allowing `(object)['key' => 'value']` in initializers?
> On Sep 25, 2021, at 12:03 PM, Marco Pivetta wrote: > > Hey Tyson, > > On Sat, 25 Sep 2021, 18:00 tyson andre, wrote: > >> My original message had a section with reasons why an end user might want >> that. >> > > Yeh, it sounds like stuff we wanna get away from Point of order here: "we" is not unanimous. -Mike -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: https://www.php.net/unsub.php
Re: [PHP-DEV] Allowing `(object)['key' => 'value']` in initializers?
On 25/09/2021 16:45, tyson andre wrote: What are your thoughts on allowing the `(object)` cast in initializer types where `new` was already allowed I'm not strongly opposed to this, but am not convinced it's a big improvement. Firstly, as with everything involving stdClass, I would be more interested in a) improving the initialization of anonymous objects, and b) allowing those in initialisers (the RFC currently forbids them, but doesn't say why, so I'm not sure if it's an implementation decision or a philosophical one). Secondly, if you have enough knowledge of the structure to provide an inline default, then you probably have enough to be worth defining a named class, even if that class then implements __set() to allow additional ad hoc properties. That class can then have its own defaults, so that your example becomes `function setData(Data $values = new Data())` Regards, -- Rowan Tommins [IMSoP] -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: https://www.php.net/unsub.php
Re: [PHP-DEV] Allowing `(object)['key' => 'value']` in initializers?
Hey Tyson, On Sat, 25 Sep 2021, 18:00 tyson andre, wrote: > My original message had a section with reasons why an end user might want > that. > Yeh, it sounds like stuff we wanna get away from > Not a push for getting rid of stdClass. Way too many things use stdClass > to get rid of stdClass. > Yes, but for legacy reasons, not for further perpetuating the practice. >
Re: [PHP-DEV] Allowing `(object)['key' => 'value']` in initializers?
Hey Marco Pivetta, > > What are your thoughts on allowing the `(object)` cast in initializer types > > where `new` was already allowed, but only when followed by an array literal > > node. (e.g. continue to forbid `(object)SOME_CONSTANT`) (see > > https://wiki.php.net/rfc/new_in_initializers) > > ... > > Reasons: > > - The ability to construct empty stdClass instances but not non-empty ones > > is something users would find surprising, > > and a lack of support for `(object)[]` be even more inconsistent if > > factory methods were allowed in the future. > > - stdClass is useful for some developers, e.g. in unit tests, when using > > libraries requiring it for parameters, > > when you need to ensure data is encoded as a JSON `{}` rather than `[]`, > > etc. > > - It would help developers write a clearer api contract for methods, > > e.g. `function setData(stdClass $default = (object)['key' => 'value'])` > > is clearer than `function setData(?stdClass $default = null) { $default > > ??= (object)['key' => 'value']; ` > > - stdClass may be the only efficient built-in way to represent objects with > > arbitrary names if RFCs such as https://externals.io/message/115800 passed > passed > > Right now, there's even an interest in getting rid (or deprecating) dynamic > properties on objects: why push the complete opposite ways? > > What is the actual value of using an stdClass instance instead of an > `array` (already supported)? My original message had a section with reasons why an end user might want that. There's a push for getting rid of (or deprecating) dynamic properties on **objects that are not stdClass (or subclasses)** Not a push for getting rid of stdClass. Way too many things use stdClass to get rid of stdClass. (whether or not stdClass gets aliased or even renamed to DynamicObject). ``` php > var_dump(json_decode('{}')); object(stdClass)#1 (0) { } ``` Thanks, Tyson -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: https://www.php.net/unsub.php
Re: [PHP-DEV] Allowing `(object)['key' => 'value']` in initializers?
Hey Tyson, On Sat, 25 Sep 2021, 17:45 tyson andre, wrote: > What are your thoughts on allowing the `(object)` cast in initializer > types where `new` was already allowed, but only when followed by an array > literal node. (e.g. continue to forbid `(object)SOME_CONSTANT`) (see > https://wiki.php.net/rfc/new_in_initializers) > Right now, there's even an interest in getting rid (or deprecating) dynamic properties on objects: why push the complete opposite ways? What is the actual value of using an stdClass instance instead of an `array` (already supported)? >