PHP Using a variable when calling a static method - php

I have three classes that all have a static function called 'create'.
I would like to call the appropriate function dynamically based on the output from a form, but am having a little trouble with the syntax. Is there anyway to perform this?
$class = $_POST['class'];
$class::create();
Any advice would be greatly appreciated.
Thanks.

If you are working with PHP 5.2, you can use call_user_func (or call_user_func_array) :
$className = 'A';
call_user_func(array($className, 'method'));
class A {
public static function method() {
echo 'Hello, A';
}
}
Will get you :
Hello, A
The kind of syntax you were using in your question is only possible with PHP >= 5.3 ; see the manual page of Static Keyword, about that :
As of PHP 5.3.0, it's possible to
reference the class using a variable.
The variable's value can not be a
keyword (e.g. self, parent and
static).

What you have works as of PHP 5.3.
ps. You should consider cleaning the $_POST['class'] since you cannot be sure what will be in it.

use call_user_func
heres an example from php.net
class myclass {
static function say_hello()
{
echo "Hello!\n";
}
}
$classname = "myclass";
call_user_func(array($classname, 'say_hello'));
call_user_func($classname .'::say_hello'); // As of 5.2.3
$myobject = new myclass();
call_user_func(array($myobject, 'say_hello'));

I believe this can only be done since PHP 5.3.0. Check this page and search for $classname::$my_static to see the example.

I may be misunderstanding what you want, but how about this?
switch ($_POST['ClassType']) {
case "Class1":
$class1::create();
break;
case "Class2":
$class2::create();
break;
// etc.
}
If that doesn't work, you should look into EVAL (dangerous, be careful.)

Related

Use contents of string variable to call function

I have the following piece of code
copy($source, $target);
I also use
move_uploaded_file($source, $target);
To prevent code reuse, I want to pass copy and move_uploaded_file in via a variable.
If my variable is $var = "copy";, simply putting $var($source, $target);, doesn't seem to work.
Are there any special characters that must surround $var?
Thanks.
The correct syntax is $var (variable functions), so your code should work.
But please don't do that, just write the code in a straightforward and readable manner. There are legitimate use cases for this technique, but this is not one of them.
You want to look at Variable Functions which goes on to explain how to do that.
function foo() {
echo "In foo()<br />\n";
}
$bar = 'foo';
$bar(); //this calls foo()
This can also be done on both object methods and static methods.
Object Methods
class Foo
{
function MyFunction()
{
//code here
}
}
$foo = new Foo();
$funcName = "MyFunction";
$foo->$funcName();
Static Methods
class Bar
{
static function MyStaticFunction()
{
//code here
}
}
$funcName = "MyStaticFunction";
Bar::$funcName();
While maybe not the case in your situation, when dealing with functions dynamically like this, it is important to check whether the function actually exists and/or is callable.
Alternatively to using Variable Functions, you can use call_user_func which will call the function based on the string name and with provided parameters.
You can use the PHP function call_user_func().
More info here.
You can use call_user_func to do this.
$result = call_user_func($functionToCall, $source, $target)
Documentation: PHP: call_user_func
as far as i know your code should work
here is the link for your refrence

Call function from an object?

