Add Arguments to Existing PHP Function from Array - php

I'm looking to figure out how to add more arguments to a function call based on an Array and can't figure out what I need to do. The function in question doesn't work with simply passing an array, but the array has to explode somehow as if each array element was a new argument in the function call. I don't think call_user_func_array works but perhaps I don't know how to execute it properly. To give some context, the array of arguments are coming from a varying amount of $_GET arguments which is processed by an API class file I have no control over, but it appears that I can add a lot of arguments that allow the results to filter.
$arrayofarguments = array("dynamicarg1","dynamicarg2","dynamicarg3");
$runthis = example($staticargument1,
$staticargument2,
$staticargument3,
$arrayofarguments,
$staticargument4);
//run the results
echo $runthis;
Expected result
$runthis = example($staticargument1,
$staticargument2,
$staticargument3,
"dynamicarg1",
"dynamicarg2",
"dynamicarg3",
$staticargument4);
Thanks for the help! :)

I think you have to do something like
function example("blaa","foo","bar",$arrayofarguments,"test") {
$args = func_get_args();
// $arg[3] would be $arrayofarguments
foreach ( $arg[3] as $function) {
$function(); // this calls the function
}
}

Related

Using a function in php - what am I doing wrong?

$users = [
"Andrew",
"Max",
"Larry",
"Ricardo",
"Lucy",
"Marcus",
"Sophie"
];
$sector_rel = [];
$location_rel = [];
function sectorRel($user){
return sector_rel[] = round(1/rand(1,10),3);
}
function locationRel($user){
return $location_rel[] = round(1/rand(1,20),3);
}
foreach($users as $user){
sectorRel($user);
locationRel($user);
}
This:
function sectorRel($user){
return sector_rel[] = round(1/rand(1,10),3);
}
Should be/could be:
function sectorRel($user){
global sector_rel;
sector_rel[] = round(1/rand(1,10),3);
}
The problem is that the functions don't have access to the array variables. You can import them into the function scope using the keyword global, if they are indeed global variables. Now, having global variables isn't a good thing, and for a small test it's okay, but eventually you'll be eliminating your globals and this solution won't work.
But alternatively, you could pass the array variables to the function as an argument. However, this still introduces a lot of logic in the function. The function has to be told about the array, it must know that it needs to add a value to the end, and it also needs to calculate the actual value to add.
So better, make the function just return the calculated value and add it to the array outside of the function:
function sectorRel($user){
// Assuming your are going to use 'user' here somewhere?
return round(1/rand(1,10),3);
}
function locationRel($user){
return round(1/rand(1,20),3);
}
foreach($users as $user){
sector_rel[] = sectorRel($user);
$location_rel[] = locationRel($user);
}
You can then wrap this entire snippet of code into another function and call that to populate the arrays. That way, you've quite reasonably split the responsibilities of the functions and have a piece of code that looks nice and clean.
You do not need to use return in either of sectorRel or locationRel. At the moment this will return the reference to that array and it is not being stored in a variable. You would need to store them in a variable or just get rid of the return. My PHP is a little weak at the moment but you should probably append the values in those functions to the array.
Also if you have a parameter called $user for each of those functions you should either use that parameter or just get rid of it.

How to write a controller that sends an array as a URL parameter?

In some MVC platforms, a controller method accepts an URL's contents as forward-slash separated list of elements, received as parameters, e.g.
site.com/controller/method/var1/var2
has associated controller:
class Controller
function method(var1, var2){
}
}
But how can I achieve this coding? I wish to start with an array and send a parameterized list to a function, i.e.
$args = array("one"=>"cheese","two"=>"eggs");
php_function("myfunction",$args);
Within myfunction, I would have
function myfunction($one, $two){
}
I know about func_get_args for accepting an unknown number of arguments. user_call_func is useful except
user_call_func("myfunction",$args);
...results in the first parameter containing an array of arguments, no difference to func_get_args called from within the function.
extract doesn't work either as I need to receive the array as a variable inside the function.
call_user_func_array takes a method description and an array of arguments, and returns the result of calling the function. I think it will take the arguments from the array in order though, rather than by name. You should assemble an array of the arguments in the correct order, and perhaps validate for missing arguments, before using this.
I've managed to create your desired with the following.
class BootStrap {
private $controller = 'NameOfIle.php';
private $method = 'function()';
private $params = array('sdfds' => 'dsfdsf', 'sdfdsfsdfdsfsd' => 'sdfdsfds');
public function __construct() {
call_user_func_array(array($this->controller, $this->method), $this->params);
}
}

Call methods by defined names & add extra parameter before being called

