Why does this example print twice? - php

When reading php documentation on variable passing, it seems this function is supposed to print
i am bar
i am bar
The documentation says; "When a string is specified in double quotes or with heredoc, variables are parsed within it."
function
<?php
class foo {
var $bar = 'I am bar.';
}
$foo = new foo();
$bar = 'bar';
$baz = array('foo', 'bar', 'baz', 'quux');
echo "{$foo->$bar}\n";
echo "{$foo->{$baz[1]}}\n";
?>
Can someone help me understand
echo "{$foo->{$baz[1]}}\n";
Why does this also print 'i am bar'? And why is $bar = 'bar' declared and what's its significance? When it's deleted the file only prints i am bar once but I am not sure why since the second echo statement seems like it should be printing the $baz variable array?
https://www.php.net/manual/en/language.types.string.php#language.types.string.parsing

you declare
$foo = new foo();
and then the $foo->bar is 'I am bar.'
So
the first time 'I am bar.' is obvious.
the second time 'I am bar.' is a trick of php variable.
PHP will translate the following to
echo "{$foo->{$baz[1]}}\n";
==>
echo "{$foo->{$bar}}\n";
==>
echo "{$foo->bar}\n";
==>
echo "I am bar.";
That's why you got two line [I am bar.]

Related

What's the difference in printing a value contained in an array key and printing a value contained in an array key of object property?

Consider below code snippets and their respective outputs :
Code snippet 1 :
<?php
$juices = array("apple", "orange", "koolaid1" => "purple");
echo "He drank some $juices[0] juice.".PHP_EOL;
echo "He drank some $juices[1] juice.".PHP_EOL;
class people {
public $john = "John Smith";
}
$people = new people();
echo "$people->john drank some $juices[0] juice.".PHP_EOL;
?>
Output of Code snippet 1 :
He drank some apple juice.
He drank some orange juice.
John Smith drank some apple juice.
Code snippet 2 :
<?php
class foo {
public $foo;
public $bar;
function __construct() {
$this->foo = 'Foo';
$this->bar = array('Bar1', 'Bar2', 'Bar3');
}
}
$foo = new foo();
$name = 'MyName';
echo "My name is \"$name\". I am printing some $foo->foo.
Now, I am printing some $foo->bar[1].";
?>
Output of Code Snippet 2 :
Notice: Array to string conversion in hello.php on line 16
My name is "MyName". I am printing some Foo. Now, I am printing some Array[1].
If you look closely you can see that in first program I'm able to print a values contained in keys of an array viz. $juices[0], $juices[1] but in the second program I'm getting a Notice when I try to print a value contained in an array key and the array is an object property.
I'm not understanding why I'm getting this Array to String conversion notice for second program.
Someone, please clear the differences to me with good explanation and help me in printing the array key value in second program.
PHP can correctly determine the intended element and object that you are referencing in the first code block. However, in the second, PHP wants to be crystal clear on how to access the element of the object. PHP bends over backward in other cases to make coding simple (type-jugging and other such features), but in this case, it needs to reign us in and demand clarity in the script.
You only need to improve your syntax.
Use curly brackets to fix it up. (Demo)
<?php
class foo {
public $foo;
public $bar;
function __construct() {
$this->foo = 'Foo';
$this->bar = array('Bar1', 'Bar2', 'Bar3');
}
}
$foo = new foo();
$name = 'MyName';
echo "My name is \"$name\". I am printing some $foo->foo.
Now, I am printing some {$foo->bar[1]}.";
?>
A similar demo from the manual (though this one is using nowdoc, not double quotes -- still it is wrapping in {}):

Variable Variables - errors and validity

