Bug #78440 [Nab]: Array-callables wont work if class has only __call/__callStatic
| From: | 6562680 at gmail dot com | Date: | Wed, 21 Aug 2019 19:00:27 +0000 |
| Subject: | Bug #78440 [Nab]: Array-callables wont work if class has only __call/__callStatic | ||
| References: | 1 | Groups: | php.bugs |
| Request: | Send a blank email to php-bugs+get-222358@lists.php.net to get a copy of this message | ||
Edit report at https://bugs.php.net/bug.php?id=78440&edit=1
ID: 78440
User updated by: 6562680 at gmail dot com
Reported by: 6562680 at gmail dot com
Summary: Array-callables wont work if class has only
__call/__callStatic
Status: Not a bug
Type: Bug
Package: Reflection related
Operating System: Win10
PHP Version: 7.2.21
Block user comment: N
Private report: N
New Comment:
It is not related to some core functions like "is_array" and so on*
Previous Comments:
------------------------------------------------------------------------
[2019-08-21 17:16:11] requinix@php.net
> I thought that's expected behavior with "too many arguments" will happened
PHP allows calling a function with extra arguments. They can be accessed with func_get_arg() and
func_get_args().
------------------------------------------------------------------------
[2019-08-21 17:14:02] 6562680 at gmail dot com
So i got the exception when wrote these topic, because try to wrap callable to closure using
\ReflectionFunction. I thought that's expected behavior with "too many arguments"
will happened
If i got additional info about - i link it here
My bad. sorry me
------------------------------------------------------------------------
[2019-08-21 17:11:26] 6562680 at gmail dot com
<?php
spl_autoload_register(function () {
require 'dynamic.php';
});
Class Proxy
{
public static function __callStatic($method, $arguments)
{
// yes we should use DI or something here
return (new Dynamic)->{ $method }(...$arguments);
}
}
/*
This class will be loaded via spl_autoload_register() and should be declared outside
Class Dynamic
{
public function __construct()
{
// some code to load data outside
}
public function reducer($carry) // ! yes there should be 2 arguments
{
return $carry; // does nothing
}
}
*/
// run #2.1
var_dump(new \ReflectionMethod(Proxy::class, 'reducer')); // expected
// throws
Method not found
// run #2.2
$array = [1,2,3];
array_reduce($array, [ Proxy::class, 'reducer' ], []); // sorry me, works well, i thought
there should be too many arguments exception
// run #2.3
array_reduce($array, function ($carry, $item) {
return Proxy::reducer($carry, $item); // works well, because of dynamic loading, and well ignores
arguments if too many
}, []);
------------------------------------------------------------------------
[2019-08-21 16:45:22] requinix@php.net
Thank you for this bug report. To properly diagnose the problem, we
need a short but complete example script to be able to reproduce
this bug ourselves.
A proper reproducing script starts with <?php and ends with ?>,
is max. 10-20 lines long and does not require any external
resources such as databases, etc. If the script requires a
database to demonstrate the issue, please make sure it creates
all necessary tables, stored procedures etc.
Please avoid embedding huge scripts into the report.
------------------------------------------------------------------------
[2019-08-21 16:40:04] 6562680 at gmail dot com
Description:
------------
I know about 7.4 and array-functions, seems like good solution.
So, currently i found 2 problems with Reflection
1. When you passing callable as string or array, you should be sure that passed arguments count will
be EXACTLY match await arguments count. Maybe as solution, but \Closure::class works well. If you
pass too many arguments, it just ignored. Because of that i should write bind() function that
creates closure from these callable, controls bound arguments with \ReflectionClass
2. When i have few libraries with functions, sometimes i want call function that will be declared
only when first access (because library has a constructor) by passing array inside mapper, filter or
reducer. So i cant do this because library has another module inside (that works only with
dependency injector) - so trying to pass array with that [ ProxyLib::class, 'func' ]
expectedly ends with "method not found exception". Of course - if i use \Closure for that
- it works well because of dynamic loading.
Test script:
---------------
/*
* 1st
*/
array_reduce($array, 'is_array', []); // nvm, just an example
// throws Too many arguments
/*
* 2nd
*/
Class Proxy
{
public static function __callStatic($method, $arguments)
{
// yes we should use DI or something here
return (new Dynamic)->{ $method }(...$arguments);
}
}
Class Dynamic
{
public function __construct() { $this->loadSomeDataOnInit(); }
public function reducer($carry, $item) { return $carry; }
}
array_reduce($array, [ Proxy::class, 'reducer' ], []);
// throws Method not found
array_reduce($array, function ($carry, $item) {
return Proxy::reducer($carry, $item); // works well, because of dynamic loading
}, []);
Expected result:
----------------
1st: ignore if too many, exception if not enough
2st: auto-wrap into closure
------------------------------------------------------------------------
--
Edit this bug report at https://bugs.php.net/bug.php?id=78440&edit=1