Variables loaded from a separate script are not defined within functions - php

I use settings.php to store general settings for my application. When I load this settings file, I can use the variables defined in settings.php in the script itself, but not within any functions I define in it.
For example, in my class definition, myclass.php:
<?php
$preIP = dirname(__FILE__);
require_once( "preIP/settings.php" );
class MyClass {
...
public function foo() {
echo $variable_from_settings;
}
}
The code in the function foo() will not work (the variable will not be defined).
The settings.php file looks like this:
$variable_from_settings = "bar";
Thanks,

How about putting
global $variable_from_settings
before
echo $variable_from_settings;

You could do the following if you don't want to put global $variable_from_settings; everywhere.
echo $GLOBALS['variable_from_settings'];
However it's probably better to use a singleton to contain your settings as suggested in create superglobal variables in php?

Related

Classes - require conflict in constructor

I'm coding a Wordpress plugin and I'm not sure regarding the function name conflict..
I have a file named test_handling.php which contains the following content :
function testing() { echo 'test'; }
I included this file in a class constructor (file named testcls.class.php) :
class TestCls {
function __construct() {
require_once('test_handling.php');
testing();
}
function otherfunction() {
testing();
}
// ...
}
In this case, I would like to know if the testing() function is only available in the TestCls class, or can it create conflicts if an other WP plugin has a function with the same name ?
Even with the same name, the functions will have different scope if defined as class method. To make a call to a regular function you will do the following:
testing();
and the result will be:
'test'
the class method need an instance of the class or be statically called. To call the method class you will need the following formats:
$class->test();
or
OtherPlugin::test();
To sum up, the function test will be different if defined as class method. Then, you will not have conflicts.
Other way to encapsulate your function and make sure you are using the right one is with namespaces. If you use a namespace in your test_handling.php
<?php
namespace myname;
function testing(){echo 'test';}
?>
You will access the function test like this:
<?php
require_once "test_handling.php";
use myname;
echo myname\testing();
Now you are sure about the function you are calling.
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.
from include in PHP manual
Which means that yes, you can have conflicts.

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

require_once to global scope within a function

It seems that if require_once is called within function, the included file doesn't extend the global variable scope. How to require_once a file to global scope from within a function?
What I'm trying to do is some dynamic module loader:
function projects_init()
{
...
foreach ($projects as $p) {
require_once($p['PHPFile']);
$init_func = $p['init'];
if ($init_func)
$init_func();
}
}
If it is not possible to use require_once that way, what is the simplest solution for this? (Please no heavy frameworks.)
EDIT: it should also work for PHP 5.2.
To summarize all the information:
functions are not an issue, they will be global anyway this way
for global variables, there are 2 options:
declare them as global in the included file
declare them as global in that function (projects_init() in my case)
The above answer is right, you can use global to get what you need.
In the included file just declare the variables global at the beginning of the file, this way the code will run in the function scope but it will change the global variables(yes, you have to be careful and declare everything you need to change as global but it should work), example:
function a() {
require_once("a.php");
}
a();
echo $globalVariable;
and in the a.php file:
global $globalVariable;
$globalVariable="text";
Functions are not an issue (ref):
All functions and classes in PHP have the global scope - they can be called outside a function even if they were defined inside and vice versa.
About global variables: As in an existing question regarding the scope of require and the like, the scope is defined where the use is. If you need something else, there are numerous answers (my take) that show how to deal with global variables, most making use of get_defined_vars.
You can use global to put a variable in the global scope.
http://php.net/manual/en/language.variables.scope.php

Using require/require_once() in a functions file

my functions.php file is just a placeholder for many different functions. I have another file settings.php that I use to store different settings. Some of the functions in functions.php will need to access some of the variables in settings.php, so I tried:
require("settings.php")
on top of the functions.php file, but that does not seem to give my functions access to the variable in settings.php. I need to put require("settings.php") in every function separately.
Is there a way I can declare the variables in settings.php to be accessible globally to all functions defined in functions.php?
Thank you,
You need to modify your functions in functions.php to use global variables defined in settings.php.
Inside settings.php;
$var1 = "something";
$var2 = "something else";
By using the global keyword:
function funcName() {
global $var1;
global $var2;
// Rest of the function...
}
Or more preferably, using the $GLOBALS[] superglobal array. Any variables declared at global scope, like I assume your settings.php vars are, will be included as array keys in $GLOBALS[]. It's a little better for readability than using the global keyword inside each function.
function funcName() {
$y = $GLOBALS['var1'];
$x = $GLOBALS['var2'];
// Etc...
}
Although you've set these variables in your settings.php file, when you try to reference them in your functions it won't work. This is because variables in functions a locally scoped to the function.
To access these global variables you need to use the global keyword to bring your global variables into scope.
For example:
// Declared in settings.php
$x = 1234;
// One of your functions
function MyFunc()
{
global $x;
DoSomething($x);
}
You need to do this for every function where $x is accessed.
For more information see:
Variable scope - php.net docs
I do not know the details of your issue, but you may wish to use require_once() within each function. This seems to be better idea than using some global variables.
You're thinking global variables.
However that's not the best way to go.
Can you perhaps create a class?
class SomeClass
{
private $settings;
function __construct()
{
require_once($settings);
$this->settings = $variable(s) from settings file
}
function some_function()
{
print($this->settings['something']);
}
}

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