scope of a global variable in drupal module - php

What is the scope of a 'global' variable inside a module in Drupal? I created a module for a custom block and need to know how long the global stays set for so I know how to use them. Do they stay across the website instance, or only once for the page. For example in the following code drupal_set_message gets called once every time I load a page with the block. Can I be sure the 'global' variable is refreshed each time the block is loaded?
<?php
global $my_array;
function fill_array()
{
global $my_array;
if(!isset($my_array))
{
drupal_set_message("filling the array");
$my_array = array();
// code to fill array up...
}
}

Check out what documentation says:
http://php.net/manual/en/language.variables.scope.php
Global variables are by default available to all global code. But if you want to use them inside you function you have to declare them as global first.
And any kind php variable has lifetime no longer then one "page call". So with your next page call all the values are lost.
If you want to keep some value longer than single execution you must use php sessions or cookie or file or database....to store them there.

I know that this is an old question but scope is more tricky than this.
Drupal executes a block of PHP in a function context using eval() so variables defined at the top level within your PHP code are not in the global context unless they are explicitly set as global.
In other words, your code has three contexts, not the normal two.

Related

PHP object scope

Can somebody explain to me the concept of object scope in PHP? I'm very new to objects in PHP and the reason I ask is because I was able to create an object within an if statement, and then access the object outside the scope of the if statement.
Example:
//only create object if some condition is met
if ($conditionTrue){
$myBook = new Book('PHP for Dummies','softcopy');
}
$myBook.read();
I would have though that this would generate an error but it didn't.
Some background to my question
I was trying to figure out how to determine which constructor to call depending on the condition that is met. The only conceivable way was to introduce an if statement but doing that, I thought would impose the issue of scope which it didn't and I'm just wondering why..
In PHP, if doesn't have its own scope. So yes, if you define something inside the if statement or inside the block, then it will be available just as if you defined it outside (assuming, of course, the code inside the block or inside the if statement gets to run).For more about the PHP scope, read the variable scope manual page.
This scenario will generate error in other languages like JAVA,C#. But in PHP this is not going to happen.
Because in PHP we can create variable anywhere there is no need to first initialise the variable and after that assign the values in it.
In this scenario when you assigns the value to $myBook it first initialises the variable $myBook for global scope. So when you accessing the $myBook outside if block, it is already present in global scope of document and because of that you can access it without generating eror.
The above scenario has some limitation like where the variable is initialised, eg (within function, within class).

Custom variable which can be used on each page like super globals?

