I have the following code
function MaximArray($arr)
{
$GLOBALS['maxim'] = 0;
array_walk_recursive($arr,create_function('$item,$key','if($item > $GLOBALS["maxim"]) $GLOBALS["maxim"] = $item;'));
return $GLOBALS['maxim'];
}
Why does this function work with $GLOBALS['maxim'] but if I declare a variable as global inside function and use it, doesn't work? I learned that $GLOBALS['a'] and global $a are equal.
Example with global variable $maxim:
$maxim=0;
function MaximArray($arr)
{
global $maxim;
array_walk_recursive($arr,create_function('$item,$key','if($item > $maxim) $maxim = $item;'));
return $maxim;
}
Assuming you're on PHP 5.3, you can use a proper inline function rather than the clunky old create_function() syntax.
array_walk_recursive($arr,function($item,$key) use $maxim {if($item > $maxim) $maxim = $item;}));
Note the use $maxim bit -- this syntax allows you to pass a local variable into an inline function. This is not possible using create_function().
As I said, this is for PHP 5.3 and later. If you're on PHP 5.2 or earlier then the above syntax won't be available to you. However since PHP 5.2 was declared end-of-life over three years ago, if that's the case then you should be urgently considering an upgrade.
Related
In PHP 5, is there any way to dynamically (i.e. via the use of call_user_func or ReflectionFunction::invoke()) call a function that returns by reference, and store the reference it returned, without raising a notice/warning/error, and without using error control operators (#)?
I am NOT referring to passing by reference. Returning by reference is a completely different topic.
To illustrate:
$a = (object) array();
$callback = function & () use (&$a) {
return $a;
};
// no problems, and sure enough $b === $a
$b = &$callback();
// emits "Strict Standards: Only variables should be assigned by reference"
// but still $b === $a anyway
$b = &call_user_func($callback);
It appears that there is no way to make call_user_func() return a reference in PHP 5.x. However, depending on the PHP version, there may be some workarounds.
One approach seems to work:
$b = &$callback();
As we discussed in the comments, this presents a problem when we have to call $callback() with a configured/variable number of arguments. If we have PHP 5.6, there is a workaround, with the ... (splat) operator:
$b = &$callback(...$argArray);
This will unpack the arguments contained in $argArray sequentially, and pass them as function arguments to $callback().
Unfortunately, this will only work in PHP 5.6+.
Before PHP 5.6, you're probably stuck using something like this (untested):
$argsToEval = array_map(function($key) {
return '$argArray[' . $key . ']';
}, array_keys($argArray));
$code = sprintf('$b = &$callback(%s);', implode(', ', $argsToEval);
eval($code);
We can both agree that this is messy. But, perhaps, different syntax could be used depending on the PHP version, as you indicated that you need to support 5.3+. I would also encourage you to drop 5.3 and 5.4 support, as 5.3 hit End of Life in March 2013, and 5.4 hit End of Life in September 2015. 5.5 will hit End of Life in June of this year. But, I do realize the practicalities of some users being able to upgrade, even once EoL has passed.
I've been programming for quite a while with PHP. Recently I decided to try and use a framework. I happened to pick Symfony2. One of the first thing I noticed was that I've never encountered any reference operator(&). I used them frequently in my previous projects.
I've found this on php.net/manual/...
Note that in PHP5 you generally don't need the reference operator -- at all -- when dealing with class objects, because PHP5 implements objects using Instances (which are more like C pointers than PHP's references system).
Are references uncommon in frameworks, or perhaps in general in PHP5?
Edit
I know what references do and how they work. I wonder why the Symfony2 examples on the site do not use reference operators anywhere.
In fact if you use passing object as argument to function, PHP won't create copy of the object but simple points to the same place in memory where this object exists. So there is no need to use reference as long as you don't want to do some complex stuff (point to another object/variable in memory).
You should look at Object and references in PHP manual.
You can also consider the following code:
<?php
class A {
public $x= 20;
}
$a = new A();
echo $a->x."<br />";
change($a);
echo $a->x."<br />";
changeRef($a);
echo $a->x."<br />"; // you get notice in this line. $a is no longer A object
echo $a."<br />";
function change(A $b) {
$b->x = 10;
$b = 15;
}
function changeRef(A &$b) {
$b->x = 10;
$b = 15;
}
I've created 2 function change (without reference) and changeRef (with reference).
As you see when using change function even if we don't use reference, when using property assignment inside function also property of variable $a has been changed - it's because $a and $b pointed to the same place in memory. However if inside the same function I set any other object (in this case simple int) to variable $b, nothing more happened. Simple $b is now pointing to some other place in memory where 15 was placed but $a is pointing to the same place in memory as earlier.
However in send function (with reference) after assigning $b value 15 it means that $a has been also assigned the same value ($b is reference to $a) so after running this function when you try to display property of $a it's impossible no more (warning raised) because $a is no longer A object but simple int with 15 value.
I hope this clears you this issue a bit and now you understand why references don't need to be used very often when using objects.
EDIT
As you mentioned using references for arrays, PHP uses copy-on-write mechanism. So if you pass array to function or other variable as long as you don't modify it no copy will be created even if passing arrays as argument.
Consider the following code:
$arr = [1,2,3];
show($arr);
function show($a) {
foreach ($a as $item) {
echo $item;
}
}
in above case no copy of $arr will be created so there is no need to use reference in this case. So unswerving your question if you don't have to modify the array you don't need to use reference. Probably that's why Symfony doesn't use references in that cases.
In addition references make code less clear because if you don't go to function declaration you won't know that it could modify your data. So probably that's the extra reason they are not so commonly used.
Passing by Reference
Note: There is no reference sign on a function call - only on function definitions. Function definitions alone are enough to correctly pass the argument by reference. As of PHP 5.3.0, you will get a warning saying that "call-time pass-by-reference" is deprecated when you use & in foo(&$a);. And as of PHP 5.4.0, call-time pass-by-reference was removed, so using it will raise a fatal error.
I'm looking for the kind to access at the value of an array directly from the object's method.
For example :
With this syntax, no problem :
$myArray = $myObject->getArray();
print_r($myArray[0])
But to reduce the number of line in source code, how to get the element directly with the method ?
I do that, but it's not correct :
$myArray = $myObject->getArray()[0];
The following is only available for PHP 5.4 and supposedly higher.
$myArray = $myObject->getArray()[0];
Unfortunately there is no quicker way below PHP 5.4.
See #deceze's answer for a good alternative.
For PHP 5.3-:
$myArray = current($myObject->getArray());
or
list($myArray) = $myObject->getArray();
If you are on php 5.4 (which support array dereferencing) you can do the second option:
$myArray = $myObject->getArray()[0];
If you are on PHP < 5.4 you can "fix" it in the class (of which the object is a instance):
class Foo
{
public function getArray()
{
return $this->theArray;
}
public function getFirstItem()
{
return $this->theArray[0];
}
}
$myObject = new Foo();
print_r($myObject->getFirstItem());
But to reduce the number of line in source code, how to get the element directly with the method ?
Although it is possible to achieve this in PHP 5.4 with the syntax you've demonstrated, I have to ask, why would you want that? There are ways of doing it in 5.3 in a one-liner, but I don't see the need to do this. The number of lines is surely less interesting than the readability of the code?
IT IS IMPOSSIBRRUUU.
Serious answer:
sadly it is not possible. You can write a very ugly wrapper like this:
function getValue($arr, $index)
{
return $arr[$index];
}
$myArray = getValue($myObject->getArray(), 0);
But that makes less readable code.
read other answers about php 5.4 Finally!
I have seen the PHP manual. But I don't understand the difference in behaviour between the earlier version and the later versions of PHP. I don't understand this statement:
Because this function depends on the current scope to determine parameter details, it cannot be used as a function parameter in versions prior to 5.3.0. If this value must be passed, the results should be assigned to a variable, and that variable should be passed.
If you wanted to pass the result of one of those functions to another function or a method, in versions of PHP prior to 5.3 you had to first assign the result to a variable.
function some_func() {
$args = func_get_args();
some_other_func($args);
}
This limitation was removed in PHP 5.3 and you can now pass the result directly.
function some_func() {
some_other_func(func_get_args());
}
As to why this limitation existed in the first place, perhaps someone with a more thorough understanding of PHP's internals can give you a more complete answer.
It means that this is invalid in 5.2:
function foo() {
$array = array_map('strtolower', func_get_args());
}
foo('BAR', 'BAZ');
It will abort with a Fatal error:
PHP Fatal error: func_get_args(): Can't be used as a function parameter
However in 5.3, it is valid code.
Is function overloading possible in php.If yes, then how and if not then why?
Thanks in advance.
I have checked the php manual which gives solution to overloading as mail() function can be overloaded by mb_mail() function .
But is this the proper way for overloading
No. Because it has not been implemented. There's a PECL extension that allows you to do this, but it makes your code not portable to environments where this extension is not available.
Don't ask why it has not been implemented.
Since PHP 5.3 you can use namespaces for 'kind of' overloading
namespace MyNamespace;
function mail() {
return \mail();
}
This can only be done internally (through a PHP extension), unless you install the PECL runkit extension, which exposes function overloading functionality to userspace.
However, you probably don't want to use runkit in a production environment, so there's no good way to do this from userspace.
i'm new to php .. so dont know about these extensions mentions above .. but recently i saw a method to overload function in php (sort of) ..
traditional function overloading is not supported in php because you can not have multiple functions with same name in php .. but you can use one single function which can take multiple arguments .. known as Variadic Function (http://en.wikipedia.org/wiki/Variadic_function)
function show()
{
$data = "";
$arr = func_get_args(); //Returns an Array of arguments passed
for($a = 0 ; $a < func_num_args() ; $a++ ) // func_num_args returns number of arguments passed .. you can also use count($arr) here
{
$data .= $arr[$a];
}
echo $data, "<br>";
}
show("Hey","Hii","Hello");
show("How Are You");
here .. i have passed variable arguments to a function and appended each of them in a string ..
ofcourse including a string is not necessary .. you can simply echo $arr array contents inside a loop .. hope that helps .. !!