<?php
$ar = (object) array('a'=>function(){
echo 'TEST';
});
$ar->a();
?>
I get this error Call to undefined method
Update:
If you are using PHP 5.3 or greater, take a look at other answers please :)
I don't think that's correct syntax, it would give you:
Parse error: syntax error, unexpected T_FUNCTION in....
You need to create a class, add method to it, use new keyword to instantiate it and then you will be able to do:
$ar->a();
class myclass
{
public function a()
{
echo 'TEST';
}
}
$ar = new myclass;
$ar->a(); // TEST
See Classes and Objects for more information.
Anonymous or not, you have a callback function, thus you need to handle it as such. E.g.:
<?php
$ar = (object) array(
'a' => function(){
echo 'TEST';
}
);
call_user_func($ar->a);
?>
For some reason it doesn't seem possibly to run the closure the way you do.
If you modify your code and set another variable to the function, it can be called:
$ar = (object) array('a'=>function(){
echo 'TEST';
});
$a = $ar->a;
$a();
This is no solution. But from what I can see, this seems like a bug or limitation in PHP 5.3.
I am using 5.3.5 when trying this.
There is no function a() but the property a, so you should call it by $ar->a.
Anyway I don't think it's going to work the way you expect it to.
EDIT:
As suggested by Álvaro G. Vicario you should use call_user_func, not echo to call the function and it will work correctly.
Or, just for the fun of it, you can do something like this -
<?php
$ar = new stdClass;
$ar->a = function($to_echo){ echo $to_echo; };
$temp = $ar->a;
//[Edit] - $ar->a("hello"); // doesn't work! php tries to match an instance method called "func" that is not defined in the original class' signature
$temp("Hey there");
call_user_func($ar->a("You still there?"));
?>

PHP and closures