I want a variable to be superglobal, but as am using procedural style I don't think I can make one of my own, so basically the question is that am using a query to retrieve all security control of my website from security table, am checking whether maintenance mode is on/off, if it's on am redirecting it to website under maintenance page, so on each page I need to check the status of variable $maintenance_status, for doing this, i need to call that query on each page, or else am getting an error that undefined variable, moreover if am making a function and including that function file in other pages, it is showing me that $db_connect(which is my db connection variable) is undefined, am including my pages in this sequence
include_once('connection.php');
include_once('functions.php');
/*other scripts goes here*/
Any idea how to pull this status on each page? I thought to make a new file for common queries but is ait a clean solution? moreover I guess am not understanding includes, if I included connection.php before functions.php than why my functions.php is showing undefined variable $db_connect?
You can use a constant for that by using define(). Defines can be set once per script execution and can not be changed during one script execution. They are superglobal - also across files which are being included.
See http://php.net/define or just
define('MY_CONSTANT', 'whatever');
define('MY_OTHER_CONSTANT', false);
function foo() {
if (MY_OTHER_CONSTANT !== true) {
echo MY_CONSTANT;
}
}
foo();
Without more code context on where within your files you are getting the errors, it will be hard to provide any advice. For example, is your reference to $db_connect done from inside a function? If it is, than it will not work unless you have a global $db_connect declaration within that function (to use the $db_connect in the global scope rather than the undefined $db_connect in the function's scope).
While I don't prefer using such global declarations within functions for a number of reasons (I would rather use dependency injection, or get the DB connection via a static singleton function call), that is probably a lesson for another time.
You might be best served anyway to make your query in some sort of init script (like after your connection.php inlcude) and define a constant regarding whether maintenance mode if on or off. Something like this
// assuming you have already made DB query and have a value of true/false on a variable called $is_maint_mode
define('MAINT_MODE', $is_maint_mode);
This would give you a constant MAINT_MODE that is globally available to your code.

Do globals interfere with required files in PHP?

I need to edit a variable (array) that is defined outside of the function, so I can use it in another function further in. The easiest way I can think of is to define it as global inside the function, but I have many required files involved as well.
The documentation of global variables says that it can be used "anywhere in the program." Does that imply throughout all files (is it global in a sense of across all files) or is it just the file it's in (locally global, if that makes sense).
I did find a question about globals on this site that suggests passing it by reference, but I have this function implemented extensively in other files and requiring them to have an additional variable in their calls would be obnoxious to say the least.
If you define your variable global within the function, you will be referring to the globally scoped variable, and changes to that variable made within your function will be visible to other functions that use that global variable, whatever files they're in, so long as the inclusion / execution order is correct.
If the file you declare the global in is in memory, then that variable is available for you to use. But, if you don't include or require the file the global is declared in on a certain page, it will not be available to you.
Order is also important. If you try to call the global variable before the include or require of the file you set it in, it will be unavailable.
Globals are shared among all files. By the way, instead of declaring them with global $variable;, you should use $GLOBALS['variable'] to make explicit that you're accessing a global variable.
If a lot of functions grouped in a file require access to some common state, chances are you need to turn them into a class. That's pretty much the definition of a class.
Or you could turn the array into a class and have functions call methods on it.
Perhaps a singleton or a registry (2) could help.
Note that most OOP implementations pass a reference to the object as a method's first parameter, hidden (C++, PHP) or not (C, Python).

Retrieving variables from included files

I have a php file that includes another one using include()
I defined a variable $something in the included file and that will change depending on a function that runs in the included file.
Now, I want to print that variable in the original file, when I use echo $something it is printing absolutely nothing, help?
Let's just leave aside that this is a poor design choice for a moment :)
You're probably running into a issue where you haven't declared the variable as global inside the function which modifies it.
function foo()
{
global $something;
$something='bar';
}
You will find the PHP manual page on variable scope most educational in this regard!
So why is this a poor design choice? First of all, check out "Are global variables bad?" which answers the question for C++. The answer is really no different for PHP - it can lead to unmaintainable and unreadable code.
There's another (increasingly historical) wrinkle with PHP though - if the 'register_globals' setting is on, a user can set global variables via the URL query string. This can lead to all manner of security problems, which is why this is now turned off by default (never write new code which requires it to be on).
As a wise man once said, "globals are the path to the dark side. globals lead to anger. anger leads to hate. hate leads to suffering" :)
It is possible you have declared your variable in global scope and are trying to use it in functional scope. To get around this use the global command.
$myglobal = 3;
function printMyGlobal() {
global $myglobal; // will not work without this line
echo $myglobal;
}
Use get_defined_vars to debug defined variables

PHP variable from other file comes back as NULL

In one PHP file, I have this code:
require_once $_SERVER['DOCUMENT_ROOT'] . '/custom/functions.php';
global $testVar;
var_dump($testVar);
In the functions.php file, I have this at the beginning, followed by a few other functions:
function pr($s) {
echo '<pre>', htmlspecialchars(print_r($s,true)), '</pre>';
}
$testVar = 'hello world';
When running the first file, the variable comes back as NULL. I added the global bit but it shouldn't be necessary. This is part of a Joomla module but I've never had problems including files before, it should just work like regular PHP. Why might this be happening?
First, try to use Joomla's path constants such as JPATH_BASE instead of $_SERVER['DOCUMENT_ROOT']. Joomla has a lot of useful constants, check it's documentation.
I've read your answer, and reading php documentation I tried to find a reason to why you need to use global keyword twice.
First, Variable scope.
The scope of a variable is the context within which it is defined. For the most
part all PHP variables only have a single scope.
(...)
However, 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.
The variable isn't in a function scope, so that's why we thought the NULL was a strange behavior.
But then I read include and found something interesting:
(...)
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.
I can't see any mention about the variables being global in this paragraph. So,it seens that, being cumbersome or not, your solution is the right thing to do when you want to use global variables like that.
In your situation, if doing this is cumbersome, I would create a simple class. If you have just helper functions in your file, create a class Util{} with a lot of methods and $testVar as an attribute.
I have found a solution that seems to work: using the global keyword both when setting the variable initially, and just before I need to use it.
(However this is quite cumbersome, and I'm still not sure why it happens, so if anyone has a better solution, feel free to post.)

Categories