> On Sep 8, 2021, at 5:44 AM, Rowan Tommins <rowan.coll...@gmail.com> wrote: >> Is it just a special-cases that will cause as much confusion for developers >> trying to understand why there are too names for the same thing as it will >> help those who will better understand the new name > > That is certainly a risk, and a factor in favour of having some plan to > retire the old name, even if only after a long overlap.
Ironically I believe if we add `DynamicObject` as an alias of `stdClass` where `DynamicObject::class === 'stdClass'` that would not provide much ability to retire `stdClass` any sooner than if we just deprecated it today. All future code that needs to refer to the class name will still refer to `stdClass`, so we won't be gaining much by creating an alias. OTOH if we introduce a **completely new class** named `DynamicObject` having exactly the same behavior as a `stdClass` object (at least initialize) then we could add any new behavior to `DynamicObject` and leave `stdClass` fully in-tact for as long as we need to, except for notes in the docs that say to move to `DynamicObject` and tools like PhpStorm, Psalm and Phan could start suggesting a move away from `stdClass` right away. With a new independent class `'DynamicObject' === get_class( new DynamicObject )` would always be true, and people who want to future proof their code could start replacing `stdClass` with `DynamicObject. People that don't (want to) make the change could maybe get a warning in PHP 9 and then maybe we remove `stdClass` in PHP and they must evolve or stick with PHP 8. #fwiw I think `DynamicObject` is the best semantic name floated thus far albeit sadly on the rather long side. `DynamicClass`, also long, could work too... ======== Of course having a different class begs the question of what `get_class((object)array())` should return? Clearly for BC it needs to be `stdClass`, but as long as it is `stdClass` then we get no real benefit from aliasing with DynamicObject. Further, although the expression style of `(object)['prop' => 'value']` is the simplest way to initialize a basic `object` with literals in a single expression it is still a bad workaround that is far from intuitive for new developers, and feels like we are just leveraging an accidental capability rather than a well-designed language feature. If we want `DynamicObject` to eventually replace `stdClass` why not ALSO provide new syntax to give people a reason to switch to it? Why not leverage the named constructor concept but as a special case for `DynamicObject`, and only for `DynamicObject` (not `stdClass`); allow any arbitrary names to be used in constructor promotion? Instead of this: $obj = (object)array( "foo" => 1, "bar" => "hello", "baz" => true, );o We could do this instead: $obj = new DynamicObject( foo: 1, bar: "hello", baz: true, ); AND since we are talking a singular special case, why not also add a `DynamicObject()` function to streamline it a bit: $obj = DynamicObject( foo: 1, bar: "hello", baz: true, ); OR we could get inspired by the shortening of `function()` to `fn()` and used obj() (since `do()` is probably unworkable): $obj = obj( foo: 1, bar: "hello", baz: true, ); OR my personal favorite (though I know that would be a bridge too far for many) why not just this, too? $obj = { foo: 1, bar: "hello", baz: true, }; While we are at it, DynamicObject could add a few really useful methods such as `fromArray()`, `toJSON()` and more? (And if I really want to get crazy, `toSqlUpdate()`, `toSqlInsert()`, etc, but now I fear I am just scaring people off.) If we gave a better developer experience with literal initializers and useful methods then we've give a lot of developers reason to update their code to use `DynamicObject` and thus we could deprecate `stdClass` sooner. A couple more things; add a `JSON_OUTPUT_DYNAMIC_OBJECT` flag to output to DynamicObject for `json_decode()`, add a 3rd parameter for flags to var_export() for the same reason, a `'return_dynamic_object'` option for `unserialize()`, and so on. (BTW, we don't have to do ALL these things in one RFC. But we could go ahead and discuss the potential of having future RFCs that would add these features.) >> or is it more fully addressing the use-case for why people use dynamic >> objects? > > The thread comes from a comment I made in Nikita's discussion about > deprecating dynamic properties on normal objects. There was no grand vision > behind it, just a long-standing dislike of the name "stdClass", and a concern > that documenting "extends stdClass" as a way to enable dynamic properties on > a custom class would make the confusion worse. Yes, I followed that discussion. But the fact you had a discussion doesn't ensure that the proposed solution is the proper one. Hence why I was trying to illicit a discussion about what would be more proper. > The one thing missing from anonymous classes right now is an elegant way to > capture data from outer scope when you create them. I'm not exactly sure what that means, but if I had to guess I think maybe you are talking about a literally initialization syntax which is something I covered above? -Mike P.S. > There are some places that have to return some "real" name for the class, > like get_class($obj). The current proposal is that "stdClass" be kept as the > real name, at least initially, so you would see this: > > $obj = new DynamicObject; > echo get_class($obj); // stdClass Yes, and that is where I see it to be most problematic, although admittedly for a built-in class with no predefined methods or properties the places where it could break an application are certainly many fewer than aliases for userland classes. But I digress on this latter point... > You can get a better idea of what's being proposed using the class_alias() > function, which lets you create an alias for a user-defined class: > https://3v4l.org/a4EI0#v8.0.10 Thanks for educating me on the existence of `class_alias()`; 12+ years of professional PHP and I can't remember ever noticing that existed. If it didn't exist I would challenge why we need it, especially because it breaks the boolean which I had thought was true, that $class_name === get_class( new $class_name() ). But since it does exist me arguing that would be moot. >> So what are the use-cases where dynamic objects still make sense, and just >> as importantly what about those use-cases is still suboptimal besides just >> the class name? > > To be honest, I think most uses of stdClass would be better served by > anonymous classes, and would have been written that way if the feature had > existed for longer. Hmm. That seems like replacing apples with oranges. I assume we would also disallow dynamic properties in anonymous classes too, right? After all, they are just statically declared classes that the developer do not assign a name. Anonymous class objects have different strengths and weaknesses and thus are useful in different contexts than dynamic objects. > My guess would be that the name reported by get_class etc would mainly be > used in tests and debugging, whereas instanceOf checks (and type constraints) > will be used in actual "business logic" code paths. Existing code will expect > "instanceOf stdClass" to work, and new code will expect "instanceOf > DynamicObject" to work, so an alias (in either direction) seems the better > compromise. Besides, don't forget `stdClass::class` in addition to `get_class()`. Anyway, with respect, I'd like to hear use-cases from others who are the ones saying they are using a lot of stdClass objects in their existing code. They may have insight that neither you nor I have on the topic. -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: https://www.php.net/unsub.php