PHP clearing variables between require file? - php

I have a require for a file in my php code. This require exists twice in the code.
require 'test.php';
echo $result;
require 'test.php';
Is there a way to clear all the variables the first require sets before running the second require on the exact same file?

You could wrap the require in a function, if you don't use global vars. In that case all the variables you create will be limited to the function scope.
function includeFile() {
require 'test.php';
echo $result;
}
includeFile();
includeFile();
But it would be much better to create a class as it was suggested in the comments.

IF you declare all your variables at the beginning of your require like:
$var = false;
$var2 = 0;
$var3 = '';
// etc...
You wouldn't have to do anything other than require the file again - the variables would automatically be reset to an initial state by these declarations.
That being said, what you are looking to do cries out for a different approach. Either encapsulate that functionality into a function or a class depending on how you need to use it. Basically, if you have some code you are repeating throughout your codebase, you should modularize it, and definitely not pollute the global scope with variables only needed for that intermal functionality.

There are two things you can do. unset() will delete all those variables. That answers your question.
What you should do is look into OOP and classes. Make a class, then make an instance of that class. You can then make a new class and have completely different values and data, ultimately disabling the need to unset() and require again.

I did not test this code!
Point is get the list of defined vars before inclusion, include file, get the list of defined vars after inclusion, compute difference, unset global variables based on that difference, include file.
See manual entries on get_defined_vars and unset.
<?php
$old_vars = get_defined_vars();
require 'test.php';
$new_vars = get_defined_vars();
echo $result;
$diff_vars = array_diff_key($old_vars, $new_vars);
while ($var = key($diff_vars)) {
unset($GLOBALS[$var]);
next($diff_vars);
}
unset($old_vars, $new_vars, $diff_vars);
require 'test.php';
Makes sense?

Related

Var visibility when including file

How to make variables visible when including some file. For example:
code.php:
<?php
global $var; $var = "green";
?>
index.php:
<?php
include("code.php");
Function index(){
echo "The apple is $var";
}
?>
Please note that in code.php there are a lot of global variables (~150 variables) and all variables are used in many different functions inside the index.php.
This is an issue to do with variable scope, plus you do not need to be defining $var as a global.
When you include a file, you can imagine in your head that it is just copy-pasting the contents of the other file into the current file.
E.g.
code.php
$includedName = 'Tom';
index.php
include 'code.php';
function sayHello($name)
{
echo 'Hello ' . $name;
}
sayHello($includedName); // Hello Tom
You've mentioned you are working with legacy code, so it may be worthwhile to preserve the use of globals for the sake of consistency - though using globals is generally considered to be very bad practice, I'd generally consider inconsistently using globals to be worse.
To break function scope and pull in variables from the global scope you must invoke the global keyword from within the function:
<?php
$var = "green";
Function index(){
global $var;
echo "The apple is $var";
}
?>
This answer sums up why global variables are considered to be bad practice:
There's no indication that this function has any side effects, yet it
does. This very easily becomes a tangled mess as some functions keep
modifying and requiring some global state. You want functions to be
stateless, acting only on their inputs and returning defined output,
however many times you call them.
However, in this specific example, you are not modifying $var's state - only reading it. So the issues are minimal.
The problems with global state can be read about in more depth on Programmers.SE.

Is it possible to declare a variable as "always global"?

Is there any way I can define a variable such a way that I don't need to global $var1; in every function? Just define it in beginning and keep using where ever needed. I know $GLOBALS exist, but don't want to use it.
First let me try to explain why you shouldn't use globals because they are extremely hard to manage. Say a team member overrides an $ADMIN variable in a file to be 1, and then all code that references the $ADMIN variable will now have the value of 1.
globals are so PHP4, so you need to pick a better design pattern, especially if this is new code.
A way to do this without using the ugly global paradigm is to use a class container. This might be known as a "registry" to some people.
class Container {
public static $setting = "foo";
}
echo Container::$setting;
This makes it more clear where this variable is located, however it has the weakness of not being able to dynamically set properties, because in PHP you cannot do that statically.
If you don't mind creating an object, and setting dynamic variables that way, it would work.
You need to pass the variable as a parameter to that function to avoid using GLOBALS.
The Problematic Scenario (Works ! but avoid it at all costs)
<?php
$test = 1;
function test()
{
global $test;
echo $test; // <--- Prints 1
}
test();
The right way...
<?php
$test = 1;
function test($test)
{
echo $test; // <--- Prints 1
}
test($test); //<--- Pass the $test param here
This behaviour called as superglobal variable. But php has limited predefined list of them: Superglobals.
So you cannot add your own superglobal variable.
Variable scope
My suggestions from the most to less radical:
Edit source code of PHP and add your own superglobals.
Do not write code at all.
Do not use PHP (use different language with different variable scope policy).
Do not use functions (write plain script).
Use constants instead of variables.
Use function params instead of using globals.
Use static variables instead of globals. (\G::$variable)