I have a Validator class that can build several arrays with methods (names) stored.
Like so $this->rules[1] = ['trim()', 'required()', 'max(35)'];
How can I loop through every method the array and call it exactly by how they are defined?
If I do it like the following, I get Undefined property: Validator::$trim() etc. error.
foreach ($this->rules[1] as $method) {
$this->$method;
}
How can I add an extra parameter $input to each method in the array before it gets in the loop?
So instead of trim() it would be trim($input), and for max(35) max(35, $input), etc.
First of all, use $this->{$method} to call your method in your example.
Secondly, don't call them like that at all. Use call_user_func_array instead.
You need to extract method name and parameters frist in order to call directly.
I recommend you use a placeholder for your $input to add it to your method call.
You can then pass the parameters for your function call as an array.
$ruleset = 'max(34,:input)';
// do the string manipulation yourself please ;-)
$method = 'max';
$input = getInput(); // wherever you get that from
$parameters = array (34, $input),
call_user_func_array(__NAMESPACE__ .'\Validator::' . $method, $parameters);
What you are looking for are the call_user_func and/or call_user_func_array methods.
As Andresch pointed out, the way your rules are defined aren't flexible. Now you would have to parse them to retrieve the inputs for the function. a better way would be the following format:
$this->rules[1] = array(
'trim',
'required',
array('max'=>35)
);
and then
foreach ( $this->rules as $rule )
{
if ( is_array($rule)
{
call_user_func_array(array($this, key($rule)), current($rule));
}
else
{
call_user_func(array($this,$rule));
}
}
P.S. don't just copy paste this code, this is intended for explanation

Trying to pass function parameters

I'm trying to take two lines of code from an elseif statement and create a function that returns the parameters back to the parent function. It's a simple card game that searches my $Cards array for a three of a kind. Here's the original code:
elseif(count($Cards) == 3) {
$CardsNotOfValue = $this->_getCardsNotOfFaceValue($faceValue, $CardsGroupedByValues);
list($Kicker1, $Kicker2) = $this->_getSortedCards($CardsNotOfValue);
return new ThreeOfAKind(array_merge($Cards, array($Kicker1, $Kicker2)));
}
Thus far, my code looks like this:
function { if (count($Cards) == 3) {
**LINE 36** $Kicker = $this->kickerCards($faceValue, $CardsGroupedByValues); }
**LINE 55** public function kickerCards(array $kickers)
{
$CardsNotOfValue = $this->_getCardsNotOfFaceValue($faceValue, $CardsGroupedByValues);
return $this->_getSortedCards($CardsNotOfValue);
}
When I try to execute a four of a kind, I get the following error (I tried to highlight the lines in question above):
PHP Catchable fatal error: Argument 1 passed to BestHandIdentifier::kickerCards() must be an array, integer given, called in /home/dev/parameter2/BestHandIdentifier.php on line 36 and defined in /home/dev/parameter2/BestHandIdentifier.php on line 55
I'm having a bit of trouble understanding how to create ($faceValue, $CardsGroupedByValues) and pass an array for my new function to evaluate. Have I gone too far in the wrong direction to begin with?
Your function definition is:
public function kickerCards(array $kickers);
So $kickers must be an array...
You are trying to call the function with:
$this->kickerCards($faceValue, $CardsGroupedByValues);
Passing two arguments, the $faceValue which is an integer, 2nd argument is an array.
Your function definition should look like:
public function kickerCards($faceValue, array $cards);
If I could elaborate further, making some assumptions.
My assumptions:
The function take a face value and array of cards currently held
The return of the function should be the cards in that array that do not match the face values.
The Cards are an array with a value (and possibly suit) key. e.g.
$twoOfHearts = array('value'=>2,'suit'=>'hearts');
So here's a possible implementation
public function kickerCards($faceValue, array $cards) {
$kickerCards = array();
foreach($cards as $card) {
if ($card['value'] != $faceValue)
$kickerCards[] = $card;
}
return $kickerCards;
}

Passing an Array as Arguments, not an Array, in PHP

I seem to remember that in PHP there is a way to pass an array as a list of arguments for a function, dereferencing the array into the standard func($arg1, $arg2) manner. But now I'm lost on how to do it. I recall the manner of passing by reference, how to "glob" incoming parameters ... but not how to de-list the array into a list of arguments.
It may be as simple as func(&$myArgs), but I'm pretty sure that isn't it. But, sadly, the php.net manual hasn't divulged anything so far. Not that I've had to use this particular feature for the last year or so.
http://www.php.net/manual/en/function.call-user-func-array.php
call_user_func_array('func',$myArgs);
As has been mentioned, as of PHP 5.6+ you can (should!) use the ... token (aka "splat operator", part of the variadic functions functionality) to easily call a function with an array of arguments:
<?php
function variadic($arg1, $arg2)
{
// Do stuff
echo $arg1.' '.$arg2;
}
$array = ['Hello', 'World'];
// 'Splat' the $array in the function call
variadic(...$array);
// 'Hello World'
Note: array items are mapped to arguments by their position in the array, not their keys.
As per CarlosCarucce's comment, this form of argument unpacking is the fastest method by far in all cases. In some comparisons, it's over 5x faster than call_user_func_array.
Aside
Because I think this is really useful (though not directly related to the question): you can type-hint the splat operator parameter in your function definition to make sure all of the passed values match a specific type.
(Just remember that doing this it MUST be the last parameter you define and that it bundles all parameters passed to the function into the array.)
This is great for making sure an array contains items of a specific type:
<?php
// Define the function...
function variadic($var, SomeClass ...$items)
{
// $items will be an array of objects of type `SomeClass`
}
// Then you can call...
variadic('Hello', new SomeClass, new SomeClass);
// or even splat both ways
$items = [
new SomeClass,
new SomeClass,
];
variadic('Hello', ...$items);
Also note that if you want to apply an instance method to an array, you need to pass the function as:
call_user_func_array(array($instance, "MethodName"), $myArgs);
For sake of completeness, as of PHP 5.1 this works, too:
<?php
function title($title, $name) {
return sprintf("%s. %s\r\n", $title, $name);
}
$function = new ReflectionFunction('title');
$myArray = array('Dr', 'Phil');
echo $function->invokeArgs($myArray); // prints "Dr. Phil"
?>
See: http://php.net/reflectionfunction.invokeargs
For methods you use ReflectionMethod::invokeArgs instead and pass the object as first parameter.

Categories