Php, global variables on two external scripts - php

How would I pass a global var in two external scripts?
<div>
<!-- INCLUDEPHP 1.php -->
</div>
<div>
<!-- INCLUDEPHP 2.php -->
</div>
I have tried creating global variables on 1.php and `2.phpp but it didn't work.
1.php:
<?php
global $someVar;
$sql = ...;
$someVar= $db -> sql_query($sql);
?>
2.php:
<?php
global $someVar;
echo "$someVar";
?>
Am I doing something wrong?

I would try including the scripts via PHP:
<div>
<?php require "1.php" ?>
</div>
<div>
<?php require "2.php" ?>
</div>

If both includes are loaded into the same page, and the variables exist already in the global scope, all your functions can access them with the global statement. Since everything is already global, the statement is not required in the global scope, only inside functions. This also permits functions to share variables by casting them onto the global scope.
There are many dangers to this, though, which I'll not pretend to be fully aware of, so one is best advised to make prudent use of the global scope in large complex applications as they can become very volatile if naming conventions are relaxed.
Basically, we're looking at,
function arrow() { global $a; $a = "arrow"; return $a; }
function sky() { global $b; $b = "sky"; return $b; }
echo "I shot an " . arrow() . " into the " . sky() . ".";
echo "I shot an $a into the $b.";
which is child's play, it demonstrates how exposed the variables are, sitting out there with no protection. Now another function can come along and blow the whole thing apart:
function whammo() { global $a, $b; $c = $a; $a = $b; $b = $c;}
echo "I shot an " . arrow() . " into the " . sky() . ".";
whammo();
echo "I shot an $a into the $b.";
See what I mean?
Your solution probably lies in a closure of some sort, wherein all the functions are contained that need this 'global'. It will be much better protected.

Related

Register/create a named function programatically in PHP

Is it possible to programatically register/create a named function in PHP, inside the global scope?
This is possible with create_function (before PHP 7+) and nowadays it's possible with anonymous/lambda functions, but then again you either let them be invoked or you assign them to a variable or an object property, then just invoke them with () at the end.
What I'm interested if it's anyhow possible to add a new named function in a scope which does not have to be assigned to a variable and accessed with $functionName?
Some solution what I'm looking for is:
create_named_function('fullname', function($firstname, $lastname) {
return $firstname . ' ' . $lastname;
});
Then I'd have it accessible like fullname(params...).
Here example with eval:
<?php
$functionName = 'foo';
$f = '
function ' . $functionName . '($a) {
var_dump($a);
}
';
// Finger crossed!)))
eval($f);
// Now you have function "foo" in your global scope!)
$functionName('bar');
// It will print
// string(3) "bar"
But you have to have clear vision what are you really doing here... because it's really tricky place...
Not sure if it should be encouraged to do this - it stops all sort of useful things being able to check code and code completion in IDE's.
BUT...
<?php
error_reporting(E_ALL);
ini_set('display_errors', 1);
$body = <<< 'FN'
<?php
function fullname($firstname, $lastname) {
return $firstname . ' ' . $lastname;
}
FN;
file_put_contents("func.php", $body);
require "func.php";
echo fullname("Joe", "Bloggs");
The first part creates an include file with the required code (note the use of Nowdoc string, which allows the inclusion of variables without them being substituted). This could be any form of code generation.

Undefined variable after wrapped include in PHP

I'm using PHP for web development. I'm using the following function to wrap the include of a view:
<?php
function render($templateFile) {
$templateDir = 'views/';
if (file_exists($templateDir . $templateFile)) {
include $templateDir . $templateFile;
} else {
throw new Exception("Template '{$templateFile}' couldn't be found " .
"in '{$templateDir}'");
}
}
?>
Although this seems right to me, there is a really unexpected behavior: when I define a variable to something (e.g. an array) and use render for including a view that uses that variable, I get an undefined variable error. But when I explicitely use include there is no error at all and things are just fine.
This is the script that calls render:
<?php
include 'lib/render.php'; // Includes the function above.
$names = array('Trevor', 'Michael', 'Franklin');
render('names.html'); // Error, but "include 'views/names.html'" works fine.
?>
And this is the file that uses the $names variable:
<html>
<head>
<title>Names</title>
</head>
<body>
<ol>
<?php foreach ($names as $name): ?>
<li><?php echo $name; ?></li>
<?php endforeach; ?>
</ol>
</body>
</html>
Help will be very much appreciated.
This is from the PHP documentation on the include function (c.f. http://us1.php.net/manual/en/function.include.php):
When a file is included, the code it contains inherits the variable
scope of the line on which the include occurs. Any variables available
at that line in the calling file will be available within the called
file, from that point forward. However, all functions and classes
defined in the included file have the global scope.
And also:
If the include occurs inside a function within the calling file, then
all of the code contained in the called file will behave as though it
had been defined inside that function. So, it will follow the variable
scope of that function.
So, if your render function can't access $names, then neither can your included file.
A possible solution would be to pass the parameters you want to be able to access in your view template, to your render function. So, something like this:
function render($templateFile, $params=array()) {
$templateDir = 'views/';
if (file_exists($templateDir . $templateFile)) {
include $templateDir . $templateFile;
} else {
throw new Exception("Template '{$templateFile}' couldn't be found " .
"in '{$templateDir}'");
}
}
Then, pass them like this:
$names = array('Trevor', 'Michael', 'Franklin');
render('names.html', array("names" => $names));
And use them in your view template like this:
<html>
<head>
<title>Names</title>
</head>
<body>
<ol>
<?php foreach ($params['names'] as $name): ?>
<li><?php echo $name; ?></li>
<?php endforeach; ?>
</ol>
</body>
</html>
There are probably better solutions to this, like putting your render function into a View class. Then you can call the View class function from inside your template file, and access parameters that way instead of just assuming there will be a $params variable in the view templates scope. But, this is the simplest solution.
The problem is, when you include the file directly using include 'views/names.html' the variable $name remains in the same files scope. Hence, it works. But when the include is done through the function, the varibale $name remains out of scope inside the function. So it doesn't work. For example, declare $names as global inside the function and it will work.
If you update the function like below you will see $names variable works.
function render($templateFile) {
global $names; // declares the global $names variable to use in the included files
$templateDir = 'views/';
if (file_exists($templateDir . $templateFile)) {
include $templateDir . $templateFile;
} else {
throw new Exception("Template '{$templateFile}' couldn't be found " .
"in '{$templateDir}'");
}
}

PHP require/include file

I have the following program Structure:
Root directory:-----index.php
|-------TPL directory
|-------------header.php
|-------------index.php
|-------------footer.php
php file loading structure:
Root directory:index.php ----require/include--->tpl:index.php
|----require/include-->header.php
|----require/include-->footer.php
Root index.php :
<?php
function get_header(){
require('./tpl/header.php');
}
function get_footer(){
require('./tpl/footer.php');
}
$a = "I am a variable";
require('./tpl/index.php');
TPL:index.php:
<?php
get_header();//when I change require('./tpl/header.php'); variable $a can work!!
echo '<br />';
echo 'I am tpl index.php';
echo $a;
echo '<br />';
get_footer();//when I change require('./tpl/footer.php'); variable $a can work!!
TPL:header.php:
<?php
echo 'I am header.php';
echo $a;//can not echo $a variable
echo '<br/>';
TPL:footer.php:
<?php
echo '<br />';
echo $a;//can not echo $a variable
echo 'I am footer';
For some reason when I used function to require header.php and footer.php my variable $a doesn't get echoed. It works fine if I use header.php or footer.php on its own. I do not understand what the problem is. What do you think is the issue here?
Your issue is probably just scope of a function does not automatically include global variables. Try setting $a to global like global $a;, example below for your get_header() function:
function get_header(){
global $a; // Sets $a to global scope
require('./tpl/header.php');
}
Using the include inside a function includes the code directly in that function. Therefore the variable is a locally in that function accessable variable - it is not set outside the function.
If you require/include without a function $a becomes a global variable.
make your variable As Global
global $YourVar;

What issue(s) does include_once or require_once solve?

From the php manual
Include_once may help avoid problems such as function redefinitions, variable value reassignments, etc.
Ok, so include_once solves issues with function redefinitions, variable value reassignments, etc. but why are they an issue in the first place ?
I'm trying to understand what kind of risks are involved in redefining functions or reassigning variable values except for a decline in performance due to additional input/output and processing ?
Is it because php parser gets confused which version of function to load/use or is the original version of the function lost once redefined? What else and what about variable reassignments?
I do understand where to use include vs include_once.
Imagine the following include file, hello.php:
function hello()
{
return 'Hello World';
}
$a = 0;
Now imagine the following file, index.php:
include 'hello.php';
$a = 1;
hello();
include 'hello.php';
hello();
echo $a; // $a = 0, not 1
Your code would now have a fatal error, since the function has been defined twice. Using include_once would avert this, since it would only include hello.php once. Also, to do with variable value reassignment, $a (should the code compile) would be reset to 0.
From the comments, please consider this a side answer - If you're looking for something where resetting a set of variables many times was required, I'd look to use a class for this with a method like Reset, you can even make it static if you didn't want to have to instantiate it, like so:
public class MyVariables
{
public static $MyVariable = "Hello";
public static $AnotherVariable = 5;
public static function Reset()
{
self::$MyVariable = "Hello";
self::$AnotherVariable = 5;
}
}
Usage like:
MyVariables::$MyVariable = "Goodbye";
MyVariables::Reset();
echo MyVariables::$MyVariable; // Hello
Let's say you have an include script vars.inc.php:
<?php
$firstname = 'Mike';
$lastname = 'Smith';
?>
And then you have a script script.php:
<?php
echo "$firstname $lastname"; // no output
include('vars.inc.php');
echo "$firstname $lastname"; // Mike Smith
$firstname = "Tim";
$lastname = "Young";
echo "$firstname $lastname"; // Tim Young
include('vars.inc.php');
echo "$firstname $lastname"; // Mike Smith
?>
What happens is that if you modify your vars in code exection and then you include once again the file defining them, you are changing their content. include_once will ensure that this will never happens throwing an error.
It will stop you loading pages more than once. Typically you'll use this at the top of your pages to bring in your init, function, class files etc.
Especially useful if you are loading pages within pages dynamically.

run function block in context of global namespace in PHP

So the senario is that I want to have a custom function for requiring libraries. Something like:
define('E_ROOT', str_replace('//','/',dirname(__FILE__)));
/* ... */
function e_load($fn, $allowReloading = FALSE) {
$inc = E_ROOT.'/path/here/'.$fn.'.php';
if($allowReloading)
require $inc; // !!!
else
require_once $inc; // !!!
}
The problem being that require and require_once will load the files into the namespace of the function, which doesn't help for libraries of functions, classes, et cetera. So is there a way to do this?
(Something avoiding require and require_once altogether is fine, as long as it doesn't use eval since it's banned on so many hosts.)
Thanks!
Technically include() is meant to act as though you're inserting the text of included script at that point in your PHP. Thus:
includeMe.php:
<?php
$test = "Hello, World!";
?>
includeIt.php:
<?php
include('includeMe.php');
echo $test;
?>
Should be the exact same as:
<?php
/* INSERTED FROM includeMe.php */
$test = "Hello, World!";
/* END INSERTED PORTION */
echo $test;
?>
Realizing this, the idea of making a function for dynamically including files makes about as much sense (and is about as easy to do) as having dynamic code all-together. It's possible, but it will involve a lot of meta-variables.
I'd look into Variable Variables in PHP as well as the get_defined_vars function for bringing variables into the global scope. This could be done with something like:
<?php
define('E_ROOT', str_replace('//','/',dirname(__FILE__)));
/* ... */
function e_load($fn, $allowReloading = FALSE) {
$prev_defined_vars = get_defined_vars();
$inc = E_ROOT.'/path/here/'.$fn.'.php';
if($allowReloading)
require $inc; // !!!
else
require_once $inc; // !!!
$now_defined_vars = get_defined_vars();
$new_vars = array_diff($now_defined_vars, $prev_defined_vars);
for($i = 0; $i < count($new_vars); $i++){
// Pull new variables into the global scope
global $$newvars[$i];
}
}
?>
It may be more convenient to just use require() and require_once() in place of e_load()
Note that functions and constants should always be in the global scope, so no matter where they are defined they should be callable from anywhere in your code.
The one exception to this is functions defined within a class. These are only callable within the namespace of the class.
EDIT:
I just tested this myself. Functions are declared in the global scope. I ran the following code:
<?php
function test(){
function test2(){
echo "Test2 was called!";
}
}
//test2(); <-- failed
test();
test2(); // <-- succeeded this time
?>
So the function was only defined after test() had been run, but the function was then callable from outside of test(). Therefore the only thing you should need to pull into the global scope are your variables, via the script I provided earlier.
require_once E_ROOT.$libName.'.php';
KISS
Instead of doing this...
$test = "Hello, World!";
... you could consider doing this ...
$GLOBALS[ 'test' ] = "Hello, World!";
Which is safe and consistent in both local function context, and global include context. Probably not harmful to visually remind the reader that you are expecting $test to become global. If you have a large number of globals being dragged in by your libraries maybe there's justification for wrapping it in a class (then you have the benefit of spl_autoload_register which kind of does what you are doing anyhow).

Categories