PHP use one central variables file inside functions

In PHP, what is the right way forward for the following situation:
I have a 'central' vars.php which contains some parameters like MySQL hostname, user, pass, a $Test variable which indicates if the code is running in a test environment or not, and some other variables which I use throughout my site.
Then I have a functions.php which contains all the functions I could use throughout my site.
In some of these functions, I might need some the variables out of the vars.php file.
What is the right way to make the vars.php available to 'everywhere' in PHP?
Now I am doing it like this:
vars.php:
<?php
if(strstr($_SERVER['HTTP_HOST'],"localhost"))
{
$Test = true;
}
?>
functions.php:
<?php
function DoSomething()
{
include "vars.php";
if($Test)
{
$String = "Test is true!";
}
else
{
$String = "Test is false!";
}
return $String;
}
?>
index.php:
<?php
include "vars.php";
include "functions.php;
$DoSomething = DoSomething();
echo $DoSomething;
?>
While this does work, I have to include the vars.php in each function I define, this doesn't seem like a 'nice' solution to me.
Isn't there a way to define the variables in vars.php directly in the global scope, and be able to use them inside functions directly without having to worry about including them?
Thanks!
The right way would be using constants instead of variables.
You're looking for global variables. If you include the file at the top of your page and then declare each one as a global within your function like this:
include('vars.php');
function whatHost()
{
global $host;
echo $host;
}
it will work. This is very bad practice though, as global state is very bad 95% of the time. PHP has powerful object-oriented features which allow you to encapsulate functionality and state within objects. I suggest you read up on that and learn about more proper ways of storing application configuration. Note that for this particular situation, you could just use constants (:
Use constants. Define all together and always on top of classes/files.
Constants are uniques and we use them as config info or static/const data.
If u are sue DEFINE remember use const as a string not a var, example:
define("BASE_PATH", "C://base/");
$dir = BASE_PATH . "images/dropbox.txt";
http://php.net/manual/en/language.constants.php

PHP Variable Scope Issue

In my code, I use a public load_snippet function of a class when I need to include HTML or PHP snippets. (I do this instead of a direct include_once because the directory structure varies depending on certain variables).
I had some issues with variable scopes, so I've narrowed down the problem to this: let's say I define a variable within my page:
$variable = 'Hello World!";
Then, I need load in a snippet:
$APP->load_snippet("slider");
The snippet renders perfectly, except that PHP gives an undefined variable error if I try to reference $variable in the slider code. If I directly include the php file, it works as expected, so I don't understand why I'm having this problem, since this is the load_snippet function:
public function load_snippet($snippet){
if(file_exists("app/".$this->APP_TYPE."/snippets/".$snippet.".php")){
include "app/".$this->APP_TYPE."/snippets/".$snippet.".php";
}
else{
include 'common/txt/404.txt';
}
}
Any help you can give me is much appreciated.
The file is being included within the context of the load_snippet() function, and therefore has only those variables which exist within that function. One way to modify this is to make your function accept two variables: the filename and an array of values.
public function load_snippet($snippet, $content) {
if (is_array($content)) extract($content);
if (file_exists("app/".$this->APP_TYPE."/snippets/".$snippet.".php")) {
include "app/".$this->APP_TYPE."/snippets/".$snippet.".php";
} else {
include 'common/txt/404.txt';
}
}
Then
$arr = array('variable' => 'Hello world!');
load_snippet('slider', $arr);
I think include inside a function makes no sense to me... I think that you should put in function
global $variable;
Note that include will put the code inside the function(include will be replaced by code) as i know..
The way you are doing it is an ugly one, but you can use global $variable inside the snipped to refer to the variable. However if you include the snipped inside a function or a method, you'll have to make the variables in that function/method global as well
If you need $variable inside of the App::load_snippet() method, it would probably be best to pass it in:
public function load_snippet($snippet, $var='Hello world'){
if(file_exists("app/".$this->APP_TYPE."/snippets/".$snippet.".php")){
include "app/".$this->APP_TYPE."/snippets/".$snippet.".php";
}else{
include 'common/txt/404.txt';
}
}
//do something with $var
}
You can set a default for when $variable hasn't been set. No globals, no out of scope variables.
Instead you can use the constants like define('VARIALABLE','value'). which will be available to you anywhere in your file
You are including inside a class. Which means that the included file has the same variable scope as the line of code which includes it has. TO fix this all you need to do is put
global $variable;
Above the include.

