I have a list of files that I require_once at the beginning of my main scripts.
In one of those files, I have a bunch of functions.
In another one of those files, I have a bunch of constants (which are variables at the moment, but they are essentially constants).
Main.php
require_once \Constants.php
require_once \Functions.php
From within main.php, I am able to call functions and call the constants from their respective scripts... I am also able to call functions and pass the constants from Constants.php as parameters to the functions.
However, I am not able to use functions that have the constants embedded within them.
In other words, I cannot use the functions from Functions.php that already have the variables from the Constants.php file within the functions, but I am able to use functions from Functions.php if they do not have any variables from other included files within the function.
Function FirstFunction(){ echo $Constant1; return 1 }
FirstFunction() uses $Constant1 from Constants.php and does not work.
Function SecondFunction($param){ echo $param; return 1 }
SecondFunction() can be passed $Constant1 from Constants.php as a parameter and it works fine.
Questions:
Is there a way for me be able to use my Main.php to call a function file and a constant file and have the function file use variables from the constant file without explicitly calling or passing them from within Main.php?
If I were to daisy chain them (Main.php calls Functions.php; Functions.php calls Constants.php) will this work? (I kind of tried this but not well enough to either trust or rule out this method just yet).
Note
Most of the information I am able to find is regarding using variables from included files, but not specifically about included files using variables from other included files.
This sounds like a simple scope issue, that has nothing to do with your include-cycle.
When you create your 'constants' as normal PHP-variables ($name='value';), in the root scope of the Constants.php, then they must be called inside any later functions, by referencing them first ... like this:
$name='value';
/** other stuff **/
function Foo(){
global $name;
//You have access to $name here
}
The true solution tho, is to actually define your constants as real constants, which makes them available in any scope ... like this:
define('NAME','value');
/** other stuff **/
function Foo(){
//You immediately have access to NAME here
}
Only downside to true constants is, that they are constant ... meaning, they can’t be changed at a later point in your script.
You can read more about 'scope' here: http://php.net/manual/en/language.variables.scope.php
include() works as if the contents of the file being included are literally cut/paste into the spot where the include() call is:
variables.php:
<?php
$foo = 'bar';
test.php:
<?php
var_dump($foo); // notice: undefined variable
include('variables.php');
var_dump($foo); // string(3) "bar"
Note that standard PHP variable scoping rules apply. So if you do the include() inside a function:
<?php
var_dump($foo); // notice: undefined variable
function test() {
var_dump($foo); // notice: undefined variable
include('variables.php');
var_dump($foo); // string(3) "bar"
}
test(); // call the test function
var_dump($foo); // notice: undefined variable
notice how $foo doesn't exist before/after the function is defined/called - it will only exist WITHIN the function, and only AFTER it's been included().
If you want your standard variables to be truly global, you'll have to include the file at a global scope, or declare them global:
variables.php:
<?php
global $foo;
$foo = 'bar';
and then using the same script, $foo will "magically" appear for the final var_dump, because it's been made global.
Related
Maybe I'm just tired or just am simply confused, but I'm having a strange issue dealing with some require_once() calls and ob_start().
Basic Structure:
Top of Main.php:
require_once 'config.php'; // includes variable $A = "bar", and Function "foo"
function getPage(){
ob_start();
include 'some_file.php';
$html = ob_get_clean();
echo $html;
die();
}
getPage();
some_file.php
require_once 'config.php'; // includes same config file
var_dump($A); // NULL
foo(); // runs, returns correct value
Config.php
$A = 'bar';
function foo(){
return "FOO";
}
So, what is wrong here? I'm including a file while buffering output. The required file config.php holds a variable and function. When including some_file.php during the buffer, the variable $A is apparently NOT set/accessible. The function foo CAN execute.
The documentation says:
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.
Your provided code does not illustrate the problem that you're describing. When I run it as-is, it correctly shows that the variable is defined.
That being said, the thing to remember is that what looks like a global variable in an included file actually ends up in the scope of the function that's calling it. So if the first time require_once() is called is from a function, the $A variable is scoped to the function - and disappears when the function returns, just like any other variable defined inside the function.
If you absolutely must define a global variable inside an included file (are you sure? really?), make sure you only include that file from the global scope - not from within a function. If you need to access the variable from within a function, include the file outside the function, and then use the global keyword to access the variable from within the function.
This question seems simple enough, but I can't find an answer anywhere...
At the beginning of my php script/file I want to create a variable.
$variable = 'this is my variable';
I want this variable to be available within the entire script, so that all classes, methods, functions, included scripts, etc. can simple call this variable as $variable.
Class MyClass
{
public function showvariable()
{
echo $variable;
}
}
The $_SESSION, $_POST, $_GET variables all behave like that. I can just write a method and use $_POST and it'll work. but if I use $variable, which I have defined at the beginning of my script, it says "Notice: Undefined variable: variable in ..." It even says it, when I write a function, rather than a class method...
I tried to write
global $variable = 'this is my variable';
But then the script wouldn't load...
"HTTP Error 500 (Internal Server Error): An unexpected condition was encountered while the server was attempting to fulfill the request."
How can I make a variable truly globally accessible like $_POST?
Why would I need this? I specifically plan on using it as a form token. At the top of the page I generate my form token as $token, at the bottom of the page I store it in the session. Before handling any form I check if the SESSION token matches the POST token... And since I often have multiple forms on the page (login form in the top nav, and register form in the main body) i just wanna make it convenient and call $token on each form. Sometimes my formelements are generated by classes or functions, but they don't recognize the variable and say it's not defined.
I found it... -.- I thought it would be easy enough...
I have to call to the variable by using
$GLOBALS['variable'];
Just found it... finally...
http://php.net/manual/en/reserved.variables.globals.php
EDIT like 8 months later or so:
I just learned about CONSTANTS!
define('name', 'value');
They just can't be reassigned...
I guess I could use that, too!
http://www.php.net/manual/en/language.constants.php
Just define a variable outside of any class or function. Then use keyword global inside any class or function.
<?php
// start of code
$my_var = 'Hellow Orld';
function myfunc() {
global $my_var;
echo $my_var; // echoes 'Hellow Orld';
}
function myOtherFunc() {
var $my_var;
echo $my_var; // echoes nothing, because $my_var is an undefined local variable.
}
class myClass {
public function myFunc() {
global $my_var;
echo $my_var; // echoes 'Hellow Orld';
}
public function myOtherFunc() {
var $my_var;
echo $my_var; // echoes nothing.
}
}
myFunc(); // "Hellow Orld"
myOtherFunc(); // no output
myClass->myFunc(); // "Hellow Orld"
myClass->myOtherFunc(); // no output
// end of file
?>
you need to declare global to access it in any function scope:
at the top of your script:
global $var;
$var= "this is my variable";
in your class
...
public function showvariable(){
global $var;
echo $var;
}
...
In PHP, global variables must be declared as such within each function in which they will be used. See: PHP Manual, section on variable scope
That being said, global variables are often a bad idea, and in most cases there's a way to avoid their use.
I am having an unexpected issue with scope. The include documentation (also applies to require_once) says the required file should have access to all variable at the line it was required.
For some reason I am not able to access a class instantiated with global scope inside a function that was required in.
Would anyone know why? I am obviously missing something.
I got it working through a reference to $GLOBALS[], but I still want to know why it is not working.
UPDATE:
The error I am getting is:
Fatal error: Call to a member function isAdmin() on a non-object in <path>.php on <line>
Code:
$newClass = new myClass();
require_once("path to my file");
----- inside required file -----
function someFunction() {
$newClass->someMethod(); // gives fatal error. (see above).
}
Functions define a new scope, so inside a function you cannot access variables in the global scope.
Variable Scope
within user-defined functions a local
function scope is introduced. Any
variable used inside a function is by
default limited to the local function
scope
About included files, the manual states:
When a file is included, the code it
contains inherits the variable scope
of the line on which the include
occurs.
So if you include something in a function, the included file's scope will be that of the function's.
UPDATE: Looking at your code example edited into the question, global $newClass; as the first line of the function should make it working.
$newClass = new myClass();
require_once("path to my file");
----- inside required file -----
function someFunction() {
global $newClass;
$newClass->someMethod();
}
Be aware though that using global can quickly make your code more difficult to maintain. Don't rely on the global scope, you can pass the object to the function as a parameter, or use a Singleton/Registry class (some tend to argue against the latter, but depending on the case it can be a cleaner solution).
The included code doesn't have a scope different than the code surrounding it. For example:
function a() {
echo $b;
}
This will fail even if echo $b is in an included file. If you replace the above with:
function a() {
include 'file.php';
}
... and file.php contains:
echo $b;
... then it's the same thing as if you wrote:
function a() {
echo $b;
}
Think of it this way: whenever you use include / require, the contents of the included file is going to replace the include / require statement, just as if you removed the statement and pasted the contents of the file in its place.
It doesn't do anything else as far as scope is concerned.
I have use
include ('base.php')
script in my other scripts ( more.php). Now base.php should receive one variable from more.php. How to pass a variable from more.php into base.php?
If you include a script file A into a script file B, then A has the same global variable scope as B has:
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. — include manual page
So if you define a variable in A, then you have access to that variable in B:
// A.php
$varInA = 'foobar';
include 'B.php';
// B.php
echo $varInA;
Create a function within base.php, like so:
function setup($config) {
// Do something with config
}
and call it from more.php..
setup($somevar);
Or, you could try using classes and member variables and constructors.
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";