It know it can be done with get_class($variable).
The problem is that my $object is actually a string containing the variable name.
so:
$object = new MyClass();
$var = '$object';
$class = get_class($var); // obviously fails
I can't use get_class($object), because I don't have direct access to that variable (I'm producing the $var string from parsing a PHP expression using token_get_all())
I tried using eval(sprintf('return get_class(%s);', $var)), but it doesn't work because the variable appear undefined from eval's scope :(
Is there a way to do this?
I need to know the class in order to pass it to ReflectionMethod, so I can get information about a method (the next element in the PHP expression).
NVM: I'm pretty sure it is not possible. Sorry for asking:)
you can do
$var = new $object();
Try using variable variables: http://php.net/manual/en/language.variables.variable.php
Something like:
$var = 'object';
$class = get_class( $$var );
you can do the following
$ref = ltrim($var, '$');
get_class($ref);
Related
Running PHP 5.4, so I wasn't expecting this, but I'm encountering the following error:
Parse error: syntax error, unexpected '::' (T_PAAMAYIM_NEKUDOTAYIM)
Assume you have a variable of stdClass setup as follows:
$this->variable = new stdClass();
$this->variable->other = array('class' => 'helloworld');
Now, assume you want to access a static method of class helloworld:
// Standard call
$x = helloworld::my_static_method();
// Call with variable class name
$x = $this->variable->other['class']::my_static_method();
When calling the above using the variable class name, I receive the parsing error. What's odd, is that if I do the following, no error is presented:
$class = $this->variable->other['class'];
$x = $class::my_static_method();
To me this seems very odd, can anyone think of a reason why the class name isn't resolving correctly when using the first example versus the second?
can anyone think of a reason why the class name isn't resolving correctly when using the first example versus the second?
The PHP parser does not support such a syntax, and that's merely all. This is because the parser has grown historically. I can't give more reason than that.
It will be that with PHP 7 you can see some changes on these syntax details working more into your expected direction Uniform Variable Syntax:
($variable->other['class'])::my_static_method();
But until then, you can go around that with the help of call_user_func:
call_user_func([$variable->other['class'], 'my_static_method']);
call_user_func($variable->other['class'] . '::my_static_method');
Or as you wrote your own, by creating a variable:
$class = $variable->other['class'];
$class::my_static_method();
Or even a variable that looks like something different:
${(int)!${0}=$variable->other['class']}::my_static_method();
Related Material:
Interpolation (double quoted string) of Associative Arrays in PHP
This doesn't work ($this->variable->other['class']::my_static_method()) as it's essentially using a string as the class name directly. It works when you assign it to a variable first, as it's then being evaluated out as the class name instead.
You can also look into using ReflectionMethod invocation in order to call the method, in which case you wouldn't have to store the class name in a variable before using it. Here's the docs on that: http://php.net/manual/en/class.reflectionmethod.php and on the invoke method (you pass in NULL to indicate a static method) http://php.net/manual/en/reflectionmethod.invoke.php
Here are a couple examples of ways to invoke your function:
class helloworld{
public static function my_static_method($i = 0){
echo "Here: ".$i;
}
}
class Foo{
private $variable;
public function __construct(){
//Create a new class
$this->variable = new stdClass();
//Create a new property of the class, storing an array
$this->variable->other = array('class' => 'helloworld');
//Call function statically
$x = helloworld::my_static_method(1); //Outputs: "Here: 1"
//Store class name in a variable before use
$class = $this->variable->other['class'];
$y = $class::my_static_method(2); //Outputs: "Here: 2"
//Using a ReflectionMethod, you can call the function this way, too
$z = new ReflectionMethod($this->variable->other['class'], 'my_static_method');
$z->invoke(null, 3); //Outputs: "Here: 3"
}
}
//Instantiate new Foo class
new Foo();
I was reading source of OpenCart and I ran into such expression below. Could someone explain it to me:
$quote = $this->{'model_shipping_' . $result['code']}->getQuote($shipping_address);
In the statement, there is a weird code part that is
$this->{'model_shipping_' . $result['code']}
which has {} and I wonder what that is? It looks an object to me but I am not really sure.
Curly braces are used to denote string or variable interpolation in PHP. It allows you to create 'variable functions', which can allow you to call a function without explicitly knowing what it actually is.
Using this, you can create a property on an object almost like you would an array:
$property_name = 'foo';
$object->{$property_name} = 'bar';
// same as $object->foo = 'bar';
Or you can call one of a set of methods, if you have some sort of REST API class:
$allowed_methods = ('get', 'post', 'put', 'delete');
$method = strtolower($_SERVER['REQUEST_METHOD']); // eg, 'POST'
if (in_array($method, $allowed_methods)) {
return $this->{$method}();
// return $this->post();
}
It's also used in strings to more easily identify interpolation, if you want to:
$hello = 'Hello';
$result = "{$hello} world";
Of course these are simplifications. The purpose of your example code is to run one of a number of functions depending on the value of $result['code'].
The name of the property is computed during runtime from two strings
Say, $result['code'] is 'abc', the accessed property will be
$this->model_shipping_abc
This is also helpful, if you have weird characters in your property or method names.
Otherwise there would be no way to distinguish between the following:
class A {
public $f = 'f';
public $func = 'uiae';
}
$a = new A();
echo $a->f . 'unc'; // "func"
echo $a->{'f' . 'unc'}; // "uiae"
Curly braces are used to explicitly specify the end of a variable
name.
https://stackoverflow.com/a/1147942/680578
http://php.net/manual/en/language.types.string.php#language.types.string.parsing.complex
$this->property = 'SomeClass';
$x = new $this->property(); // works
$x = $this->property::create(); // fails (parse error)
Is this a bug in PHP?
Can a static method be called using the property, without assigning the value to a new variable, and using that variable instead?
Use call_user_func
$x = call_user_func(array($this->property, 'create'));
It's been entered as a bug for a few months and is still in Open status, so I'm gonna go with yes.
https://bugs.php.net/bug.php?id=61397
Similarly,
https://bugs.php.net/bug.php?id=54095
It it possible to call a class and method from strings?
Something like:
// $_REQUEST['var'] = 'House-Kitchen';
$var = explode('-',$_REQUEST['var']);
echo $var[0]->$var[1];
Yes. its possible. If $var[0] is the name of class then following will work.
call_user_func(array($var[0], $var[1]));
If $var[0] is the name of class instance then following will work.
call_user_func(array(get_class(${$var[0]}), $var[1]));
Links:
call_user_func
get_class
The better way is to try.
I did try :
$House = new stdClass();
$House->Kitchen = "visible result";
$_REQUEST['var'] = 'House-Kitchen';
$var = explode('-',$_REQUEST['var']);
echo $$var[0]->$var[1];
It works. Be careful : you need to use double $ for the first element (to use variable with $var[0] name).
And be very careful : it's a high security breach (you allow everyone to call methods on current defined class).
I have a function called check_nickname()
And I want to write something like this
$ttt='nickname';
check_.$ttt();
How can I do it correct ?
I would advise against that.
this will produce unmaintainable and undebuggable code.
I'd make one function which does all the verifications.
Create a variable that holds the function name, and apply parentheses to it:
$ttt='nickname';
$funcname = 'check_'.$ttt;
$funcname();
You would need to create another variable, such as $a = "check_".$ttt;, then call $a();
$ttt = 'nickname';
$your_function = 'check_' . $ttt;
$your_function();