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

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

Related

PHP oop how can i call dynamic function name

I have a method display() in the book class.
$name = 'display()';
$book = new Book('PHP Object-Oriented Solutions', 300);
$book->$name;
How can i call display method using $book->$name
You need to tell PHP that you're trying to execute a method, not in the variable itself, but within the actual code:
$name = 'display';
$book = new Book('PHP Object-Oriented Solutions', 300);
$book->$name();
Otherwise, as you have seen, it will treat $name as a property name, and rightly so ... If you have both a property and a method named 'display', there wouldn't be a way to distinguish between the two using what you've tried.
The cleanest way (imo at least) is to use something like:
$name = 'display';
$book = new Book('PHP Object-Oriented Solutions', 300);
call_user_func([$book, $name]); // This looks cleaner and/or more obvious on first sight.
// call_user_func_array([$book, $name], $arrayOfArguments);
// And as #Narf suggested (and I agree cuz we move forward)
call_user_func([$book, $name], ... $arrayOfArguments);
And yes you can pass parameters to this function, that will be passed to the function, but you have to list them after the callable array. in order to avoid doing that (hard to maintain and not always what you want) you can use call_user_func_array which accepts an array of arguments as second argument that is passed to the callable.
call_user_func Documentation
call_user_func_array Documentation

Add Arguments to Existing PHP Function from Array

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
}
}

How to access an array that is defined in the file scope from a function in the same file in PHP?

I'm writing a blacklist word checker. I've named the script as blacklist_check.php and it looks like this:
<?php
$black_list = [
'ass',
'anus',
/* many others that i skipped here */
];
function is_black_listed ($word) {
return in_array($word, $black_list);
}
?>
However when I use the is_black_listed function, I always get Warning: in_array() expects parameter 2 to be array, null given.
Should I put the $black_list array inside of is_black_listed function? I don't want to do it, as the array would always get created when I call the function, instead of it being just one time when I require (or include) the script!
Should I use global $black_list inside of is_black_listed function?
Help me out with the best practice to solve this problem!
Don't use a global variable, they're pretty hard to maintain and make your code less readable. Instead, just pass the array to the function:
function is_black_listed ($word, $black_list)
Then call it with:
is_black_listed( "bad words!", $black_list);
Better yet, create a class to do this, and create the array as a member variable:
class WordFilter {
private $black_list = [ ... ];
function __construct( $words = array()) {
// Optionally add dynamic words to the list
foreach( $words as $word)
$black_list[] = $word;
}
function is_black_listed( $word) {
return in_array( $word, $this->black_list);
}
}
$filter = new WordFilter( array( 'potty', 'mouth'));
$filter->is_black_listed( "bad");

php, I cant pass an array as reference

this is the function:
public function func(&$parameters = array())
{
}
now I need to do this:
$x->func (get_defined_vars());
but that fails. Another way:
$x->func (&get_defined_vars());
it drops an error: Can't use function return value in write context in ...
Then how to do it?
get_defined_vars() returns an array, not a variable. As you can only pass variables by reference you need to write:
$definedVars = get_defined_vars();
func($definedVars);
Though I don't really see a reason to pass the array by reference here. (If you are doing this for performance, don't do it, as it won't help.)
public function func(&$parameters = array())
{
}
Not defined correctly.
Try this way:-
call_user_func_array( 'func', $parameters );
See the notes on the call_user_func_array() function documentation for more information.

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