On Tue, Mar 25, 2025, at 6:59 AM, Rob Landers wrote:

>> When I say module scope, I'm referring to something along the lines that 
>> Arnaud and I were exploring a while back.  tldr, "cluster of files with a 
>> common namespace root, which can get loaded together."  It was mostly about 
>> performance, but did offer module-private as well, with some nice potential. 
>>  At the moment it's stalled out on "there's nasty hard edge cases and we're 
>> not sure if it's worth it" concerns.
>> 
>> Concept brain dump here: 
>> https://github.com/Crell/php-rfcs/blob/master/modules/spec-brainstorm.md
>> Code exploration from Arnaud here: 
>> https://github.com/arnaud-lb/php-src/pull/10
>> 
>> Still well short of RFC state, of course, but provided for context.
>
> My email has been broken for a few days, so sorry for the late response...

No worries, I'm about to leave town myself. :-)

>> In this case, I am not seeing what the nesting gets you.  Making Destination 
>> a normal class doesn't hurt anything here, does it?
>
> I wasn't intending to write a definitive example, just to illustrate 
> it. A better example might be a lazy cache, using hooks to notify the 
> outer class it has possibly been updated: 
>
> (note this is using the new syntax, but this syntax is NOT currently 
> reflected in the RFC text, yet)
>
> namespace Caching;
>
> class Cache {
>     private array $items = [];
>     private array $dirty = [];
>
>     public function getItem(string $key): CacheItem {
>         return $this->items[$key] ?? ($this->items[$key] = new 
> CacheItem($this, $key, null));
>     }
>
>     public function saveChanges(): void {
>         foreach ($this->dirty as $key => $value) {
>             echo "Saving $key to persistent storage\n";
>         }
>         $this->dirty = [];
>     }
>
>     private function markDirty(string $key): void {
>         $this->dirty[$key] = $this->items[$key];
>     }
>
>     public class CacheItem {
>         public string|null $value {
>             get {
>                 return $this->_value;
>             }
>             set {
>                $this->_value = $value;
>                $this->cache->markDirty($this->key);
>             }
>         }
>
>         public function __construct(
>             private readonly Cache $cache,
>             public private(set) string $key,
>             private string|null $_value,
>         ) {}
>     }
> }
>
> $cache = new Cache();
> $item1 = $cache->getItem('foo');
> $item1->value = 'bar';
>
> $cache->saveChanges();
>
> This outputs:
>
> Saving foo to persistent storage
>
> This provides for a simple API for outside the Cache class: getItem() 
> and saveChanges(); that's it. For CacheItem's, you only have the props 
> for the key or value, and updating the value marks the item as "dirty".
>
> Currently, if you want this same API, the only way to do this is by:
>
> 1. using reflection,
> 2. using a closure and binding it to the other class's scope,
> 3. providing a listener + observer (more formal version of [2]), or
> 3. iterating over items while saving to find dirty items.
>
> Those choices are not ideal (IMHO).
>
> Reflection feels "hacky" as does using a bound closure. The 
> listener/observer pattern is probably overkill here, unless you already 
> have one lying around (i.e., using symfony/laravel or a related 
> framework), but still might require making some of the "internal" api 
> public. Finally, iterating over all the items to find dirty ones is 
> naive and inefficient.
>
> Hopefully this is a better illustration of what nesting provides?
>
> -- Rob
 
I have a similar if less involved use case in my ordering library, though it 
doesn't need the look-back functionality.

So the use case that nested classes would enable that isn't currently covered 
by "just use separate files and @internal, deal" is around the lesser class 
having private access to the greater class.  Which... I believe fileprivate and 
modules would also address, albeit in a different way, yes?  (Presuming 
fileprivate is available on properties, not just the class itself.)

--Larry Garfield

Reply via email to