Proposal: magic constant '::name' for properties and methods etc. like '::class' is for classes/object

php.internals

Lydia de Jongh

3 years ago
Hi, Lately I made a small object initializer/builder with php Attributes. 'Directly' accessing properties and methods of the class as a parameter in an Attribute is not really possible. You can do that for a class with: \path\to\MyClass::class, but for properties or methods you have to use strings, without recognition in editors. It would be so nice if more items in php could be accessed with a magic constant as you can do with ::class. With magic constant an editor could recognize it and it limits typos etc. and it provides the developer with a list of the properties/methods in scope. At the moment I implemented a kind of workaround by providing simple classes with the property names in class constants. Or add an extra property to a class with a property name that can be used in an attribute. I will try to explain with examples of my code. abstract class SaveFactoryAbstract { use ObjectBuilderTrait; #[ResetValue] protected bool $isSaved = false; #[InitObject] // tells the builder to initialize this property with the latest specs provided by (other) attributes #[ResetObject] protected ?SaveInterface $oSave = null; public function __construct(){ $this->buildMe(); // provided by the trait } } This is straightforward. Until you extend this class and want to set the class for $oSave. The other developer does not know which properties he can declare with an attribute.... #[UseClass('oSave', ImageSave::class)] #[ResetValue('isSaved', default: true)] class ImageSaveFactory extends SaveFactoryAbstract { } As workaround I make classes like: class oop { // lower character on purpose, for this is not a normal class final public const isSaved = 'isSaved'; final public const Save = 'oSave'; final private function __construct() {} } So the extending class can be: This is recognized by the editor and gives the developer some clues. #[UseClass(oop::Save, ImageSave::class)] #[ResetValue(oop::isSaved, default: true)] class ImageSaveFactory extends SaveFactoryAbstract { } But this is really annoying..... It would be much better if we could do something like: #[UseClass(static::$oSave::name, ImageSave::class)] // 'static::' can be used, since the attribute belong to the scope of this class #[ResetValue(static::$isSaved::name, default: true)] class ImageSaveFactory extends SaveFactoryAbstract { } This could also extend possibilities with/for variable variables.... Like: $this->myProp::name myClass::$staticProp::name A potential difficulty is: how to access normal properties/methods.... Maybe just as if they are static? Like parent::normalMethod() is working.... A normal property or method cannot have the same name as its static partner (sadly) so internally I hope it is not a problem. outside scope: myClass::$staticProperty::name myClass::$normalProperty::name myClass::normalMethod::name inside scope: static::$normalProperty::name self::$normalProperty::name // I do not know if 'self::' adds anything for this purpose, except for private properties/methods maybe inside class/object: $this->normalProperty::name $this->normalMethod::name $this::$staticProperty::name I hope you like the idea! Greetz, Lydia

Claude Pache

3 years ago
> Le 12 mai 2023 à 19:29, Lydia de Jongh <flexjoly@gmail.com> a écrit : > > Hi, > > Lately I made a small object initializer/builder with php Attributes. > > 'Directly' accessing properties and methods of the class as a parameter in > an Attribute is not really possible. > You can do that for a class with: \path\to\MyClass::class, but for > properties or methods you have to use strings, without recognition in > editors. > > It would be so nice if more items in php could be accessed with a magic > constant as you can do with ::class. > With magic constant an editor could recognize it and it limits typos etc. > and it provides the developer with a list of the properties/methods in > scope. > > At the moment I implemented a kind of workaround by providing simple > classes with the property names in class constants. > Or add an extra property to a class with a property name that can be used > in an attribute. > > I will try to explain with examples of my code. > > abstract class SaveFactoryAbstract { > use ObjectBuilderTrait; > > #[ResetValue] > protected bool $isSaved = false; > > #[InitObject] // tells the builder to initialize this property with the > latest specs provided by (other) attributes > #[ResetObject] > protected ?SaveInterface $oSave = null; > > public function __construct(){ > $this->buildMe(); // provided by the trait > } > } > > > This is straightforward. Until you extend this class and want to set the > class for $oSave. > The other developer does not know which properties he can declare with an > attribute.... > > #[UseClass('oSave', ImageSave::class)] > #[ResetValue('isSaved', default: true)] > class ImageSaveFactory extends SaveFactoryAbstract { } > > > As workaround I make classes like: > > class oop { // lower character on purpose, for this is not a normal class > > final public const isSaved = 'isSaved'; > > final public const Save = 'oSave'; > final private function __construct() {} > } > > So the extending class can be: > This is recognized by the editor and gives the developer some clues. > #[UseClass(oop::Save, ImageSave::class)] > #[ResetValue(oop::isSaved, default: true)] > class ImageSaveFactory extends SaveFactoryAbstract { } > > But this is really annoying..... > > > It would be much better if we could do something like: > #[UseClass(static::$oSave::name, ImageSave::class)] // 'static::' can be > used, since the attribute belong to the scope of this class > #[ResetValue(static::$isSaved::name, default: true)] > class ImageSaveFactory extends SaveFactoryAbstract { > } > > This could also extend possibilities with/for variable variables.... > Like: > $this->myProp::name > myClass::$staticProp::name > > > A potential difficulty is: how to access normal properties/methods.... > Maybe just as if they are static? > Like parent::normalMethod() is working.... > A normal property or method cannot have the same name as its static partner > (sadly) so internally I hope it is not a problem. > > outside scope: > myClass::$staticProperty::name > myClass::$normalProperty::name > myClass::normalMethod::name > > inside scope: > static::$normalProperty::name > self::$normalProperty::name // I do not know if 'self::' adds anything for > this purpose, except for private properties/methods maybe > > inside class/object: > $this->normalProperty::name > $this->normalMethod::name > $this::$staticProperty::name > I hope you like the idea! Greetz, Lydia
Hi, That looks like the `nameof` operator proposed a few days ago? https://externals.io/message/120173 https://externals.io/message/120173 —Claude