|  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #76749 call_user_func / invoke break strict typing
Submitted: 2018-08-15 21:59 UTC Modified: 2018-08-16 09:28 UTC
Avg. Score:5.0 ± 0.0
Reproduced:1 of 1 (100.0%)
Same Version:0 (0.0%)
Same OS:0 (0.0%)
From: j dot vanbeele at gmail dot com Assigned:
Status: Duplicate Package: *General Issues
PHP Version: 7.0.31 OS: Any
Private report: No CVE-ID: None
 [2018-08-15 21:59 UTC] j dot vanbeele at gmail dot com
See below.

Test script:
<?php declare(strict_types=1);

namespace poop; // Commenting this fixes strict typing

// A.php
class A {
	public function MyFunction(string $str) {
		return $str;


// B.php
class B {
	public function __call($func, $args) {
		// Uncommenting this breaks strict typing given namespace
		// return call_user_func_array(array(new A, $func), $args);

		// Uncommenting this breaks strict typing given namespace
		// $ref = new \ReflectionMethod('poop\A', 'MyFunction');
		// return $ref->invokeArgs(new A, $args);
		// Doesn't break strict typing
		return (new A)->$func($args);



// Script.php
var_dump((new B)->MyFunction(1));

Expected result:
The expected result is that none of the cases above should break strict typing.

As a side note, if theres classes were stored in the following way:


then the declare(strict_types=1) should be done in B.php over Script.php since due to __call, B is technically the caller, and not Script.php. 

This is already the case with (new A)->$func($args) and hopefully that behaviour will be reproduced given this bug will be fixed.

P.S - Is there any way I could pass multiple arguments to (new A)->$func() for the timebeing?

Actual result:
Using invoke or call_user_func will make the code resort back to weak typing unless the namespace is commented out.


Add a Patch

Pull Requests

Add a Pull Request


AllCommentsChangesGit/SVN commitsRelated reports
 [2018-08-16 04:38 UTC]
-Status: Open +Status: Feedback
 [2018-08-16 04:38 UTC]
Not sure what you mean by it "fixes" or "breaks" strict typing.

If I keep the namespace, fix B.php to use "new poop\A", and add require()s to Script.php, then I get
> Fatal error: Uncaught TypeError: Argument 1 passed to poop\A::MyFunction() must be of the type string, array
> given, called in ...\B.php on line 14 and defined in ...\A.php:7
which, by the way, is not an issue of strict typing but of the fact that PHP can't coerce an array to a string.

And with call_user_func_array and invokeArgs, the calls work and value is a string.

So that all looks correct.

And yes, you can use argument unpacking:
  return (new A)->$func(...$args);
 [2018-08-16 08:56 UTC] j dot vanbeele at gmail dot com
Sorry, allow me to clarify the issue:

In the code #1, 'A' is already in the `namespace` 'poop' and I'm expecting a `TypeError` because I'm passing an `integer` to a `string` with `strict_types=1`. Instead, it coerces the `integer` to a `string` which is weak typing. #1:

When I change `call_user_func_array` to `invoke`, I'm also expecting a `TypeError` because I'm passing an `integer` to a `string` with `strict_types=1`. Instead, it coerces the `integer` to a `string` which is weak typing. #2:

The only time I'm getting what I expect - a TypeError - is when I use `variable functions`. #3:

Or, when I remove the `namespace`. #4:
 [2018-08-16 09:27 UTC]
-Status: Feedback +Status: Duplicate
 [2018-08-16 09:27 UTC]
Ah, I see.

Take a look at bug #72248.
Also check out to see the difference between the regular/PHP 5.6 and the optimized calls.

The correct behavior is that call_user_func/_array and ReflectionFunction::invoke/Args perform the function calls by themselves (regardless of optimization), like the current behavior without a namespace. Since PHP does not use strict_types for its own calls, yes: the arguments will be coerced without warnings. And no, there is no way to turn it on internally.

What should you do to avoid this problem?

With argument unpacking and PHP 7's syntax improvements, there's not much of a reason to use call_user_func/_array anymore. You can write the function calls inline.
As for reflection... well, it's expensive so you really should be avoiding this if at all possible anyways.
 [2018-08-16 09:28 UTC]
> like the current behavior without a namespace
*with a namespace
 [2018-08-16 10:59 UTC] j dot vanbeele at gmail dot com
I kind of expected that to be the case but wasn't sure if that was intended behaviour. Also, using argument unpacking that way is awesome. I'll probably avoid given functions for given reasons ie performance.

Thank you so much for your time.
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Mon Jul 15 20:01:29 2024 UTC