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 .. !!
Related
I have a couple of libraries that use code similar to the following one.
$args = array_merge(array(&$target, $context), $args);
$result = call_user_func_array($callback, $args);
The code is different in both the cases, but the code I shown is what essentially is done. The $callback function uses the following signature:
function callback(&$target, $context);
Both the libraries document that, and third-party code (call it plug-in, or extension) adopts that function signature, which means none of the extensions defines the callback as, e.g., function my_extension_loader_callback($target, $context).
What confuses me are the following sentence in the documentation for call_user_func_array().
Before PHP 5.4, referenced variables in param_arr are passed to the function by reference, regardless of whether the function expects the respective parameter to be passed by reference. This form of call-time pass by reference does not emit a deprecation notice, but it is nonetheless deprecated, and has been removed in PHP 5.4. Furthermore, this does not apply to internal functions, for which the function signature is honored. Passing by value when the function expects a parameter by reference results in a warning and having call_user_func() return FALSE.
In particular, the highlighted sentence seems to suggest that is not done for functions define in PHP code.
Does using call_user_func_array() in this way work in PHP 5.4?
When using call_user_func_array, passing by value when a function expects a reference is considered an error, in newer versions of PHP.
This was valid PHP code before PHP 5.3.3:
//first param is pass by reference:
my_function(&$strName){
}
//passing by value, not by reference, is now incorrect if passing by reference is expected:
call_user_func_array("my_function", array($strSomething));
//correct usage
call_user_func_array("my_function", array(&$strSomething));
The above pass by value is no longer possible without a warning (my project is also set to throw exceptions on any kind of error (notice, warning, etc).) so I had to fix this.
Solution
I've hit this problem and this is how I solved it (I have a small RPC server, so there is no such thing as referenced values after deserializing params):
//generic utility function for this kind of situations
function &array_make_references(&$arrSomething)
{
$arrAllValuesReferencesToOriginalValues=array();
foreach($arrSomething as $mxKey=>&$mxValue)
$arrAllValuesReferencesToOriginalValues[$mxKey]=&$mxValue;
return $arrAllValuesReferencesToOriginalValues;
}
Although $strSomething is not passed by reference, array_make_references will make it a reference to itself:
call_user_func_array("my_function", array_make_references(array($strSomething)));
I think the PHP guys were thinking of helping people catch incorrectly called functions (a well concealed pitfall), which happens often when going through call_user_func_array.
If call_user_func_array() returns false you have a problem, otherwise everything should be fine.
Parameters aren't passed by reference by default anymore, but you do it explicitly.
The only trouble could be that your reference gets lost during array_merge(), haven't tested that.
I've found this same problem when upgrading to PHP5.4 when there were several sites using call_user_func_array with arguments passed by reference.
The workaround I've made is very simple and consists on replacing the call_user_func_array itself with the full function call using eval(). It's not the most elegant solution but it fits the purpose for me :)
Here's the old code:
call_user_func_array($target, &$arguments);
Which I replace with:
$my_arguments = '';
for ($i=0; $i<count($arguments); $i++) {
if ($i > 0) { $my_arguments.= ", "; }
$my_arguments.= "\$arguments[$i]";
}
$evalthis = " $target ( $my_arguments );";
eval($evalthis);
Hope this helps!
This question already has answers here:
PHP call_user_func vs. just calling function
(8 answers)
Closed 6 months ago.
I dont understand the function, call_user_func() in the sense that i get how it works but I'm not sure why its required or in what context to use it in php. As far as I'm concerned why not just call the function instead of calling a function with a function? Thnx!
call_user_func gives PHP the ability to treat methods and functions as quasi first-class citizens. In functional languages like javascript there is no need for these special tools per-se because a function is an object that happens to be callable.
PHP is getting closer to having this sort of notion though, especially with the closure support that came along with PHP5.3. Take a look at the comment I put under #deceze's answer. There are some other tools (namely variable functions, reflection and now closures) that offer the same basic functionality.
The most notable thing about call_user_func though is how it allows you to treat global functions, static classes and objects with a uniform interface. It's probably the closest thing they have to a single interface to invoke functions no matter how they're implemented. Internally the PHP core group of developers is working to homogenize some sort of a 'callable' or 'invokable' interface for the language, I'm sure we'll see a clean offering in PHP5.4 or the next major release.
I've had a couple situations where this was very necessary. For example, when I was creating a project that allowed a user to construct parts of a programming language, the system would wrap the "tag" definition in a function before running it for security reasons. However, in doing this, I can't simply call those functions, because I don't know when I need to call them, or even what the names would be. Enter call_user_func()...
So, I'm sure you're confused right now. Let me explain. What my system did, was take some XML, and convert it into PHP/HTML/JS with PHP. This allowed for rapid creation of GUIs (which was the goal). Take this XML for example:
<window id="login-win" title="Access Restricted" width="310" height="186" layout="accordion" layoutConfig="animate:true">
<panel id="login-panel" title="User Login">
<form id="login-form" title="Credentials">
<textbox id="login-uname" label="Username"/>
<password id="login-pass" label="Password"/>
<submit text="Login"/>
</form>
</panel>
<panel id="login-register" title="Register">
Nothing, you can't register!
</panel>
</window>
Each XML tag would be read, then fed into it's corresponding PHP function. That function would determine what to do for that 1 tag. In order to pull this off, I had files each named after the tag it handled. So, for example, the tag's file was "submit.php". This file's contents would get wrapped in a generated function, something like:
function tag_submit($variables, $parent, $children){
// deal with the data, then echo what is needed
}
This function's name would be stored in an array, with it's associated tag name, with the rest of the generated functions. This makes it so the function is generated once, and only created when needed, saving memory, since I would do a if(func_exists()) call to determine if I needed it or not.
However, since this is all dynamic, and the user may want to add in a new tag, for say, a < date > tag, I needed to use call_user_func() to get things to work. I can't hard-code a function call if I don't know what the name is.
Hope that all made sense. Basically, yes, it is a rarely used function, but it is still very very useful.
Named functions, anonymous functions, static methods, instance methods and objects with an "__invoke" method are collectively known as 'callables'. If I have a callable it should be possible to call it by placing parentheses afterwards "()" (I'll assume it takes no arguments). This works when our callable is stored in a variable, for example:
$f(); // Call $f
However, what if I store a callable in an object property?
$obj = new stdClass;
$obj->my_func = function() {};
$obj->my_func(); // Error: stdClass does not have a "my_func" method
The problem is that PHP's parser is getting confused because the code is ambiguous, it could mean calling a callable property or calling a method. PHP chooses to always treat this kind of code as a method call, so we cannot call callable properties this way. This is why we need 'call_user_func':
call_user_func($obj->my_func); // Calls $obj->my_func
There are other times when PHP doesn't understand the normal parentheses syntax; for example, PHP currently (5.5) doesn't know how to call the return value of another callable:
get_a_callable()(); // Parse error, unexpected "("
call_user_func(get_a_callable()); // Calls the return value of get_a_callable
It's also not currently possible to call a function definion directly, which is useful to work around PHP's lack of "let" statements, for example:
function($x) { echo $x . $x; }('hello'); // Parse error, unexpected "("
call_user_func(function($x) { echo $x . $x; }, 'hello'); // Calls the function
There are also times where it's useful to have function calls /reified/ as the 'call_user_func' function. For example, when using higher-order functions like array_map:
$funcs = [function() { return 'hello'; },
function() { return 'world'; }];
array_map('call_user_func', $funcs); // ['hello', 'world']
It's also useful when we don't know how many parameters will be needed, ie. we can't substitute our own "function($f, $x, $y, ...) { return $f($x, $y, ...); }".
One particularly nice definition is partial application, which only takes a few lines thanks to call_user_func and call_user_func_array:
function partial() {
$args1 = func_get_args(); // $f, $a, $b, $c, ...
return function() use ($args1) {
// Returns $f($a, $b, $c, ..., $d, $e, $f, ...)
$args2 = func_get_args(); // $d, $e, $f, ...
return call_user_func_array('call_user_func',
array_merge($args1, $args2));
};
}
What is the difference between these two code excerpts, respectively, in PHP?:
function eat_apple($apple)
{
return true;
}
And:
function eat_apple()
{
$apple = func_get_arg(0);
return true;
}
Or is there a difference? If there is not, what is the point of func_get_arg()? Surely it serves some purpose I'm not aware of?
func_get_arg (and func_get_args) make it possible to have functions with a variable number of parameters, so called variadic functions.
Take array_merge as an example, which takes a variable number of arrays to be merged.
Hello. What is the difference between these two code excerpts, respectively, in PHP?:
-function eat_apple($apple)
+function eat_apple()
{
+ $apple = func_get_arg(0);
return true;
}
what is the point of func_get_arg()? Surely it serves some purpose I'm not aware of?
The officially stated purpose is to:
Return an item from the argument list
-- http://php.net/func-get-arg
In truth, there isn't much difference, and a standard passed argument is usually preferable over func_get_arg().
There are two occasions when you might want to use func_get_arg() rather than using defined arguments:
If you want to have an unlimited number of arguments. Typically, this would be better done with a single array argument, but there are times when you may want to allow unlimited arguments. A real example of a function that works this way is PHP's built-in printf function.
Where you have a complex function where the number of arguments given may alter what the arguments are used for and/or their data type. For example, passing a single argument may cause the function to expect a string, whereas passing two arguments, it may expect an integer first, and then the string. I can't think of any examples of this off the top of my head, but I'm fairly sure there are some. Ordinarily, I would say that this sort of behaviour is bad practice, but I can see how it may be useful for adding features while maintaining backward compatibility.
There are two things that you will definitely lose if you use fung_get_arg() instead of standard function arguments:
The ability to pass by reference.
The ability for your IDE to do any type hinting or auto-completion.
The other possible reason I could think of is avoiding a fatal error.
You have a function:
<?php
function display ($a, $b, $c) {
echo $a . " is " . $b . " " . $c;
}
?>
and you could call
<?php
display ("Rock", "good", "boy");
- this will not throw any error.
display ("Rock", "good");
- this will throw fatal error.
?>
So, now think of the second call, you could avoid the fatal error, see how many arguments are passed with func_get_args and process your code with func_get_arg(1) etc.
Several reasons:
You can use that magic to emulate overloading
You can write function (like printf) which can take undetermined number of arguments.
Example for first:
class a{
function X(MyOBJ $obj){...}
}
class b extends a{
function X(string $s,int $i){...}
}
class c extends b{
function X(){...}
}
This will throw a warning. If you use func_get_args() inside the function to get relevant parameters, no warning will be thrown.
Example for the second:
//not good, you can only send 3 strings
function merge_strings($s1, $s2, $s3){
return $s1 . $s2 . $s3;
}
//good one
function merge_strings(){
return join('',func_get_args());
}
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.
I've tested the following and it works on both PHP 5.2 and 5.3, however, it's not documented anywhere as far as I can see so I'm evaluating its use.
I have a function in a class called isValid, this checks a hash to see if the given value is in the set of allowed values. There are some values that are valid, but deprecated; I'd like my isValid function to update the passed in value to the current one and return true.
That's fine for when I call it myself, however, I'd like to use this method when used as a callback for array_filter too.
Here's a test case, which as expected results in an array with the values 2,3,4,5,6.
<?php
$test = array(1, 2, 3, 4, 5);
echo print_r(array_filter($test, 'maptest'), true);
function maptest(&$value)
{
$value ++;
return true;
}
So StackOverflow: is this allowed, or is it undocumented functionality that may disappear/stop working/cause errors in the future?
Yes, it's allowed.
In this respect, there's nothing special about calling functions through callbacks.
However, your specific example does not illustrate one difficulty. Consider:
function inc(&$i) { $i++; }
$n = 0;
// Warning: Parameter 1 to inc() expected to be a reference, value given:
call_user_func('inc', $n);
The problem is that you're passing $n to call_user_func and call_user_func doesn't accept values by reference. So by the time inc is called, it won't receive a reference. This isn't a problem with array_filter because it traverses the array directly and can directly pass the variables in the array to the callback function.
You could use call-time pass-by-reference, but this is deprecated and removed from trunk:
function inc(&$i) { $i++; }
$n = 0;
// Deprecated: Call-time pass-by-reference has been deprecated
call_user_func('inc', &$n);
So the best option is to use call_user_func_array instead:
function inc(&$i) { $i++; }
$n = 0;
call_user_func_array('inc', array(&$n));
This function will pass-by-reference the elements that have the is_ref flag set and will pass-by-value the other ones.
Except when explicitly noted, I'd say this is fine and acceptable. A callback can be any built-in or user-defined function.