Working a lot with JS I have come to love closures, so I was pleased to learn that there are closures in PHP also. However I just can't get this stuff to work, what's wrong with this piece of code?
class Foo {
public $Bar;
public function Foo() {
$this->Bar = function() { echo "Hello World"; };
}
};
$F = new Foo();
$F->Bar();
I keep getting PHP Fatal error: Call to undefined method Foo::Bar() errors.
This has been discussed a lot on SO already (see e.g. this answer). This should do the trick:
$b = $f->Bar;
$b();
Yes, it is that stupid. You could use call_user_func() to put in in one line (see jlb's answer to this question), but the ugliness remains.
If you want a one-line solution to replace
$F->Bar()
try this:
call_user_func($F->Bar);
PHP has separation between methods and fields. In fact, you can have a method and a field of the same name at the same time:
class Foo {
public $Bar;
function Bar() { echo "hello\n"; }
};
$F = new Foo();
$F->Bar = 42;
$F->Bar(); // echoes "hello"
So you can see that, to avoid ambiguity, there must be a separate syntax between calling a method with that name, and accessing a field with that name and then calling that as a function.
If PHP had better syntax, they would support ($F->Bar)(), i.e. function call operator on any expression, but currently only variables can be "called".
PHP isn't liking the $F->Bar notation for accessing the closure.
If you change this slightly to
$t = $F->Bar();
$t();
then it works.

php newbie question: classes

i'm new to php and am wondering - is it possible to initialize a class with parameters?
like $obj = new myClass('myID');
i've tried but it gave me an error.
maybe someone can point me to some good tutorials.
thanks
Yes it is, you need to pass the variables through the constructor:
class SomeClass
{
function __construct($some_var)
{
}
}
Please note that in older versions of php the constructor needs to have the name of the class, it´s __construct() since php 5.
Yes, you need to use a class constructor.
Example:
<?php
class ClassWithArgs
{
function __construct($argument1, $argument2)
{
echo "arg 1 = $argument1\n";
echo "arg 2 = $argument2\n";
}
}
$object = new ClassWithArgs('one', 'two');
?>
Example Output
arg 1 = one
arg 2 = two
I suggest you also take a look at the PHP5 OOP documentation, it includes simple examples to get you going: http://php.net/manual/en/language.oop5.php

Getting static property from a class with dynamic class name in PHP

I have this:
one string variable which holds the class name ($classname)
one string variable with holds the property name ($propertyname)
I want to get that property from that class, the problem is, the property is static and I don't know how to do that.
If the property weren't static, it would have been:
$classname->$propertyname;
if the property were a method, I could have used call_user_function
call_user_func(array($classname, $propertyname));
But in my case, am I just lost. I am however hoping that it is possible. With the thousands of functions that PHP has, he'd better have something for this as well. Maybe I'm missing something?
Thanks!
Edit:
for those with eval() solutions: thanks, but it is out of the question
for those with get _class _vars() solutions: thanks, but it seems it returns "the default properties of the given class" (php.net), and yes, I would like that value to be changable (even though it does help me in some of the cases)
If you are using PHP 5.3.0 or greater, you can use the following:
$classname::$$propertyname;
Unfortunately, if you are using a version lower than 5.3.0, you are stuck using eval() (get_class_vars() will not work if the value is dynamic).
$value = eval($classname.'::$'.$propertyname.';');
EDIT: I've just said get_class_vars() wouldn't work if the value is dynamic, but apparently, variable static members are part of "the default properties of a class". You could use the following wrapper:
function get_user_prop($className, $property) {
if(!class_exists($className)) return null;
if(!property_exists($className, $property)) return null;
$vars = get_class_vars($className);
return $vars[$property];
}
class Foo { static $bar = 'Fizz'; }
echo get_user_prop('Foo', 'bar'); // echoes Fizz
Foo::$bar = 'Buzz';
echo get_user_prop('Foo', 'bar'); // echoes Buzz
Unfortunately, if you want to set the value of the variable, you will still need to use eval(), but with some validation in place, it's not so evil.
function set_user_prop($className, $property,$value) {
if(!class_exists($className)) return false;
if(!property_exists($className, $property)) return false;
/* Since I cannot trust the value of $value
* I am putting it in single quotes (I don't
* want its value to be evaled. Now it will
* just be parsed as a variable reference).
*/
eval($className.'::$'.$property.'=$value;');
return true;
}
class Foo { static $bar = 'Fizz'; }
echo get_user_prop('Foo', 'bar'); // echoes Fizz
set_user_prop('Foo', 'bar', 'Buzz');
echo get_user_prop('Foo', 'bar'); // echoes Buzz
set_user_prop() with this validation should be secure. If people start putting random things as $className and $property, it will exit out of the function as it won't be an existing class or property. As of $value, it is never actually parsed as code so whatever they put in there won't affect the script.
I think this is the simplest:
$foo = new ReflectionProperty('myClassName', 'myPropertyName');
print $foo->getValue();
To return a variable value that is set by a Static Variable you need to call:
$static_value = constant($classname.'::'.$propertyname);
Check out the documentation :: PHP Constant Documentation
You should be able to do something like:
eval("echo $classname::$propertyname;");
I just did a quick test and got this to work for me. Not sure if there's a better way or not, but I wasn't able to find one.
'eval' looks so close to 'evil', and I hate using it and/or seeing it in code. With a few ideas from other answers, here's a way to avoid it even if your php isn't 5.3 or higher.
Changed to reflect testing based on a comment.
class A {
static $foo = 'bar';
}
A::$foo = 'baz';
$a = new A;
$class = get_class($a);
$vars = get_class_vars($class);
echo $vars['foo'];
Outputs 'baz'.
One thing I noticed is that you can't set variables which are protected in static classes as the eval() command runs in a scope outside the class. The only thing to get around this would be to implement a static method inside the/every class which runs the eval(). This method could be protected as the call_user_func() [to call the setter method] also runs from inside the class.
Potentially relevant: discussion on late static binding in PHP - When would you need to use late static binding?.
get_class_vars is not same as get_object_vars.
I think get_clas_vars should return the original property values.
Even if for you said eval is out of the question, prior PHP 5.3 the easiest solution is still by using eval:
eval("\$propertyval = $classname::\$propertyname;");
echo $propertyval;
Getting and setting both static and non static properties without using Reflection
Using Reflection works but it is costly
Here is what I use for this purpose,
It works for PHP 5 >= 5.1.0 because I'm using property_exist
function getObjectProperty($object, $property)
{
if (property_exists(get_class($object), $property)) {
return array_key_exists($property, get_object_vars($object))
? $object->{$property}
: $object::$$property;
}
}
function setObjectProperty($object, $property, $value)
{
if (property_exists(get_class($object), $property)) {
array_key_exists($property, get_object_vars($object))
? $object->{$property} = $value
: $object::$$property = $value;
}
}
You can use ReflectionClass:
class foo
{
private static $bar = "something";
}
$class = "foo";
$reflector = new ReflectionClass($class);
$static_vars = $reflector->getStaticProperties();
var_dump($static_vars["bar"]);

Categories