class method with unlimited parameters - php

I have the following code:
$array = array('foo', 'foo', 'bar', 'bis', 'ter')
Arrays::without($array, 'foo', 'bis') // Returns array('bar', 'ter')
As you can see, the second and third parameter to calling the Arrays::without function. you can pass as many parameters as you want, such as:
Arrays::without($array, 'foo', 'bis','athirdparam','afourthparam') // Returns array('bar', 'ter')
Im trying to encapsulate this into a static method inside a class i have:
public static function without($arr,$p)
{
return Arrays::without($arr,$p);
}
What i need to know is if there is a way i can pass unlimited arguments to this method without and use them inside my funciton call to Arrays::without

You can call:
Arrays::without($arr, ...$p);
Where $p is an array or write your method like that:
public static function without($arr,$p)
{
return Arrays::without($arr, ...$p);
}
But it's quite unnecessary.
Check splat operator: http://php.net/manual/en/migration56.new-features.php#migration56.new-features.splat

Either use func_get_args() inside the function, or public static function without(...$args) for the function signature.... it's all described here in the PHP Docs

Related

Is there a way to force a function or method to be called using named parameters only?

For example, let's say we wrote the following function:
function myFunction(
Foo $foo,
Bar $bar,
) {}
In the future, we realize we want to re-order our parameters:
function myFunction(
Bar $bar,
Foo $foo,
) {}
If this function is only ever called using named parameters, then the above change does not break any existing code.
Therefore, is there a way to force a function or method to be called using named parameters only?
If you really want to, then one way would be to use an array parameter
function myFunction ($par)
{
$Foo = $par['Foo'];
$Bar - $par['Bar'];
}
call it
$param = ['Foo'=>23.4, 'Bar'=>'Hello'];
myFunction ($param);

Second class changes first class without returning or using a reference PHP OOP

i have 2 classes. I am confused about how the second class is editing the first's properties without being passed the first class as a reference.
first.php
namespace first;
class first {
public $prop = 'first value';
function __construct(){
$second = '\\second\\second';
require 'second.php';
call_user_func_array(array(new $second, 'method'), array($this));
}
}
$first = new first();
echo $first->prop;
second.php
namespace second;
class second {
function method($first){
$first->prop = 'second value';
}
}
i get this output:
second value
can someone please explain how the second class is doing this? it seems to defy everything i've learned.
In PHP by default, objects are passed by reference. In your case you are passing the class object "first" to the second class object "second". So PHP does it for you, and you don't have to specify to pass it by Reference e.g. (&$variable) since $this is an object and not a variable. If you are passing a $variable then you have to specify if you want to pass it by reference ($second->method(&$variable))
call_user_func_array(array(new $second, 'method'), array($this));
In that call you passed ($this) as the argument for method "method" in class second and modify the property "prop".
This function is doing the trick.
call_user_func_array()
This is call back function :- call_user_func_array — Call a callback with an array of parameters
function __construct(){
$second = '\\second\\second';
require 'second.php';
//This is the call back function which
call_user_func_array(array(new $second, 'method'), array($this));
}
call_user_func_array(array(new $second, 'method'), array($this));
This function hast two parameters, array(new $second, 'method'), array($this)
in the first parameter you have an array of two elements, namely new $second, and 'method' which instantiates the class new second and the function method. The second parameter is
array($this) which says this class, meaning or referring to `class first {}`
In nutshell , the reason whey the first class can be modified is because it has got a call back function with parameters of the second class.
you can check out how is function works http://www.php.net/manual/en/function.call-user-func-array.php
As Elin suggested, please read http://www.php.net/manual/en/language.oop5.references.php. It answers everything.
As of PHP 5, an object variable doesn't contain the object itself as value anymore. It only contains an object identifier which allows object accessors to find the actual object. When an object is sent by argument, returned or assigned to another variable, the different variables are not aliases: they hold a copy of the identifier, which points to the same object.

How do you know what parameters/arguments to put in a closure?

