Re: [PHP-DEV] Namespace-private class properties
2020-09-22 14:51 GMT, guilhermebla...@gmail.com : > This should answer your question: > https://github.com/php/php-src/pull/947#issuecomment-224912697 > Yes, indeed. "The reason comes due to how namespaces are implemented in the language, where they only exist at compile time." Pity. > On Tue, Sep 22, 2020 at 7:38 AM Olle Härstedt > wrote: >> >> 2020-09-21 21:50 GMT, Rowan Tommins : >> > On 21/09/2020 17:13, Michael Morris wrote: >> >> Next thing to consider - we have the problem of having already used >> >> the >> >> protected keyword in PHP, and honestly I prefer PHP's interpretation >> >> of >> >> the >> >> word. >> > >> > >> > I think it's actually Java that's the outlier here: PHP's meaning of >> > "protected" corresponds directly to C++, and to name a few I came upon >> > in a quick search it's also used that way by Kotlin [1], Scala [2], C# >> > [3] and Oxygene [4] - all of which use other ways to signal package >> > visibility: >> > >> > - Kotlin has a fourth visibility, "internal", meaning "public within >> > this module" >> > - Scala has an interesting syntax where you can modify the visibility >> > with the name of a package, as in "private[SomePackage]" >> > - C# adds *three* extra visibility modes: "internal", "internal >> > protected", and "private protected" >> > - Oxygene (a language I know next to nothing about) apparently has no >> > fewer than TEN modes, including both "assembly or protected" and >> > "assembly and protected" >> > >> > >> > All of which I think shows two things: firstly, that there are lots of >> > different ways to express this concept; and secondly, that there are a >> > lot of subtle combinations that might be useful. >> > >> > The C# list is particularly confusing, presumably because it's evolved >> > without a coherent plan. If I'm understanding correctly, C#'s "private >> > protected" corresponds to Oxygene's much clearer "assembly and >> > protected", while "protected internal" corresponds to "assembly or >> > protected". Considering those combinations up front might be sensible, >> > even if they're not implemented at once. >> > >> > >> > If we're considering using namespaces rather than a new package concept >> > for this, we potentially have a third dimension: is it private to _this >> > exact namespace_, or any "child" namespace starting with the same >> > prefix? Maybe something like Scala's modifier syntax might be more >> > useful, for instance: >> > >> > namespace Acme\Frobulator\Helpers\File; >> > class FileWidget { >> > private[namespace] $foo; // accessible specifically in the >> > "Acme\Frobulator\Helpers\File" namespace >> > private[Acme\Frobulator\Helpers\File\*] $bar; // accessible in >> > this >> > namespace, and all sub-namespaces >> > private[Acme\Frobulator\*] $baz; // accessible in >> > "Acme\Frobulator" >> > and all its sub-namespaces >> > } >> > >> > >> > [1] https://kotlinlang.org/docs/reference/visibility-modifiers.html >> > [2] https://www.tutorialspoint.com/scala/scala_access_modifiers.htm >> > [3] >> > https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/access-modifiers >> > [4] >> > https://docs.elementscompiler.com/Oxygene/Members/VisibilityLevels/structs/access-modifiers >> > >> > >> > Regards, >> > >> > -- >> > Rowan Tommins (né Collins) >> > [IMSoP] >> > >> > -- >> > PHP Internals - PHP Runtime Development Mailing List >> > To unsubscribe, visit: https://www.php.net/unsub.php >> > >> > >> >> All good ideas, but I still don't know if PHP is aware of current >> namespace at all time? Anyone has this knowledge? It's a precondition >> to check namespace access. >> >> Olle >> >> -- >> PHP Internals - PHP Runtime Development Mailing List >> To unsubscribe, visit: https://www.php.net/unsub.php >> > > > -- > Guilherme Blanco > SVP Technology at Statflo Inc. > Mobile: +1 647 232 5599 > -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: https://www.php.net/unsub.php
Re: [PHP-DEV] Namespace-private class properties
This should answer your question: https://github.com/php/php-src/pull/947#issuecomment-224912697 On Tue, Sep 22, 2020 at 7:38 AM Olle Härstedt wrote: > > 2020-09-21 21:50 GMT, Rowan Tommins : > > On 21/09/2020 17:13, Michael Morris wrote: > >> Next thing to consider - we have the problem of having already used the > >> protected keyword in PHP, and honestly I prefer PHP's interpretation of > >> the > >> word. > > > > > > I think it's actually Java that's the outlier here: PHP's meaning of > > "protected" corresponds directly to C++, and to name a few I came upon > > in a quick search it's also used that way by Kotlin [1], Scala [2], C# > > [3] and Oxygene [4] - all of which use other ways to signal package > > visibility: > > > > - Kotlin has a fourth visibility, "internal", meaning "public within > > this module" > > - Scala has an interesting syntax where you can modify the visibility > > with the name of a package, as in "private[SomePackage]" > > - C# adds *three* extra visibility modes: "internal", "internal > > protected", and "private protected" > > - Oxygene (a language I know next to nothing about) apparently has no > > fewer than TEN modes, including both "assembly or protected" and > > "assembly and protected" > > > > > > All of which I think shows two things: firstly, that there are lots of > > different ways to express this concept; and secondly, that there are a > > lot of subtle combinations that might be useful. > > > > The C# list is particularly confusing, presumably because it's evolved > > without a coherent plan. If I'm understanding correctly, C#'s "private > > protected" corresponds to Oxygene's much clearer "assembly and > > protected", while "protected internal" corresponds to "assembly or > > protected". Considering those combinations up front might be sensible, > > even if they're not implemented at once. > > > > > > If we're considering using namespaces rather than a new package concept > > for this, we potentially have a third dimension: is it private to _this > > exact namespace_, or any "child" namespace starting with the same > > prefix? Maybe something like Scala's modifier syntax might be more > > useful, for instance: > > > > namespace Acme\Frobulator\Helpers\File; > > class FileWidget { > > private[namespace] $foo; // accessible specifically in the > > "Acme\Frobulator\Helpers\File" namespace > > private[Acme\Frobulator\Helpers\File\*] $bar; // accessible in this > > namespace, and all sub-namespaces > > private[Acme\Frobulator\*] $baz; // accessible in "Acme\Frobulator" > > and all its sub-namespaces > > } > > > > > > [1] https://kotlinlang.org/docs/reference/visibility-modifiers.html > > [2] https://www.tutorialspoint.com/scala/scala_access_modifiers.htm > > [3] > > https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/access-modifiers > > [4] > > https://docs.elementscompiler.com/Oxygene/Members/VisibilityLevels/structs/access-modifiers > > > > > > Regards, > > > > -- > > Rowan Tommins (né Collins) > > [IMSoP] > > > > -- > > PHP Internals - PHP Runtime Development Mailing List > > To unsubscribe, visit: https://www.php.net/unsub.php > > > > > > All good ideas, but I still don't know if PHP is aware of current > namespace at all time? Anyone has this knowledge? It's a precondition > to check namespace access. > > Olle > > -- > PHP Internals - PHP Runtime Development Mailing List > To unsubscribe, visit: https://www.php.net/unsub.php > -- Guilherme Blanco SVP Technology at Statflo Inc. Mobile: +1 647 232 5599 -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: https://www.php.net/unsub.php
Re: [PHP-DEV] Namespace-private class properties
2020-09-21 21:50 GMT, Rowan Tommins : > On 21/09/2020 17:13, Michael Morris wrote: >> Next thing to consider - we have the problem of having already used the >> protected keyword in PHP, and honestly I prefer PHP's interpretation of >> the >> word. > > > I think it's actually Java that's the outlier here: PHP's meaning of > "protected" corresponds directly to C++, and to name a few I came upon > in a quick search it's also used that way by Kotlin [1], Scala [2], C# > [3] and Oxygene [4] - all of which use other ways to signal package > visibility: > > - Kotlin has a fourth visibility, "internal", meaning "public within > this module" > - Scala has an interesting syntax where you can modify the visibility > with the name of a package, as in "private[SomePackage]" > - C# adds *three* extra visibility modes: "internal", "internal > protected", and "private protected" > - Oxygene (a language I know next to nothing about) apparently has no > fewer than TEN modes, including both "assembly or protected" and > "assembly and protected" > > > All of which I think shows two things: firstly, that there are lots of > different ways to express this concept; and secondly, that there are a > lot of subtle combinations that might be useful. > > The C# list is particularly confusing, presumably because it's evolved > without a coherent plan. If I'm understanding correctly, C#'s "private > protected" corresponds to Oxygene's much clearer "assembly and > protected", while "protected internal" corresponds to "assembly or > protected". Considering those combinations up front might be sensible, > even if they're not implemented at once. > > > If we're considering using namespaces rather than a new package concept > for this, we potentially have a third dimension: is it private to _this > exact namespace_, or any "child" namespace starting with the same > prefix? Maybe something like Scala's modifier syntax might be more > useful, for instance: > > namespace Acme\Frobulator\Helpers\File; > class FileWidget { > private[namespace] $foo; // accessible specifically in the > "Acme\Frobulator\Helpers\File" namespace > private[Acme\Frobulator\Helpers\File\*] $bar; // accessible in this > namespace, and all sub-namespaces > private[Acme\Frobulator\*] $baz; // accessible in "Acme\Frobulator" > and all its sub-namespaces > } > > > [1] https://kotlinlang.org/docs/reference/visibility-modifiers.html > [2] https://www.tutorialspoint.com/scala/scala_access_modifiers.htm > [3] > https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/access-modifiers > [4] > https://docs.elementscompiler.com/Oxygene/Members/VisibilityLevels/structs/access-modifiers > > > Regards, > > -- > Rowan Tommins (né Collins) > [IMSoP] > > -- > PHP Internals - PHP Runtime Development Mailing List > To unsubscribe, visit: https://www.php.net/unsub.php > > All good ideas, but I still don't know if PHP is aware of current namespace at all time? Anyone has this knowledge? It's a precondition to check namespace access. Olle -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: https://www.php.net/unsub.php
Re: [PHP-DEV] Namespace-private class properties
On 21/09/2020 17:13, Michael Morris wrote: Next thing to consider - we have the problem of having already used the protected keyword in PHP, and honestly I prefer PHP's interpretation of the word. I think it's actually Java that's the outlier here: PHP's meaning of "protected" corresponds directly to C++, and to name a few I came upon in a quick search it's also used that way by Kotlin [1], Scala [2], C# [3] and Oxygene [4] - all of which use other ways to signal package visibility: - Kotlin has a fourth visibility, "internal", meaning "public within this module" - Scala has an interesting syntax where you can modify the visibility with the name of a package, as in "private[SomePackage]" - C# adds *three* extra visibility modes: "internal", "internal protected", and "private protected" - Oxygene (a language I know next to nothing about) apparently has no fewer than TEN modes, including both "assembly or protected" and "assembly and protected" All of which I think shows two things: firstly, that there are lots of different ways to express this concept; and secondly, that there are a lot of subtle combinations that might be useful. The C# list is particularly confusing, presumably because it's evolved without a coherent plan. If I'm understanding correctly, C#'s "private protected" corresponds to Oxygene's much clearer "assembly and protected", while "protected internal" corresponds to "assembly or protected". Considering those combinations up front might be sensible, even if they're not implemented at once. If we're considering using namespaces rather than a new package concept for this, we potentially have a third dimension: is it private to _this exact namespace_, or any "child" namespace starting with the same prefix? Maybe something like Scala's modifier syntax might be more useful, for instance: namespace Acme\Frobulator\Helpers\File; class FileWidget { private[namespace] $foo; // accessible specifically in the "Acme\Frobulator\Helpers\File" namespace private[Acme\Frobulator\Helpers\File\*] $bar; // accessible in this namespace, and all sub-namespaces private[Acme\Frobulator\*] $baz; // accessible in "Acme\Frobulator" and all its sub-namespaces } [1] https://kotlinlang.org/docs/reference/visibility-modifiers.html [2] https://www.tutorialspoint.com/scala/scala_access_modifiers.htm [3] https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/access-modifiers [4] https://docs.elementscompiler.com/Oxygene/Members/VisibilityLevels/structs/access-modifiers Regards, -- Rowan Tommins (né Collins) [IMSoP] -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: https://www.php.net/unsub.php
Re: [PHP-DEV] Namespace-private class properties
2020-09-21 16:13 GMT, Michael Morris : > This sort of thing would be useful. Drupal and Symfony both mark methods in > their libraries that aren't supposed to be used externally, but people do > anyway and then they get mad at the framework developers when they decide > to rearrange what are supposed to be internal methods. > > I wrote a userland assertion to enforce just this sort of thing - enforcing > Java's notion of protected on methods otherwise marked as public. It worked > by looking up the caller in the debug_backtrace and checking to see if the > namespaces matched. To keep the impact of this check minimal I used > assert() for the check so that it wouldn't bog down production (where, > presumably, no new code would be written). > > Now, the above worked, but you could hack in by lying about your namespace > in your file declaration. Since, at the end of the day, PHP's notion of > namespace is entirely a string replace with no other enforcement there's no > way I can see of changing this short of fundamentally changing how PHP > handles namespaces. But I wonder if that should be bothered with since > someone would have to go considerably out of their way to make a call to a > method they weren't supposed to, and they only have themselves to blame if > this sort of solution becomes unstable. > > Next thing to consider - we have the problem of having already used the > protected keyword in PHP, and honestly I prefer PHP's interpretation of the > word. However, PHP doesn't have class scope at this time, so one > possibility is to allow class scope to set a default scope of the unscoped > methods and members of the class. So... > > public class A { > function foo () {} // Callable from anywhere. > } > > protected class B { > function foo () {} // Callable only from current namespace, or any child > namespace. > public function moo() {} // Callable anywhere. In effect the method > specific scope overrides class scope. > } > > private class C { > function foo () {} // Callable only from the same namespace, no children > can access. This includes a extending child function from another namespace > protected function moo () {} // Callable from any child class regardless > of that child's namespace. > } > > That could work. Feel free to poke holes in this - I'm sure I've missed > something. This syntax is already used for the PR about namespace encapsulation. Also, I think visibility always should be explicit. Olle -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: https://www.php.net/unsub.php
Re: [PHP-DEV] Namespace-private class properties
This sort of thing would be useful. Drupal and Symfony both mark methods in their libraries that aren't supposed to be used externally, but people do anyway and then they get mad at the framework developers when they decide to rearrange what are supposed to be internal methods. I wrote a userland assertion to enforce just this sort of thing - enforcing Java's notion of protected on methods otherwise marked as public. It worked by looking up the caller in the debug_backtrace and checking to see if the namespaces matched. To keep the impact of this check minimal I used assert() for the check so that it wouldn't bog down production (where, presumably, no new code would be written). Now, the above worked, but you could hack in by lying about your namespace in your file declaration. Since, at the end of the day, PHP's notion of namespace is entirely a string replace with no other enforcement there's no way I can see of changing this short of fundamentally changing how PHP handles namespaces. But I wonder if that should be bothered with since someone would have to go considerably out of their way to make a call to a method they weren't supposed to, and they only have themselves to blame if this sort of solution becomes unstable. Next thing to consider - we have the problem of having already used the protected keyword in PHP, and honestly I prefer PHP's interpretation of the word. However, PHP doesn't have class scope at this time, so one possibility is to allow class scope to set a default scope of the unscoped methods and members of the class. So... public class A { function foo () {} // Callable from anywhere. } protected class B { function foo () {} // Callable only from current namespace, or any child namespace. public function moo() {} // Callable anywhere. In effect the method specific scope overrides class scope. } private class C { function foo () {} // Callable only from the same namespace, no children can access. This includes a extending child function from another namespace protected function moo () {} // Callable from any child class regardless of that child's namespace. } That could work. Feel free to poke holes in this - I'm sure I've missed something. On Sat, Sep 19, 2020 at 7:43 AM Rowan Tommins wrote: > On 17/09/2020 13:28, Olle Härstedt wrote: > > We have public, protected and private. Since PHP has no module system, we > > have no qualifier to mark a class property as "private for this module". > > One solution to this could be to add a new qualifier "internal", to make > > properties public within the current namespace. > > > As well as the implementation details of doing this at run-time (which > is where PHP does all its access checks right now) the mapping of > "namespace" to "module" is not necessarily the most useful one. > > For instance, if you define an "internal" property in a class called > Acme\Frobulator\Handlers\TextFile\Format\CSV, it would be accessible in > other classes in namespace Acme\Frobulator\Handlers\TextFile\Format\ and > possibly also sub-namespaces like > Acme\Frobulator\Handlers\TextFile\Format\Exceptions, but not in other > parts of Acme\Frobulator\Handlers\TextFile or Acme\Frobulator as a whole. > > If Acme\Frobulator was the root of the Composer package, the only way to > make something internal to the package as a whole would be to flatten > everything into that root namespace, like > Acme\Frobulator\Handler_TextFile_Format_CSV > > That leads me to think that if we do want "module"-level features - be > it internal classes, internal properties, or module-level declare() > settings - we need a way for the user to define that separately from the > fully-qualified namespace. > > Regards, > > -- > Rowan Tommins (né Collins) > [IMSoP] > > -- > PHP Internals - PHP Runtime Development Mailing List > To unsubscribe, visit: https://www.php.net/unsub.php > >
Re: [PHP-DEV] Namespace-private class properties
On 17/09/2020 13:28, Olle Härstedt wrote: We have public, protected and private. Since PHP has no module system, we have no qualifier to mark a class property as "private for this module". One solution to this could be to add a new qualifier "internal", to make properties public within the current namespace. As well as the implementation details of doing this at run-time (which is where PHP does all its access checks right now) the mapping of "namespace" to "module" is not necessarily the most useful one. For instance, if you define an "internal" property in a class called Acme\Frobulator\Handlers\TextFile\Format\CSV, it would be accessible in other classes in namespace Acme\Frobulator\Handlers\TextFile\Format\ and possibly also sub-namespaces like Acme\Frobulator\Handlers\TextFile\Format\Exceptions, but not in other parts of Acme\Frobulator\Handlers\TextFile or Acme\Frobulator as a whole. If Acme\Frobulator was the root of the Composer package, the only way to make something internal to the package as a whole would be to flatten everything into that root namespace, like Acme\Frobulator\Handler_TextFile_Format_CSV That leads me to think that if we do want "module"-level features - be it internal classes, internal properties, or module-level declare() settings - we need a way for the user to define that separately from the fully-qualified namespace. Regards, -- Rowan Tommins (né Collins) [IMSoP] -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: https://www.php.net/unsub.php
Re: [PHP-DEV] Namespace-private class properties
On Sat, 19 Sep 2020, 09:20 Olle Härstedt, wrote: > > On Fri, 18 Sep 2020, 00:13 Mike Schinkel, wrote: > >> >> >> > On Sep 17, 2020, at 8:28 AM, Olle Härstedt >> wrote: >> > >> > (NB: This idea is NOT about namespace visibility for classes, >> interfaces or >> > traits (already discussed here: >> https://wiki.php.net/rfc/namespace-visibility). >> > It's about adding a *new* visibility qualifier, call it "internal", to >> > make properties >> > private inside a namespace. The purpose is to make composition less >> > fragile by not >> > exposing more than necessary.) >> > >> > (NB: This feature exists in Swift, described here: >> > https://docs.swift.org/swift-book/LanguageGuide/AccessControl.html) >> > >> > We have public, protected and private. Since PHP has no module system, >> we >> > have no qualifier to mark a class property as "private for this module". >> > One solution to this could be to add a new qualifier "internal", to make >> > properties public within the current namespace. >> > >> > Use-cases: >> > >> > * Split data and behaviour into different files and classes >> > * Safely skip getters and setters without risk of properties being >> abused >> > by client code >> >> +1 >> >> This might be able to address a use-case I have wanted for a while, which >> is to have traits with properties (and methods) that are not accessible >> with the class that uses the trait. >> >> So if a trait is in a different namespace than the using class, the using >> class would not be able to access these "internal" properties. >> >> Or at least I think that could work? >> >> -Mike >> > > True, the properties/methods of the trait could be made internal, while > exposing the trait itself (and at least one method, to make it usable). > > The question is if PHP tracks the current namespace it's in on each line. > It needs to be known at all times for such an access level to work. > > Olle > Just discovered that this feature already exists in Psalm, @psalm-internal. They are streets ahead. :) Olle >
Re: [PHP-DEV] Namespace-private class properties
On Fri, 18 Sep 2020, 00:13 Mike Schinkel, wrote: > > > > On Sep 17, 2020, at 8:28 AM, Olle Härstedt > wrote: > > > > (NB: This idea is NOT about namespace visibility for classes, interfaces > or > > traits (already discussed here: > https://wiki.php.net/rfc/namespace-visibility). > > It's about adding a *new* visibility qualifier, call it "internal", to > > make properties > > private inside a namespace. The purpose is to make composition less > > fragile by not > > exposing more than necessary.) > > > > (NB: This feature exists in Swift, described here: > > https://docs.swift.org/swift-book/LanguageGuide/AccessControl.html) > > > > We have public, protected and private. Since PHP has no module system, we > > have no qualifier to mark a class property as "private for this module". > > One solution to this could be to add a new qualifier "internal", to make > > properties public within the current namespace. > > > > Use-cases: > > > > * Split data and behaviour into different files and classes > > * Safely skip getters and setters without risk of properties being abused > > by client code > > +1 > > This might be able to address a use-case I have wanted for a while, which > is to have traits with properties (and methods) that are not accessible > with the class that uses the trait. > > So if a trait is in a different namespace than the using class, the using > class would not be able to access these "internal" properties. > > Or at least I think that could work? > > -Mike > True, the properties/methods of the trait could be made internal, while exposing the trait itself (and at least one method, to make it usable). The question is if PHP tracks the current namespace it's in on each line. It needs to be known at all times for such an access level to work. Olle
Re: [PHP-DEV] Namespace-private class properties
> On Sep 17, 2020, at 8:28 AM, Olle Härstedt wrote: > > (NB: This idea is NOT about namespace visibility for classes, interfaces or > traits (already discussed here: > https://wiki.php.net/rfc/namespace-visibility). > It's about adding a *new* visibility qualifier, call it "internal", to > make properties > private inside a namespace. The purpose is to make composition less > fragile by not > exposing more than necessary.) > > (NB: This feature exists in Swift, described here: > https://docs.swift.org/swift-book/LanguageGuide/AccessControl.html) > > We have public, protected and private. Since PHP has no module system, we > have no qualifier to mark a class property as "private for this module". > One solution to this could be to add a new qualifier "internal", to make > properties public within the current namespace. > > Use-cases: > > * Split data and behaviour into different files and classes > * Safely skip getters and setters without risk of properties being abused > by client code +1 This might be able to address a use-case I have wanted for a while, which is to have traits with properties (and methods) that are not accessible with the class that uses the trait. So if a trait is in a different namespace than the using class, the using class would not be able to access these "internal" properties. Or at least I think that could work? -Mike > > Tiny example: > > ``` > namespace App\User; > class User { > internal $username; > internal $password; > } > > namespace App\User\Services; > class ProcessUser { > // Child namespace has access to internal properties, > // but App\ has not. > } > ``` > > Possible? > > Olle > -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: https://www.php.net/unsub.php