php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Request #62455 last chance to work with __call by reference died after removing call-time-&
Submitted: 2012-06-30 19:34 UTC Modified: 2012-07-09 06:46 UTC
Votes:1
Avg. Score:5.0 ± 0.0
Reproduced:1 of 1 (100.0%)
Same Version:1 (100.0%)
Same OS:1 (100.0%)
From: scout4u at ya dot ru Assigned:
Status: Wont fix Package: *General Issues
PHP Version: 5.4.4 OS:
Private report: No CVE-ID: None
Have you experienced this issue?
Rate the importance of this bug to you:

 [2012-06-30 19:34 UTC] scout4u at ya dot ru
Description:
------------
As of PHP 5.4 our content management system became not working without 
possibility to get it to life. Beacause of a bug of removing call-time passing 
by reference.

Explanation:
We have magical loading of «methods» in class as __call() - processed launches:

__call:
	1. seeking existing of function If it exists — then function launches 
and everything is ok.
	2. If there is no such function — it's been loaded from _functions/ 
directory:
So we have auto-loading of functions.
BUT:
	Because of __call don't support (why???) references we could call our 
methods like this:
		$sm->test( &data );

and in test-function we were be able to work BY REFERENCE. In php53 there was 
deprecations — ok, we were turning them off. BUT as of php54 we completely can't 
load virtual function with passing reference nohow... at all.

Ok, we can to preload function if it doesn't exist. But we already can't work by 
reference. So... in case of dealing with realy big array we will have to push 
that into the function and COPY back to the original. This is a huge CPU/memory 
consuming way.

Sooo... If there is no way to pass to the __call Maybe dear authors will revert 
support (even with peprecation-errors) for future times exactly untill __call 
could deal with reference (if that will never start working with reference — 
maybe there should be way to work with __call at least by passing reference in 
call-time maner?)

I belive that __call and its ability of working by reference is a criticaly 
important (maybe not so usual happen) but important thing to leave in PHP still 
working

Test script:
---------------
<?php
	class sm{
		function __call($n, $val){
			if( !function_exists($n) )
				include $n;
			
			return call_user_func($n, $val);  // call_user_func can not use reference either. But everything works when we pass reference call-time.
		}
	}
	$sm = new sm();

	$data = array('prop'=>1);

	function test( &$d ){
		$d['prop'] = 2;
	}

	$sm->test( &$data );  // PHP 5.2, 5.3(deprecated) $data['prop'] === 2

	//!!!!!!!!! as of PHP54 this techinique will stop working and working by reference to __call will not be working in all PHP-version as of 54.
	$sm->test( &$data );  // PHP 5.4(removed) fail


?>


Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2012-07-01 13:08 UTC] cataphract@php.net
-Status: Open +Status: Wont fix
 [2012-07-01 13:08 UTC] cataphract@php.net
You can still pass by reference to __call using call_user_func_array().
 [2012-07-02 14:24 UTC] scout4u at ya dot ru
Well. Code stoped working. It's nice to hear that call_user_func_array can still 
process with references. But without ability to throw link call-time into __call 
we will have only COPY inside of that. And that's a great fail for PHP's 
functionality.

As I described our aproach to magical invocation of method we could work with 
refs even without permision to have ref right in: __call($name, &data)
Now to skip this breaking of functionality in PHP54 we do pre-loading by tech:

$sm->need('function1');
function1();

and then we work by reference this is an ugly way. So magical loading became 
impossible with working by reference. Sooo... maybe you will rise a question to 
revert these changins took place in 53-54? What have motivated author to refuse 
of refs in call-time? I hope that is not: «my granny don't like reference call-
time».
 [2012-07-02 14:29 UTC] scout4u at ya dot ru
Dear catagraph, Sorry I can't catch you. What do you mean? Do you mean that we can 
work in maner I have submited before? But we can't.
 [2012-07-02 14:55 UTC] scout4u at ya dot ru
«You can still pass by reference to __call using call_user_func_array().»

When I try to launch: call_user_func_array(array($this,$n), &$val);
I have:
 Call-time pass-by-reference has been removed in

When I try to launch: function __call($n, &$val)
I have:
 Method smTest::__call() cannot take arguments by reference

What do you mean by «refs are available for call_user_func_array()»?
 [2012-07-08 21:29 UTC] cataphract@php.net
Please see the documentation of call_user_func_array(). Unsurprisingly, it takes its arguments as an array. So you would have:

call_user_func_array(array($this,$n), array(&$val))
 [2012-07-08 21:36 UTC] cataphract@php.net
A full example:

<?php
class A {
function __call($func, $args) {
$args[0] = 3;
}
}
$a = new A;
call_user_func_array([$a, 'foo'], [&$a]);
var_dump($a); //int(3)
 [2012-07-09 06:46 UTC] scout4u at ya dot ru
You offer to work in artifishial maner and not in way:
$sm->letsGo($args);

Now we have decided to use construction:
$sm->need( 'funcName' );
sm_funcName( arg1,arg2 );
instead of
$sm->funcName( arg1,arg2 );

Alas I see nobody would revert references (by some mysterious reson).
 [2012-08-28 13:04 UTC] madsorcerer at gmail dot com
I found, that it is possible to use $sm->test(array('data'=>&$data));
Not so good solution but still...
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Apr 25 12:01:31 2024 UTC