When do closures have parameters (or how do closures with parameters work)? I know that use() is used to import variables outside the anonymous function, but what about the parameter(s) of the closure itself?
An example of closures with parameters is currying:
function greeter($greeting)
{
return function($whom) use ($greeting) {
// greeting is the closed over variable
return "$greeting $whom";
};
}
$hello_greeter = greeter('hello');
echo $hello_greeter('world'); // will print 'hello world';
The greeter function will return a "half-implemented" function that will always start with the same greeting, followed by whatever is passed into it (e.g. the person to greet).
If you are using a function that accept an anonymous function as parameter, then check the doc of the function.
If the function is written by you, then you are the controller, you decide it.
use() is especially useful for functions that require a function as a parameter. It might be required that the passed function take only two parameters and that any extra parameter is simply ignored. In this case, use use() to "import" a variable from current scope to the anon function.
$myvar = 10;
$fun = function(&$val, $index) use ($myvar) {$val += $myvar;};
$testArray = array(1,2,3);
array_walk($testArray, $fun);
var_dump($testArray); // 11, 12, 13
Note: if your anon function signature was function(&$val, $index, $myvar) instead, you would get constant warnings when using your anon function with array_walk because that extra 3rd parameter is unused and undefined. So, use use() to pass in that extra parameter instead.
Edit: you can also pass in variables by reference in use()...
$myvar = 10;
$fun = function(&$val, $index) use (&$myvar) {$myvar = 1; $val += $myvar;};
$testArray = array(1,2,3);
array_walk($testArray, $fun);
var_dump($testArray); // 2, 3, 4
echo $myvar; // 1
Closures passed to PHP functions that should have parameters are detailed in the docs. A good example of this is array_walk(), which is used to apply the callback to an iterable:
$arr = array('a', 'b', 'c');
array_walk($arr, function($key, $val) {
echo $key . ' => ' . $val . "\n";
});
In the docs, the parameters that you should include on the callable passed to array_walk() are detailed under "Parameters." It says:
Typically, funcname takes on two parameters. The array parameter's value being the first, and the key/index second.
Often times you will find similar hints on other functions in the PHP docs. I was disappointed that the documentation for array_map() was not as detailed, but I can remember there being other functions that excepted callables that had sufficient closure parameter documentation.
If you are looking to write your own function that accepts closures (or other values that you can call) and dictates what parameters it must have, you can use the typehint callback in PHP 5.3 or callable in PHP 5.4.
function gobblesUpCallable(callable $func) {
call_user_func($func); // Use this, someone could pass in a callable string or array
}
However, to specify parameters, you'll need to use ReflectionClass or ReflectionFunction which means you probably forgo call_user_func().

Get number of parameters a function requires

This is an extension question of PHP pass in $this to function outside class
And I believe this is what I'm looking for but it's in python not php: Programmatically determining amount of parameters a function requires - Python
Let's say I have a function like this:
function client_func($cls, $arg){ }
and when I'm ready to call this function I might do something like this in pseudo code:
if function's first parameter equals '$cls', then call client_func(instanceof class, $arg)
else call client_func($arg)
So basically, is there a way to lookahead to a function and see what parameter values are required before calling the function?
I guess this would be like debug_backtrace(), but the other way around.
func_get_args() can only be called from within a function which doesn't help me here.
Any thoughts?
Use Reflection, especially ReflectionFunction in your case.
$fct = new ReflectionFunction('client_func');
echo $fct->getNumberOfRequiredParameters();
As far as I can see you will find getParameters() useful too
Only way is with reflection by going to http://us3.php.net/manual/en/book.reflection.php
class foo {
function bar ($arg1, $arg2) {
// ...
}
}
$method = new ReflectionMethod('foo', 'bar');
$num = $method->getNumberOfParameters();

Passing a function's args straight to another function

In PHP, is there a way to send a function's arguments straight to another function without having to specify them one by one? Is there a way to expand func_get_arg() so that the other function receives the individual arguments and not just a single array?
I'd like to send the arguments from foo() straight to bar() like so:
function foo($arg1, $arg2, $arg3)
{
$args = expand_args(func_get_arg());
bar($args);
}
yes.
function foo($arg1, $arg2, $arg3)
{
$args = func_get_arg();
call_user_func_array("bar",$args);
}
If you want to call it on a function belonging to an instance of an entirely seperate class, that can be done by passing the first arg to call_user_func_array as an array.
In this example, the function foo accepts whatever arguments, and passes them directly into $bar->baz->bob(), and returns the result.
public function foo(/* example arguments */)
{
return call_user_func_array
(
array($bar->baz, 'bob'),
func_get_args()
);
}

Categories