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;
Related
I want to set a PHP variable: $custom, that will be used whenever it is defined.
But I want the output of this variable to be dependant of another variable: $v index, which is used inside while, which gets defined only during the while statement.
I don't know if it's possible to do, right now I have the following code, and for the way I defined $custom[3], it doesn't work.
Only $custom[1] and $custom[2] varibables will work, but they take into account only constant values or variable whose values were already set, so this isn't helpful.
Code:
<?php
$product[1]["price"]=10;
$product[2]["price"]=50;
$product[3]["price"]=70;
$custom[1] = 'Static HTML Block';
$custom[2] = 'Past Variable: '. $product[2]["price"] .'';
$custom[3] = 'Future Variable: '. $product[$v]["price"] .''; // I want this kind of definitoin
?>
<HTML>
// the following part will be used within an include, and shouldn't be modified ///
<?php
$v = 1;
while ($z <= 5) {
?>
<?= $custom[$v] ? $custom[$v] : '$' . $product[$v]["price"] ?>
<?php
$v = $v + 1;
$z = $z + 1;
}
?>
So basically, I want that on the third run (when v=3), that Future Variable: 70 will be the output.
The Rationale:
I want to use the latter code as a constant Include, that will serve as a template for all files. but on occasion, a certain file may require special changes that also require PHP code modification, so I will want to perform them within such specific file, that will affect the original include.
Edit 2:
More Simple example:
<?php
$product[1]["price"]=10;
$product[2]["price"]=50;
$custom[1] = 'I dont modify the PHP code';
$custom[2] = 'I DO mofiy the latter PHP code: '. $product[$v]["price"] .'';
?>
<HTML>
// the following part will be used within an include, and shouldn't be modified ///
<?php $v = 1; while ($v <= 5) { ?>
<?= $custom[$v] ?>
<p>
<?php $v = $v + 1; } ?>
// Expected Output:
//I dont modify the PHP code
//I DO mofiy the latter PHP code: 50
It's a little difficult to tell what you are trying to do, but I think you need to decouple your data from your presentation:
$product[1]['price']=10;
$product[2]['price']=50;
$product[3]['price']=70;
$custom[1] = 'Static HTML Block';
$custom[2] = 'Past Variable: %s';
$custom[3] = 'Future Variable: %s';
$v = 1;
while($z <= 5) {
$price = $product[ $v ]['price'];
printf($custom[ $v ], $price);
$v++;
$z++;
}
In this case, $custom stores the format, but doesn't actually contain the data. You call printf to output the desired format with whatever data you want to pass.
It's not clear to me what you're trying to accomplish, but if I had to guess, you want something known as templates (e.g. Twig), and your question might possibly be a XY problem. If you supply more context maybe someone might be able to help you further.
As to the matter at hand, you cannot define $custom[3] here since $v is not defined yet:
$custom[3] = 'Future Variable: '. $product[$v]["price"] .''; // I want this kind of definitoin
The closest you can get is to use eval (which is rarely recommended), or define a closure, even if it's awkward. Instead of a variable, you define a function:
$custom[3] = function($productData) {
return 'Future Variable: '. $productData["price"] .'';
}
The above you can do in an included file.
Then in the loop you check whether the custom object is a function, and if so, you call it and assign the return value to the reply.
The code below stays the same whatever the include - actually, it even works with the data you have now. Of course, it has to be a little more complicated.
while ($z <= 5) {
// If the $v-th item is customised
if (array_key_exists($v, $custom)) {
// Verify what it is
if (is_callable($custom[$v])) {
// if it's a function, call it.
$reply = $custom[$v]($product);
} else {
$reply = $custom[$v];
}
} else {
// Not customised, just print the price.
$reply = '$' . $product[$v]["price"];
}
print $reply;
Another more "templateish" solution is to define strings and then process them using e.g. preg_replace_callback in order to generate the desired HTML. In this case, too, you need to pass to the templater a fixed variable, such as $product[$v]. You need some kind of 'language' to indicate where you want elements of this fixed variables to be instantiated. Usually, square brackets or curly brackets, often doubled, are used:
$custom[3] = 'Future Variable: {{price}}';
At resolution time, preg_replace_callback may be made to replace {{price}} with the value in $product[$v]['price'], and so on (e.g. {{weight}}, {{description}}...).
(You can also do this server side and populate the HTML page via AJAX using client-side libraries such as Handlebars).
The quick and nasty way to make your own template is to create an array of keys => values and pass it to the where loops as your $custom variable.
While you're in the where(){} loop, use the php function extract to convert the array into $key = 'value' pairs. This is very similar to list without having having to define each variable manually.
http://php.net/manual/en/function.extract.php
Eg.
$data = [
'foo' => 'bar',
];
extract($data);
print $foo; // output: bar
Then after you extract, include your file. Make sure that you wrap this in output buffering mode ob_start() and put it in a function so your local variables can't be overriden.
This is how you make homebrew templating languages.
$var = require_once("target.php");
is that possible to store require_once in variable and execute it late?
I need to place this into function
function foo($path){
if($path !== ""){$path = require_once($path);}
do something first...
$path//than execute require_once
}
The answer is no. When you assign require_once(); to a variable, the variable turns into a boolean with 1 in case the file was included successfully, or 0 otherwise (useless in require_once() as it returns a fatal error if it fails.
So, doing:
<?php
$hello = require_once("./hello.php");
echo $hello; // Prints 1.
?>
Anyway, if you create a php file that returns something, as for example:
FILE: require.php
<?php
$hello = "HELLO";
return $hello;
?>
In this case, the previous example would be different:
<?php
$hello = require_once("./require.php");
echo $hello; // Prints HELLO.
?>
So, you cannot store the function itself to execute it later, but you can store returned values from the required or included files. Anyway, if you explain better what are you using it for, I maybe able to help you better.
I'm learning php on a very basic level and need som assistance.
I want to echo variables from one file to another. I'll try to reproduce:
folder/file1.php
file1.php contains 3 different php scripts:
php $var1 = "Hello"
php $var2 = "Goodbye"
php $var3 = "Nice"
And i want to echo one of the three variables randomly (scrambled) on various pages.
I use this now:
php include 'folder/file1.php'; echo get_($var1);
But it only displays the $var1 text.
How about:
<?php
$var1 = "Hello";
$var2 = "Goodbye";
$var3 = "Nice";
$i = rand(1, 3);
echo ${"var" . $i}
?>
At run time ${"var" . $i} is calculated to be $var1, $var2 or $var3.
Using php rand and dynamically created variable will let you do it. You can just continue to include your other files above this script and ensure the variables are named in a static way as shown above and it will work.
Example: Here (click edit then ideoneit)
put those vars in an array, and randomly select an element from the array:
$myItems = array("hello","goodbye","lovely");
echo $myItems[rand(0,2)];
http://us2.php.net/rand
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
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.