Simple question:
I've been exploring open source code and saw the following statement:
$this->{$worker}
What is the meaning of enclosing brackets around, and what is the difference between this and:
$this->worker
Curly braces are used for string or variable interpolation in PHP.
Something like
$worker = 'foo';
$this->{$worker} = 'bar';
that means
$this->foo = 'bar';
When is useful
class RandomName
{
protected $foo;
protected $bar;
protected $foo_bar;
$properties_array = array('foo', 'bar', 'foo_bar');
if (in_array($property, $properties_array)) {
$this->{$property} = //some value
}
}
The first one actually uses the value of the variable $worker, while the latter uses the Expression / word worker to target the object property.
The first example is using a variable as the attribute name. The second example is using a non-variable name for an attribute on your class.
Related
How can i reference a class property knowing only a string?
class Foo
{
public $bar;
public function TestFoobar()
{
$this->foobar('bar');
}
public function foobar($string)
{
echo $this->$$string; //doesn't work
}
}
what is the correct way to eval the string?
You only need to use one $ when referencing an object's member variable using a string variable.
echo $this->$string;
If you want to use a property value for obtaining the name of a property, you need to use "{" brackets:
$this->{$this->myvar} = $value;
Even if they're objects, they work:
$this->{$this->myobjname}->somemethod();
As the others have mentioned, $this->$string should do the trick.
However, this
$this->$$string;
will actually evaluate string, and evaluate again the result of that.
$foo = 'bar';
$bar = 'foobar';
echo $$foo; //-> $'bar' -> 'foobar'
you were very close. you just added 1 extra $ sign.
public function foobar($string)
{
echo $this->$string; //will work
}
echo $this->$string; //should work
You only need $$string when accessing a local variable having only its name stored in a string. Since normally in a class you access it like $obj->property, you only need to add one $.
To remember the exact syntax, take in mind that you use a $ more than you normally use. As you use $object->property to access an object property, then the dynamic access is done with $object->$property_name.
I would like to handle functions references and lambda in consistent way in PHP, but I have trouble when assigning a function reference to a variable.
function foo()
{
echo "hi\n";
}
$here = function() { echo "hello\n"; };
$here = foo;
The last line gives me a warning. I could use string literal, but I am afraid of two things -- using it later as string by mistake, and problems with name resolution when passing such string-reference over namespace boundaries.
Is there any way to grab that reference without using strings?
One way is to create it as an anonymous function:
$foo = function()
{
echo "hi\n";
};
$foo();
The following code uses the string "rand" stored in the property $prop to call rand() as a variable function, by using $function as a temporary local variable.
class C
{
private $prop = "rand";
public function execute()
{
$function = $this->prop;
echo $function();
}
}
$c = new C();
$c->execute();
This works, but I need to call the variable function stored in $this->prop using only one statement and avoiding the temporary variable.
I had no luck with
echo $this->prop();
because it actually calls the method prop() which does not exist and in any case it is not what I want to do.
As $this->prop is actually a string, I tried the following, but it produces a syntax error:
echo ($this->prop)();
I also tried
echo call_user_func($this->prop);
Although it does the work, it is not an option for me because it is not a variable function.
It seems like variable functions only work using local variables as function name.
Does anybody know a way to call directly a variable function using a class property as function name, avoiding the local temporary variable and the usage of call_user_func()?
Edit:
I understand your perplexity, therefore I'm going to explain what's wrong with using call_user_func.
I'm just exploring the opportunities offered by variable functions, which seems to be less then those offered by variable variables.
Let's try using variable variables feature it its simplest form.
Suppose we have a function f() which returns the string "something"
function f() {
return "something";
}
then a class property containing the string "something"
$this->prop = "something";
$something is a local variable
$something = "I am a local variable";
Then all the following statements will work:
$r = ${"something"};
$r = ${$this->prop};
$r = ${f()};
My personal conclusion: No matter how the string "something" has been obtained; just surround it with braces {} and prepend a dollar symbol $ to consider it a variable.
Pretty flessibe.
Let's try the same for variable functions
Now we have a function f() which returns the string "rand"
function f() {
return "rand";
}
then a class property containing the string "rand"
$this->prop = "rand";
Variable functions on the other hand, does not allow a string followed by parenthesis () to be considered a function call.
$r = "rand"(); // Produces a syntax error, unexpected '()' after a string
$r = $this->prop(); // Calls the 'prop()' method, which does not exist
$r = f()(); // Again a syntax error, unexpected '()' after the function f()
I have to conclude that variable functions always require a local variable to be run :(
You need to implement a magic __call method, like this:
class C
{
private $prop = "execute";
public function __call($method, $args)
{
if($method == "prop") // just for this prop name
{
if(method_exists($this, $this->prop))
return call_user_func_array([$this, $this->prop], $args);
}
}
public function execute ($s){
echo '>>'.$s.'<<';
}
}
$c = new C;
$c->prop(123);
It certainly does feel like a glaring omission in PHP's syntax. (Although taken literally I guess they are variable functions, not property functions!?) I would have perhaps expected the following "curly brace" syntax to work, but it doesn't, Parse error: syntax error, unexpected '{' in ....
echo {$this->prop}();
However, there are significant benefits to using variable function syntax over other methods. Variable functions are quicker than call_user_func() / call_user_func_array() and natively support pass-by-reference, rather than the "special-case" call-time pass-by-reference with call_user_func_array() (which is deprecated in all other cases).
An alternative to the __call magic method (above), which is going to be relatively slow, is to simply use a wrapper method, to which you pass the function/method name and use variable functions inside that wrapper method.
In its most simplest form:
function callUserFunc($callable) {
return $callable();
}
Because of the performance benefit (over using call_user_func_array()) several frameworks implement a similar "helper" method, allowing for a variable number of arguments. This other question/answer goes into more depth and covers some performance benchmarks: Calling a function with explicit parameters vs. call_user_func_array()
In case anyone is wondering, since PHP 7 we get immedietally invoked function expressions.
While this particular case is undocumented it actually works in the following example:
class Test {
private $func = "strtolower";
public function testFunc() {
return ($this->func)("ALPHABET");
}
}
$t = new Test();
echo $t->testFunc(); //echoes alphabet in PHP 7+ error in anything below
This can be seen in https://3v4l.org/JiuIF
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
How can i reference a class property knowing only a string?
class Foo
{
public $bar;
public function TestFoobar()
{
$this->foobar('bar');
}
public function foobar($string)
{
echo $this->$$string; //doesn't work
}
}
what is the correct way to eval the string?
You only need to use one $ when referencing an object's member variable using a string variable.
echo $this->$string;
If you want to use a property value for obtaining the name of a property, you need to use "{" brackets:
$this->{$this->myvar} = $value;
Even if they're objects, they work:
$this->{$this->myobjname}->somemethod();
As the others have mentioned, $this->$string should do the trick.
However, this
$this->$$string;
will actually evaluate string, and evaluate again the result of that.
$foo = 'bar';
$bar = 'foobar';
echo $$foo; //-> $'bar' -> 'foobar'
you were very close. you just added 1 extra $ sign.
public function foobar($string)
{
echo $this->$string; //will work
}
echo $this->$string; //should work
You only need $$string when accessing a local variable having only its name stored in a string. Since normally in a class you access it like $obj->property, you only need to add one $.
To remember the exact syntax, take in mind that you use a $ more than you normally use. As you use $object->property to access an object property, then the dynamic access is done with $object->$property_name.