10

The following pattern used to be possible in PHP:

function foo($arr)
{
    // modify $arr in some way
    return $arr;
}

This could then be called using pass-by-value:

$arr = array(1, 2, 3);
$newarr = foo($arr);

or pass-by-reference:

$arr = array(1, 2, 3);
foo(&$arr);

but "Call-time pass-by-reference has been deprecated". Modifying the function signature:

function foo(&$arr)

will handle the pass-by-reference case, but will break the dual-purpose nature of the original function, since pass-by-value is no longer possible.

Is there any way around this?

3
  • It triggers an E_DEPRECATED, which is just a notice error level. But the feature itself is unaffected. It is not "no longer possible". (And it's still not going to be removed in next years PHP 5.4..) Commented May 26, 2011 at 12:35
  • I meant that pass-by-value when calling a function that's declared as taking its argument by reference is not possible. As you point out, it's still possible to pass by reference even if the function doesn't declare its argument that way, but I always like to think that deprecated stuff should be avoided if possible. Commented May 26, 2011 at 12:41
  • 1
    Yes, that's exactly why it was declared deprecated. It was commonly misused without much thought. And this error message is meant to scare people away from that syntax. Now that you've given it some thought for your actual code, it no longer applies to you. (I would avoid the fugly workarounds over the not-anytime-soon-to-be-removed supported syntax.) Commented May 26, 2011 at 12:44

4 Answers 4

5

I think this is as close as you get:

function foo(&$bar) { ... }

foo($array);                // call by reference
$bar = foo($_tmp = $array); // call by value

Unfortunately it will require some changes to every call.

Sign up to request clarification or add additional context in comments.

2 Comments

That's likely the best alternative here; explicit and legible.
I should note that I wouldn't really recommend writing code that way. e.g., you could simply write $bar = $array; foo($bar); The goal here was just to try to mimic the deprecated syntax as closely as possible. Also, if you go about changing your code, keep in mind that the lines that use pass-by-value will not be generating any warnings, and switching the function around like this will cause it to silently change behavior on those cases. So personally, I would keep using the code as-is, and start looking for better third party libraries in the meantime.
2

The dual-purpose nature was stupid, which is why the behaviour is deprecated. Modify the function signature, as you suggest.

2 Comments

Dual-purpose nature wasn't stupid, it was dangerous because you could modify a variable if you passed it by reference. Now we're forced to explicitly declare whether the variable is being passed by reference or not. It has it's advantages (less careful programmers won't shoot their own leg and PHP can finally pass arguments without copying values) and drawbacks (no dual-purpose so function doing nearly the same thing has to be declared twice).
@Bobby: What @Michael said. :)
1

Sadly, I don't believe there is a way around it.

Just make your function use the reference with &.

Comments

1

A simple workaround is to prepare a wrapper function:

function foo($arr) {
    return foo_ref($arr);
}

function foo_ref(&$arr) {
    ...

Then depending on the current use, either invoke the normal foo() or the foo_ref() if you want the array to be modified in place.


There is also a common array(&$wrap) parameter cheat, but that doesn't seem suitable in your case. A more contemporary workaround would be this tricky trick:

// pass by value
foo($array);

// pass by reference (implicitly due to being an object)
foo($array = new ArrayObject($array));

This allows for similar reference passing to unprepared functions. Personally I would prefer keeping the E_DEPRECATED warning and the intended syntax for this purpose.

1 Comment

Unfortunately ArrayObject cannot be used with array functions so it's not necessarily a drop-in "fix." Otherwise it would probably work.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.