register_shutdown_function() not supports private methods

php.internals

David Rodrigues

6 years ago
Hi internals, I am using the register_shutdown_function() inside a class, and then I have created a private method to be called during shutdown. I have noted that if the method is public it works, but private does not. register_shutdown_function([ self::class, 'privateMethod' ]); // FAIL Warning: (Registered shutdown functions) Unable to call MyClass::privateMethod() - function does not exist in Unknown on line 0 In contrast, spl_autoload_register() will works independent if it is private or public. spl_autoload_register([ self::class, 'privateMethod' ]); // OK Example code: https://3v4l.org/lClJQ This case is applicable independent if method is static or not. My real case is that I am initializing a static method that will register some shutdowns events (that are static methods too). This shutdown function should be private, to avoid execution at a public scope. As workaround I am keeping it as public. So, there are some reason to it do not works like spl does?
-- David Rodrigues

Claude Pache

6 years ago
> Le 28 nov. 2019 à 00:33, David Rodrigues <david.proweb@gmail.com> a écrit : > > My real case is that I am initializing a static method that will register > some shutdowns events (that are static methods too). This shutdown function > should be private, to avoid execution at a public scope. As workaround I am > keeping it as public.
Another workaround is to use a closure: register_shutdown_function(function () { self::privateMethod(); }); —Claude

Dan Ackroyd

6 years ago
On Wed, 27 Nov 2019 at 23:33, David Rodrigues <david.proweb@gmail.com> wrote:
> > Hi internals, > > I am using the register_shutdown_function() inside a class, and then I have > created a private method to be called during shutdown. I have noted that if > the method is public it works, but private does not. > > This shutdown function should be private, > to avoid execution at a public scope.
That is one of the reasons Closure::fromCallable was added: https://www.php.net/manual/en/closure.fromcallable.php So like: register_shutdown_function(Closure::fromCallable([$this, 'leave' ])); Or in your example: https://3v4l.org/MSLA4
> spl_autoload_register([ self::class, 'privateMethod' ]); // OK
That is not OK. It might not give an error, but it's a bug if a private method can be called accidentally, without jumping through the deliberate hoops to work around private methods. Claude Pache wrote:
> Another workaround is to use a closure:
Although that works, using Closure::fromCallable() has the benefits of preserving the parameters and their info. function foo(int $x) { } $fn = Closure::fromCallable('foo'); $reflection = new ReflectionFunction($fn); foreach ($reflection->getParameters() as $param) { echo "Param type is: " . $param->getType(); } // Output is "Param type is: int" cheers Dan Ack

David Rodrigues

6 years ago
Em qui., 28 de nov. de 2019 às 14:13, Dan Ackroyd <Danack@basereality.com> escreveu:
> On Wed, 27 Nov 2019 at 23:33, David Rodrigues <david.proweb@gmail.com> > wrote: > > > > Hi internals, > > > > I am using the register_shutdown_function() inside a class, and then I > have > > created a private method to be called during shutdown. I have noted that > if > > the method is public it works, but private does not. > > > > This shutdown function should be private, > > to avoid execution at a public scope. > > That is one of the reasons Closure::fromCallable was added: > https://www.php.net/manual/en/closure.fromcallable.php > > So like: register_shutdown_function(Closure::fromCallable([$this, 'leave' > ])); > Or in your example: https://3v4l.org/MSLA4
Thanks! It will solve the problem.
> > > > spl_autoload_register([ self::class, 'privateMethod' ]); // OK > > That is not OK. It might not give an error, but it's a bug if a > private method can be called accidentally, without jumping through the > deliberate hoops to work around private methods. >
In that case, it should be deprecated?
> > Claude Pache wrote: > > Another workaround is to use a closure: > > Although that works, using Closure::fromCallable() has the benefits of > preserving the parameters and their info. > > function foo(int $x) { > } > > $fn = Closure::fromCallable('foo'); > $reflection = new ReflectionFunction($fn); > > foreach ($reflection->getParameters() as $param) { > echo "Param type is: " . $param->getType(); > } > // Output is "Param type is: int" > > cheers > Dan > Ack >
-- David Rodrigues