PHP Preserve scope when calling a function

I have a function that includes a file based on the string that gets passed to it i.e. the action variable from the query string. I use this for filtering purposes etc so people can't include files they shouldn't be able to and if the file doesn't exist a default file is loaded instead.
The problem is that when the function runs and includes the file scope, is lost because the include ran inside a function. This becomes a problem because I use a global configuration file, then I use specific configuration files for each module on the site.
The way I'm doing it at the moment is defining the variables I want to be able to use as global and then adding them into the top of the filtering function.
Is there any easier way to do this, i.e. by preserving scope when a function call is made or is there such a thing as PHP macros?
Edit: Would it be better to use extract($_GLOBALS); inside my function call instead?
Edit 2:
For anyone that cared. I realised I was over thinking the problem altogether and that instead of using a function I should just use an include, duh! That way I can keep my scope and have my cake too.
Edit: Okay, I've re-read your question and I think I get what you're talking about now:
you want something like this to work:
// myInclude.php
$x = "abc";
// -----------------------
// myRegularFile.php
function doInclude() {
include 'myInclude.php';
}
$x = "A default value";
doInclude();
echo $x; // should be "abc", but actually prints "A default value"
If you are only changing a couple of variables, and you know ahead of time which variables are going to be defined in the include, declare them as global in the doInclude() function.
Alternatively, if each of your includes could define any number of variables, you could put them all into one array:
// myInclude.php
$includedVars['x'] = "abc";
$includedVars['y'] = "def";
// ------------------
// myRegularFile.php
function doInclude() {
global $includedVars;
include 'myInclude.php';
// perhaps filter out any "unexpected" variables here if you want
}
doInclude();
extract($includedVars);
echo $x; // "abc"
echo $y; // "def"
original answer:
this sort of thing is known as "closures" and are being introduced in PHP 5.3
http://steike.com/code/php-closures/
Would it be better to use extract($_GLOBALS); inside my function call instead?
dear lord, no. if you want to access a global variable from inside a function, just use the global keyword. eg:
$x = "foo";
function wrong() {
echo $x;
}
function right() {
global $x;
echo $x;
}
wrong(); // undefined variable $x
right(); // "foo"
When it comes to configuration options (especially file paths and such) I generally just define them with absolute paths using a define(). Something like:
define('MY_CONFIG_PATH', '/home/jschmoe/myfiles/config.inc.php');
That way they're always globally accessible regardless of scope changes and unless I migrate to a different file structure it's always able to find everything.
If I understand correctly, you have a code along the lines of:
function do_include($foo) {
if (is_valid($foo))
include $foo;
}
do_include(#$_GET['foo']);
One solution (which may or may not be simple, depending on the codebase) is to move the include out in the global scope:
if (is_valid(#$_GET['foo']))
include $_GET['foo'];
Other workarounds exists (like you mentioned: declaring globals, working with the $_GLOBALS array directly, etc), but the advantage of this solution is that you don't have to remember such conventions in all the included files.
Why not return a value from your include and then set the value of the include call to a variable:
config.php
return array(
'foo'=>'bar',
'x'=>23,
'y'=>12
);
script.php
$config = require('config.php');
var_dump($config);
No need to mess up the place with global variables
Is there any easier way to do this, i.e. by preserving scope when a function call is made
You could use:
function doInclude($file, $args = array()) {
extract($args);
include($file);
}
If you don't want to explicitly pass the variables, you could call doInclude with get_defined_vars as argument, eg.:
doInclude('test.template.php', get_defined_vars());
Personally I would prefer to pass an explicit array, rather than use this, but it would work.
You can declare variables within the included file as global, ensuring they have global scope:
//inc.php
global $cfg;
$cfg['foo'] = bar;
//index.php
function get_cfg($cfgFile) {
if (valid_cfg_file($cfgFile)) {
include_once($cfgFile);
}
}
...
get_cfg('inc.php');
echo "cfg[foo]: $cfg[foo]\n";

Categories