Php Custom Mvc - how to check if function gets arguments? - php

Im working lately on a custom mvc for php, and one of the question was really bothered me:
Ive got the controller class, and i want to check if a certain function of the class getting arguments, and if not, return false.
is there any method to do it?
cause i searched in php.net and google and didn't find anything....
thanx!

Use reflection:
$reflection = new ReflectionMethod ($class_name, $method_name);
$params = $r->getParameters();
$params is now an array of ReflectionParameter objects

Have a look at func_get_args
You can use it inside the method in your controller to get the list of all arguments passed to the method.
You also have func_num_args that will just give you the number of arguments passed to your method.

Use function func_get_args
function sum(){
$s=0;
foreach(func_get_args() as $a) $s+= is_numeric($a)?$a:0;
return $s;
};
print sum(1,2,3,4,5,6); // 21

Related

PHP - is there a way to save an already defind function in a variable?

I am interested in something google couldn't really help me with...
I know that its possible to use anonymous functions and also store functions in a variable in PHP like that
$function = function myFoo() { echo "bar"; }
and call it using the variable: $function();
So far so good but what if I have a function or method declared somewhere but not saved on intializing?
I have a function that shall expect a callable, of course call_user_func() can help me here but then I need to pass the method name in my callback handler which I think is pretty unsafe because in the moment I add the callback I cant say if it really is a function and exists when I store it.
Thatswhy I would like to realize the following szenario:
This function:
function anyFunction() {
echo "doWhatever...!";
}
should be saved in a variable at a later point in time:
$myOtherFunction = get_registered_func("anyFunction");
I know get_registered_func() doesnt exist but I want to know if this is possible somehow!
With this I could now have another function
function setCallback(callable $theCallbackFunction) { }
And use it like this:
setCallback($myOtherFunction);
This would have a great advantage that an exception / a fatal is thrown when the parameter is no function or does not exist.
So in short, is there a way to store a previously defined, already existing function or method in a variable?
PHP's callable meta type can be:
a string
an array
an anonymous function
Only the latter one is somewhat "type safe", i.e. if you get an anonymous function you know it's something you can call. The other two options are merely formalised informal standards (if that makes sense) which are supported by a few functions that accept callbacks; they're not actually a type in PHP's type system. Therefore there's basically no guarantee you can make about them.
You can only work around this by checking whether the callable you got is, well, callable using is_callable before you execute them. You could wrap this into your own class, for example, to actually create a real callable type.
I see no reason why this shouldn't be possible, other than there not being a PHP function to do it. The anonymous function syntax is newly introduced in PHP, I wouldn'be surprised if it was still a little rough around the edges.
You can always wrap it:
function wrap_function ($callback) {
if (is_callable($callback) === false) {
throw new Exception("nope");
}
return function () {
call_user_func($callback, func_get_args());
}
}
$foo = new Foo();
$ref = wrap_function(array($foo, "bar"));
Not a good way, but maybe this helps you:
function foo($a) {
echo $a;
}
$callFoo = 'foo';
$callFoo('Hello World!'); // prints Hello

Trying to understand php function call_user_func found in a book example

The example comes from the book "Professional PHP5" by Edward Lecky-Thompson.
function __get($propertyName) {
if(!array_key_exists($propertyName, $this->propertyTable))
throw new Exception("Błędna własność \"$propertyName\"!");
if(method_exists($this, 'get' . $propertyName)) {
return call_user_func(array($this, 'get' . $propertyName));
} else {
return $this->data[$this->propertyTable[$propertyName]];
}
}
Can somebody please explain what happens exactly step-by-step in the call_user_func function?
On php.net I've read that the first parameter is a function to be called and the remaining parameters are passed to that function as its parameters.
On php.net there were simple examples and I had no problem understanding them. However I don't get it why in the above example there is an array, and why $this as the first element of the array?
P.S.
I found a similar question on stackoverflow, and I understand what the code is supposed to do but I don't understand fully why what's written works.
Here's the link to the similar question:
PropertyObject
The two-part array is PHP's informal formal convention of passing the method of a specific object as a callback/callable. See http://php.net/manual/en/language.types.callable.php for details.
array($this, 'getFoo') simply stands for the getFoo method of the $this object.
This is used in a class. If $propertyName = 'Foo' you are effectively calling the function $this->getFoo.
$this is always the current object so another way of saying it is that you are calling the function getFoo on the current object.

PHP Callback function not working on object functions

