How to modify echo'd variable already called in PHP? - 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.

Related

Why does this example print twice?

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.]

Print a PHP script's echo in another PHP script without include

I have a file, let's call it first.php. It echoes a lot of text. Inside that text I also want to include something another file, second.php echoes. I'd like to do this without including the code from second.php, because there are collisions.
TL;DR I want a PHP script to execute another one, wait for it to print, and then echo whatever it printed.
Tried
echo something
include second script
echo something else
But it doesn't work because of said collisions. The second script only prints a short plain text.
Better example
a.php prints "hello" and "world" and declares $i=1
b.php prints "beautiful" and declares $i=2
I want to print "hello beautiful world" and have $i=1
You could run the second script through the CLI with shell_exec
echo something
shell_exec("php second.php");
echo something else
However, this won't work if the second script needs to access variables that are set by the webserver, like $_GET or $_SERVER. If you need to pass certain variables along, you can send them as command line arguments. But the second script will then have to access them using $argv, not $_GET.
shell_exec("php second.php " . escapeshellarg($_GET['id']));
second.php can get the ID from $argv[1].
Imo you should really solve the actual problem by not re-using variables which are sharing scope. If you cannot do that it means you are putting too much in the current scope. However if you really want to do it you could wrap it in a function (which has its own scope).
<?php
$i = 1;
echo 'hello';
echo call_user_func(function() {
// in your case this would be a include statement
$i = 2;
return 'beautiful';
});
echo 'world';
var_dump($i); // 1
If you actually need to "import" variables from the current scope create a closure instead:
<?php
$i = 1;
echo 'hello';
echo call_user_func(function() use ($theVariable) {
// in your case this would be a include statement
$i = 2;
return 'beautiful';
});
echo 'world';
var_dump($i); // 1
You could include the second file in a function. Functions have their own variable scopes. So, variables of the second file can not overwrite variables with the same name of the first script file.
$myvar = 1;
include 'first.php';
callSecond ();
echo $myvar;
function callSecond () {
include 'second.php';
}
echo $myvar would give 1, even when 'second.php' assigns $myvar = 2;

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};
?>

Weird PHP Introspection: Get original variable NAMES from function call?

I have a strange question that's probably not possible, but it's worth asking in case there are any PHP internals nerds who know a way to do it. Is there any way to get the variable name from a function call within PHP? It'd be easier to give an example:
function fn($argument) {
echo SOME_MAGIC_FUNCTION();
}
$var1 = "foo";
$var2 = "bar";
fn($var1); // outputs "$var1", not "foo"
fn($var2); // outputs "$var2", not "bar"
Before you say it - yes, I know this would be a terrible idea with no use in production code. However, I'm migrating some old code to new code, and this would allow me to very easily auto-generate the replacement code. Thanks!
debug_backtrace() returns information about the current call stack, including the file and line number of the call to the current function. You could read the current script and parse the line containing the call to find out the variable names of the arguments.
A test script with debug_backtrace:
<?php
function getFirstArgName() {
$calls=debug_backtrace();
$nearest_call=$calls[1];
$lines=explode("\n", file_get_contents($nearest_call["file"]));
$calling_code=$lines[$nearest_call["line"]-1];
$regex="/".$nearest_call["function"]."\\(([^\\)]+)\\)/";
preg_match_all($regex, $calling_code, $matches);
$args=preg_split("/\\s*,\\s*/", $matches[1][0]);
return $args[0];
}
function fn($argument) {
echo getFirstArgName();
}
$var1 = "foo";
$var2 = "bar";
fn($var1);
fn($var2);
?>
Output:
$var1$var2

Using a Superglobal as a Default Function Parameter in PHP

There are multiple ways I can conceive for achieving the following functionality; however I am hoping for a super elegant solution. Can I use a PHP superglobal variable as the default value for a user defined function parameter?
Example:
function test1($foo=$_SERVER['PATH']) {
echo $foo;
}
The above code spits out an error. Like I said I know that I can achieve the same thing using the following code (but the above code is more attractive):
function test2($foo) {
if (!isset($foo)) $foo = $_SERVER['PATH'];
echo $foo;
}
Thanks for the help!
I would recommend passing in the variable, but if you want to use a global one, you can do this
function test2() {
global $foo;
...
}
at the top of your function and set the value somewhere else, or go with your second idea - but you need to specify a default value in the function parameter to make it optional.
function test2($foo='') {
if (empty($foo)) $foo = $_SERVER['PATH'];
echo $foo;
}
Another way to work with variables from outside your function is to pass them in by reference. This passes in a reference to the original variable, not a copy, so any changes you make inside the function will affect the original variable value outside of the scope of the function as well.
$foo = 'bar';
function test2(&$foo) {
echo $foo; // this will output "bar"
}

Categories