php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #78440 Array-callables wont work if class has only __call/__callStatic
Submitted: 2019-08-21 16:40 UTC Modified: 2019-08-21 19:00 UTC
From: 6562680 at gmail dot com Assigned:
Status: Not a bug Package: Reflection related
PHP Version: 7.2.21 OS: Win10
Private report: No CVE-ID: None
 [2019-08-21 16:40 UTC] 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


Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2019-08-21 16:45 UTC] requinix@php.net
-Status: Open +Status: Feedback
 [2019-08-21 16:45 UTC] 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 17:11 UTC] 6562680 at gmail dot com
-Status: Feedback +Status: Open
 [2019-08-21 17:11 UTC] 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 17:14 UTC] 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:16 UTC] requinix@php.net
-Status: Open +Status: Not a bug
 [2019-08-21 17:16 UTC] 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 19:00 UTC] 6562680 at gmail dot com
It is not related to some core functions like "is_array" and so on*
 
PHP Copyright © 2001-2020 The PHP Group
All rights reserved.
Last updated: Thu Apr 09 05:01:23 2020 UTC