I've been studying PHP for a little while now, and I ran across variable manipulation functionality officially called Variable Variables. The basic syntax is:
$foo = 'bar';
$$foo = 'foo2';
The result of these two statements is $foo equals bar, and a new variable, $bar equals foo2.
I expect that if variable $foo contained a number, this would throw some sort of error. What happens if the value of $foo is originally set to an invalid variable name? What error will be thrown?
No error will be thrown.
The PHP Docs on Variables states that variables must match the following regex:
[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*
However this rule is only enforced by the parser. PHP supports variables named anything, the parser just enforces certain naming conventions.
You can check it yourself:
$foo = '1';
$$foo = 'baz';
print_r(get_defined_vars());
/*
Prints:
Array
(
...
[foo] => 1
[1] => baz
)
*/
You can try it with this simple script:
<?php
$foo='1';
$$foo='hello world';
echo $$foo;
?>
and this one:
<?php
$foo='1';
$$foo='hello world';
echo $1;
?>
Basically, no error will be thrown if you do this. However, you must access the new variable as $$foo, not as $1. If you run both scripts, the first one will say "hello world" and the second will give an error in the log file.
EDIT: Thanks #Fabrício Matté for saying that you can access it like this:
<?php
$foo='1';
$$foo='hello world';
echo ${1};
?>

PHP Variable object properties

I understand the concept of variable variables in PHP.
According to my understanding of variable variables in PHP the following code:
$foo = 'hello';
$$foo = 'world';
echo $foo . ' ' . $hello;
Will generate the output as:
Hello World
But I am finding it difficult to understand the case of variable object properties
Say I have a class called foo with a single property as follows:
class foo {
var $r = 'I am r.';
}
Now, creating the instance of the class foo and using the concept of variable variables the following code:
$foo = new foo();
$bar = 'r';
echo $foo->$bar;
will output:
I am r.
Up till everything is fine, but when I include a property having an array value it gets messed up for me.
Say for example I add another property with array value to the class foo and now the class looks like:
class foo {
var $arr = array('I am A.', 'I am B.', 'I am C.');
var $r = 'I am r.';
}
Now When I create the instance of the class foo and try to read the property $arr[1] as follows:
$arr = 'arr';
echo $foo->$arr[1];
Which outputs:
I am r.
and the output looks weird to me. I mean how does $foo->$arr[1] resolves to the propery $r in the class foo ?
Shouldn't doing $foo->$arr resolve into $foo->arr[1] (Note: There is no dollar sign) giving the output:
I am B.
How does this happen?
I am aware that doing $foor{$arr}[1] outputs "I am B."
My question is why does $foo->$arr doesn't resolve into $foo->arr ? Given that the variable $arr is holding the value 'arr' ?
A note to admins/supervisors: This question is not a duplicate; I have tried searching for the similar questions but none of it answered what I need to know.
class foo {
var $arr = array('I am A.', 'I am B.', 'I am C.');
var $r = 'I am r.';
}
$foo = new foo;
$arr = 'arr';
echo $foo->$arr[1];
It's order of precedence that's biting you here. The last line could be re-written as
echo $foo->{$arr[1]};
Since strings are arrays starting with index 0, $arr[1] references the second character in 'arr', i.e. 'r', and results in printing the string 'I am r.'.
To get the results you're expecting, you need to explicitly tell PHP which part of the expression is meant as the variable name, because by default it greedily takes pretty much everything. Replacing the last line with this will get the output you expect:
echo $foo->{$arr}[1];
This will evaluate $arr to its full string 'arr', and then use that as the label to the class member $arr in foo; the index will then grab the second entry in that array, 'I am B.'.

How to modify echo'd variable already called in PHP?

In the following code, is there a way to modify the contents of a variable after it has been called? In this really simple (and pointless) example, when $foo is called, I wish for it to echo 'baryay', not 'bar' WITHOUT needing to call changefoo() before hand. changefoo must be called after.
<?php
changefoo(){
global $foo,
$foo .= 'yay';
}
$foo = 'bar';
echo $foo;
changefoo();
?>
Awaiting general coding method harassment and suggestions.
No. Once you've written something to the output, you can hardly go back and change it. You need to restructure your flow to match your needs.
Think of it like an actual printer. If you print something on a piece of paper, even if the page is not done printing yet, you can't go back and modify what you printed.
If it's the result of an echo statement, it's no longer a variable. You can alter your scripts output with regular output buffering functions, no matter where it comes from:
<?php
function changefoo(){
global $foo;
$foo = 'blah';
}
ob_start();
$foo = 'bar';
echo $foo;
changefoo();
ob_end_clean();
echo $foo;
?>
I do not believe that is possible.
Also try not to use globals. just pass the variable in:
function changefoo(&$foo){
$foo .= 'yay';
}
$foo = 'bar';
changefoo($foo);
echo $foo; //baryay
No, once it is echoed, you couldn't change what is displayed on screen without using javascript/jquery. If you want it to echo "baryay", you would need to write:
echo $foo."yay";
I know this is old, but here's an idea.
This will echo "bar" then change it to "blah" after 5 secconds
<?php
ob_start(); // output buffering on
$foo = 'bar'; // set $foo initially
echo "<span id='foo'>$foo</div>"; // echo $foo along with some HTML needed later
sleep(5); // wait 5 seconds for demonstration purposes
$foo = 'blah'; // set $foo again
ob_end_clean(); // output buffering off
echo "<script>document.getElementById('foo').innerHTML = $foo;</script>"; // outputs JS that changes the DOM innerHTML.

PHP Syntax ${"{$type}_method"}

I've been reading an PHP5 book, and the author commonly used this syntax
${"{$something}_somethingelse"};
I have no idea what that means. Does it dynamically generate a variable name?
Someone help me out?
It is a language feature called Variable variables.
Consider the following piece of code:
$a = 'hello';
This is pretty straight forward. It creates the variable $a and sets its value to 'hello'.
Let's move on with:
$$a = 'world';
${$a} = 'world';
Basically, since $a = 'hello', those two statement are the equivalent of doing:
$hello = 'world';
So the following:
echo "$a ${$a}";
Is the equivalent of doing:
echo "$a $hello";
Braces { }
The braces are used to prevent ambiguity problems from occurring. Consider the following:
$$a[1] = 'hello world';
Do you want to assign a variable named after the value of $a[1] or do you want to assign the index 1 of the variable named after $a?
For the first choice, you would write it as such:
${$a[1]} = 'hello world';
For the second choice:
${$a}[1] = 'hello world';
Your example
Now, for your example.
Let's consider that:
$something = 'hello';
Using your example as such:
${"{$something}_somethingelse"} = 'php rocks';
Would essentially be equivalent of doing:
$hello_somethingelse = 'php rocks';
They are 'variable variables'. See this.
Brackets allow you to make more advanced variable names. It your Case if $something was equal to test it would be:
${"test_somethingelse"};
Which is just an advanced variable name.
Here is an example.
$test = "test";
${"test_test"} = "test2";
echo $test; // prints test
echo ${"test_test"}; // prints test2
Using Variable Varaibles, as everyone else mentioned, you can create variables based on other variables. So in your case, he was making a variable based on $something's value
$something = "test";
${"{$something}_somethingelse"};
turns into
${"test_somethingelse"};
That will replace the {$something} with the value of $something.
I think the inner curly braces are just for readability and to help when doing $object->property etc.
Because it seems to be also in a variable, that is called a variable variable.
For example,
$foo = 'bar';
$$foo = 7;
echo $bar;
// produces 7;

Categories