I have an array and want to apply MySQLi->real_escape_string on every member of the array through array_walk but this is not working:
array_walk($array, '$mysqli->real_escape_string');
It gives this error:
Warning: array_walk() expects parameter 2 to be a valid callback, function '$mysqli->real_escape_string' not found or invalid function name in C:\wamp\www\ts.php on line 69
$mysqli is a valid object and works fine if I do $mysqli->real_escape_string('anything') on anything else.
My Question: Is it not possible to pass object's functions as callback ? Or am I doing something wrong.
IMPORTANT: I know I can create my own callback function and implement $mysqli->real_escape_string in it BUT I want to know is it not possible to use callback as an object's function ?
If your calling a method within an object you should pass in an array, first item being the object / context and then second should be the method:
Small example
function callback()
{
//blah
}
the above is called a function and should be called like so: array_walk($array, 'callback');
class object()
{
public function callback()
{
}
}
the above callback is called a method, its practically the same as a function but because its within a class it has a parent context, so should be called like so:
$object = new object();
array_walk($array, array($object , 'callback'));
MySQLi is an object orientated library so after you have initialized your mysqli object you should call the "method" like so:
array_walk($array, array($msqli, 'real_escape_string'));
Also as mentioned above, array_walk will walk both key and value into the mysql object witch will cause in exact escaping, you should use array_map to walk the values alone:
array_map($array, array($msqli, 'real_escape_string'));
As you can read on php callback page, you shall use:
# produces an error
array_walk($array, array($msqli, 'real_escape_string'));
array_map($array, array($msqli, 'real_escape_string'));
array_walk will only allow a user defined function to be passed as the callback, not a core PHP function or method. To do this I would try the following:
foreach($array as &$value) {
$value = $mysqli->real_escape_string($value);
}
Passing the value by reference allows it to be modified within the foreach loop, resulting in each member of the array being escaped.
I found this post to be quite useful when figuring out how to get array_walk() to work in methods within a class. Adding it to this thread in case it helps others out.

__call magic creating new classes in PHP

I am using the __call magic within some of my mvc code to produce an autoloadable forms framework but I have ran into a problem I am hoping some one on here might have a work around for.
The __call magic takes two paramters: $methodName and $arguments. The arguments come back as an array of args which you called. Normally this function is called on methods you can do as such so feed these arguments into a function:
call_user_func_array($methodName, $arguments);
And this will propogate the methods signature with the arguments. I am trying to do something a little more complex. I am attempting to propogate a classes constructor the same way, through being able to send maybe a imploded comma deliminenated array of the arguments into the classes constructor or just sending the args in directly but both of these do not produce the required result. When I send an imploded array down into the constructor PHP thinks it's a string and when I send the array it thinks it's an array.
This is the code I am using atm:
public function __call($method, $args){
return $this->init_element(new $method($args['name'], $args['value'], $args['opts']));
}
What if I had 4 arguments to pass down though? Is there a way I can get it to dynamically fill the constructor just like you can for a function using call_user_func_array()?
I could use an attributes() function to do this but I would really like to be able to do it like I can with functions.
Thanks in advance,
Use PHP's reflection classes: (http://php.net/manual/en/class.reflectionclass.php)
$obj = new ReflectionClass( $classname );
then
$ins = $obj->newInstanceArgs( $arguments );
or
$ins = $obj->newInstance( );
I saw the following somewhere around the web:
call_user_func_array(array($obj, '__construct'), $args);

PHP, how to pass func-get-args values to another function as list of arguments?

I want to create a function (my_function()) getting unlimited number of arguments and passing it into another function (call_another_function()).
function my_function() {
another_function($arg1, $arg2, $arg3 ... $argN);
}
So, want to call my_function(1,2,3,4,5) and get calling another_function(1,2,3,4,5)
I know that I shoud use func_get_args() to get all function arguments as array, but I don't know how to pass this arguments to another function.
Thank you.
Try call_user_func_array:
function my_function() {
$args = func_get_args();
call_user_func_array("another_function", $args);
}
In programming and computer science, this is called an apply function.
Use call_user_func_array
like
call_user_func_array('another_function', func_get_args());
It's not yet documented but you might use reflection API, especially invokeArgs.
(maybe I should have used a comment rather than a full post)
I have solved such a problem with the ...$args parameter in the function.
In my case, it was arguments forwarding to the parent construction call.
public function __construct(...$args)
{
parent::__construct(...$args);
}

Categories