If I have a file a.php which I can't edit.
<?php
$a = 1;
function a() {
global $a;
echo $a;
}
a();
then running php a.php prints 1 nicely. But if I have b.php:
<?php
function b() {
include "a.php";
}
b();
Then running php b.php doesn't print anything.
What can I type before the include "a.php" to make it behave the same without editing a.php?
(Obviously other than defining $a. In my real-world example it has to work for a complicated a.php).
Try adding a global into your new function:
function b() {
global $a;
include "a.php";
}
At the moment I wonder if PHP is treating $a as local to your b() function.
Addendum: in response to your comment, it seems that you need to grab arbitrary variables that your include has created locally in your function, and remake them as global. This works for me on 5.3.20 on OSX 10.6.8:
function b() {
include 'a.php';
// Move variables into global space
foreach (get_defined_vars() as $name => $value) {
global $$name;
// global wipes the value, so just reset it
$$name = $value;
echo "Declared $name as global\n";
}
}
b();
// Your global vars should be available here
Obviously you can remove the echo once you're happy it works.
Defining a function inside a function? Yuck. But I guess you have a real-world situation that doesn't allow any other way. But for the record, this is REALLY BAD PRACTICE
Adding global $a to b() should work.
function b() {
global $a;
include "a.php";
}
I don't know what variables need to be defined. a.php is really complicated
Then the only way I can think of is not using a function in b.php, so you're in the global scope when including a.php. I can see no other way.
It sounds like a.php is some legacy or 3rd party script that you have to wrap in your own application. I had a similar problem once and the solution was not pretty. First, you will have to find out, what global variables exist (grep global or similar helps).
This is the relevant part of my "Script Adapter" class:
private function _includeScript($file, $globals)
{
foreach ($globals as $global) {
global $$global;
}
ob_start();
require $file;
$this->_response->setBody(ob_get_clean());
}
As you see, I had to catch the output too. The class also emulates $_GET and catches header calls to assign everything to a Response object, but for your case only this method is important. It gets called with the file name and an array of global variable names as parameters:
_includeScript('a.php', array('a'));
Related
This is probably not the wisest question, but is it possible to return a variable from a function without redeclaring it?
function test(){
$a = 1;
return $a;
}
Would it somehow be possible to access $a with just calling the function? test();
not $a = test();
Is that the only way? I want to make $a available after calling the function.
You have to put the variable into the global scope:
http://codepad.org/PzKxWGbU
function test()
{
$GLOBALS['a'] = 'Hello World!';
}
test();
echo $a;
But it would be better to use a return value or references:
function test(&$ref)
{
$ref = 'Hello World!';
}
$var = '';
test($var);
I assume you want to change some context when you call the function.
This is possible. For example, all global variables share the same context across your application. If a function set's a global variable, its available in the global scope:
function change_global_variable($name, $value)
{
$GLOBALS[$name] = $value;
}
change_global_variable('a', 1);
echo $a;
However, whenever you do something like this, take care that you're destroying the modularity of your code. For example, if you have 50 functions like this and 80 variables, and then you need to change something, you need to change many, many places. And even harder, you don't remember which places you need to change and how they belong to each other.
It's normally better to make the context an object and pass it to the function that changes it, so it's more clear what the function does:
class Context extends ArrayObject {}
$context = new Context;
function change_context(Context $context, $name, $value)
{
$context[$name] = $value;
}
change_context($context, 'b', 2);
echo $context['b'], "\n";
This example demonstrates something that's called dependency injection. Instead of modifying the only one (global) context that exists in PHP, you are telling the function what it should modify, instead that it modifies hard-encoded global variables
There is a mix form of it, using the global variable scope to contain the context, so you spare to pass it as an additional parameter, however I only show it here for completeness, because it's not helping to retain modularity that well (however it's better than using more than one global variable):
class Context extends ArrayObject {}
$context = new Context;
function change_global_context($name, $value)
{
global $context;
$context[$name] = $value;
}
change_global_context('c', 3);
echo $context['c'], "\n";
Rule of thumb: Avoid global variables. Consider them of being very expensive and you don't want your code to be expensive.
No, it is not due to the scoping.
An option would be to declare $a before and then making it a global. It will then be available inside test:
$a = '';
function test(){
global $a;
$a = 1;
return $a;
}
echo $a; // 1
But may I ask why you want to do this? Are you just playing around or do you have a use case? You're most probably doing it wrong if you need this.
Maybe if you just want to show the variable you can use
function test(){
$a = 1;
echo $a;
return $a;
}
in this way if you want you can save the variable $a in a variable if not you can just show it calling the test function.
Hope it helps.
Nicola.
I have two PHP files. In the first I set a cookie based on a $_GET value, and then call a function which then sends this value on to the other file. This is some code which I'm using in join.php:
include('inc/processJoin.php');
setcookie("site_Referral", $_GET['rid'], time()+10000);
$joinProc = new processJoin();
$joinProc->grabReferral($_COOKIE["site_Referral"]);
The other file (processJoin.php) will then send this value (among others) to further files which will process and insert the data into the database.
The problem I'm having is that when the grabReferral() function in processJoin.php is called, the $referralID variable isn't being defined on a global scale - other functions in processJoin.php can't seem to access it to send to other files/processes.
I've tried this in processJoin.php:
grabReferral($rid) {
global $ref_id;
$ref_id = $rid;
}
someOtherFunction() {
sendValue($ref_id);
}
But the someOtherFunction can't seem to access or use the $ref_id value. I've also tried using define() to no avail. What am I doing wrong?
you have to define the global var in the second function as well..
// global scope
$ref_id = 1;
grabReferral($rid){
global $ref_id;
$ref_id = $rid;
}
someOtherFunction(){
global $ref_id;
sendValue($ref_id);
}
felix
personally, I would recommend the $GLOBALS super variable.
function foo(){
$GLOBALS['foobar'] = 'foobar';
}
function bar(){
echo $GLOBALS['foobar'];
}
foo();
bar();
DEMO
This is a simple and working code to initialize global variable from a function :
function doit()
{
$GLOBALS['val'] = 'bar';
}
doit();
echo $val;
Gives the output as :
bar
The following works.
<?php
foo();
bar();
function foo()
{
global $jabberwocky;
$jabberwocky="Jabberwocky<br>";
bar();
}
function bar()
{
global $jabberwocky;
echo $jabberwocky;
}
?>
to produce:
Jabberwocky
Jabberwocky
So it seems that a variable first declared as global inside a function and then initalised inside that function acquires global scope.
The global keyword lets you access a global variable, not create one. Global variables are the ones created in the outermost scope (i.e. not inside a function or class), and are not accessible inside function unless you declare them with global.
Disclaimer: none of this code was tested, but it definitely gets the point across.
Choose a name for the variable you want to be available in the global scope.
Within the function, assign a value to the name index of the $GLOBALS array.
function my_function(){
//...
$GLOBALS['myGlobalVariable'] = 42; //globalize variable
//...
}
Now when you want to access the variable from code running in the global scope, i.e. NOT within a function, you can simply use $ name to access it, without referencing the $GLOBALS array.
<?php
//<global scope>
echo $myGlobalVariable; //outputs "42"
//</global scope>
?>
To access your global variable from a non-global scope such as a function or an object, you have two options:
Access it through the appropriate index of the $GLOBALS array. Ex: $GLOBALS['myGlobalVariable'] This takes a long time to type, especially if you need to use the global variable multiple times in your non-global scope.
A more concise way is to import your global variable into the local scope by using the 'global' statement. After using this statement, you can reference the global variable as though it were a local variable. Changes you make to the variable will be reflected globally.
//<non global scopes>
function a(){
//...
global $myGlobalVariable;
echo $myGlobalVariable; // outputs "42"
//...
}
function b(){
//...
echo $GLOBALS['myGlobalVariable']; // outputs "42"
echo $myGlobalVariable; // outputs "" (nothing)
// ^also generates warning - variable not defined
//...
}
//</non global scopes>
Please use global variables in any language with caution, especially in PHP.
See the following resources for discussion of global variables:
http://chateau-logic.com/content/dangers-global-variables-revisited-because-php
http://c2.com/cgi/wiki?GlobalVariablesAreBad
The visibility of a variable
I hope that helped
<?php
$a = 1;
$b = 2;
function Sum()
{
global $a, $b;
$b = $a + $b;
}
Sum();
echo $b;
?>
I understand that if you declare a variable within a php function with the 'global' keyword it will reference a variable declared outside the function, but why would a php programmer want to declare a variable outside of a function scope as 'global?' Thanks!
I understand what this does:
<?
$a = 1;
function $boo() {
global $a;
echo $a;
}
?>
But what I'm getting at is why would I want to do this?
<?
global $a;
function $boo() {
//foo
}
?>
It has to do with php scope
If you have file a.php that has a class like this
<?
class test()
{
function test()
{
include('b.php');
}
}
?>
and a file b.php
<?
$a = 1;
?>
Then $a will only be accessible in the scope of function test()
if you have global $a in b.php, $a then becomes a global variable
here's the php doc about it : http://php.net/manual/en/function.include.php
I have no idea why you would want to do that. For all intents and purposes (unless I am very, very much mistaken) this is exactly the same as just:
<?
var $a;
function $boo() {
// foo
}
?>
Which in turn is the very same as
<?
function $boo() {
// foo
}
?>
because you generally don't have to instantiate your variables in PHP.
Very curious why you're using variably-named functions though? (function $boo() {} )
Well, IMHO the use of global variables is a poor programming practice. It can cause unintended side-effects in your program which are hard to debug, and makes it harder to maintain.
i have alias to include() in my functions.php file:
function render_template($template)
{
include($template);
}
and simple template.html :
Hello, <?php echo $name ?>
But unfortunately, alias function gave me this output:
require 'functions.php';
$name = "world";
include('template.html'); // Hello, world
render_template('template.html'); // PHP Notice:Undefined variable: name
why is that? and how i can fix this?
thanks.
You have two more options to make it work around the scope issue. (Using global would require localising a long list of vars. Also it's not actually clear if your $name resides in the global scope anyway and always.)
First you could just turn your render_template() function into a name-resolver:
function template($t) {
return $t; // maybe add a directory later on
}
Using it like this:
$name = "world";
include(template('template.html'));
Which is nicer to read and has obvious syntactical meaning.
The more quirky alternative is capturing the local variables for render_template:
$name = "world";
render_template('template.html', get_defined_vars());
Where render_template would require this addition:
function render_template($template, $vars)
{
extract($vars); // in lieu of global $var1,$var2,$var3,...
include($template);
}
So that's more cumbersome than using a name-resolver.
The variable $name is not visible at the point where include is called (inside function render_template). One way to fix it would be:
function render_template($template)
{
global $name;
include($template);
}
Its a Scope Problem, you can set the variable to global, or encapsulate the whole thing a little bit more, for example like that:
class view{
private $_data;
public function __construct(){
$this->_data = new stdClass();
}
public function __get($name){
return $this->_data->{$name};
}
public function __set($name,$value){
$this->_data->{$name} = $value;
}
public function render($template){
$data = $this->_data;
include($template);
}
}
$view = new view;
$view->name = "world";
$view->render('template.html');
template.html :
Hello <?php print $data->name; ?>
If $name is in the global scope then you can get around it by declaring the variable global with the function. But a better solution would be to re-architect the code to require passing the relevant variable value into the function.
This is expected.
Look here.
You would be interested in the following quote, "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. An exception to this rule are magic constants which are evaluated by the parser before the include occurs".
I have A.php and B.php
A.php
<?php
error_reporting(E_ALL);
ini_set("display_errors",1);
class myClass
{
function hello()
{
return 'hello';
}
}
?>
B.php
<?php
error_reporting(E_ALL);
ini_set("display_errors",1);
require_once('/A.php');
$a = new myClass();
testing();
function testing()
{
echo $a ->hello();
}
?>
B.php inherits A.php ,
if i run B.php,but it show
"Fatal error: Call to a member function hello() on a non-object."
So the question is simple, how can i correct this ,but "$a = new myClass();" is not inside the function, since in .NET world can do this, i believe PHP also possible.
And one more question is, what is the modify of function in A.php ,if i have not state private/public/protected?
This is not inheritance. B.php merely includes A.php. This means all the code in A.php becomes available to the execution context of B.php.
Inheritance is a class relationship
class A{}
class B extends A{}
Class B can be said to inherit from A. So, a hierarchy has been formed.
Much as we humans inherit traits from our parents, classes inherit properties from their parents. For this reason, it is very common to talk about these classes in terms of their place in the hierarchy. Class A is a parent to class B. Class B is a child to class A.
But the actual problem you are having, the source of the error message, is a scope issue. You create $a in the global scope but attempt to access it from within a function's scope, in this case testing().
The best way to solve this is to pass your instances of myClass into testing()
$a = new myClass();
testing( $a );
function testing( $myClassObj )
{
echo $myClassObj->hello();
}
And to answer your final question - in PHP5 - class members not explicitly declared with an access modifier become implicitly public.
If you want to use $a in the function, you need to either put
global $a;
as the first line of the function, or access it as $GLOBALS['a']
use this
function testing()
{
global $a;
echo $a ->hello();
}
A couple of things I would change here, I'll explain in a moment.
A.php
<?php
error_reporting(E_ALL);
ini_set("display_errors",1);
class myClass
{
// Here, access modifier.
public function hello()
{
return 'hello';
}
}
?>
B.php
<?php
error_reporting(E_ALL);
ini_set("display_errors",1);
require_once('/A.php');
testing();
function testing()
{
// Here, change where variable is defined to place it in scope.
$a = new myClass();
echo $a ->hello();
}
?>
When no access specifier is given on a method, it defaults to public. However, it is generally better to just declare what you want the method to have. You will appreciate this if you find yourself actively coding in multiple languages as they will each have a different default.
Right now the variable $a is not in the scope of the function testing(). Allow me to rearrange your program and you shall see why. You could have written it, like so:
B.php
<?php
function testing()
{
echo $a ->hello();
}
error_reporting(E_ALL);
ini_set("display_errors",1);
require_once('/A.php');
$a = new myClass();
testing();
?>
You see, where testing() is now defined, $a does not exist. It hasn't been defined yet. So it is not inside testing()'s scope. You'll have to either define $a inside testing() or else pass it in as a parameter. In my first pass, I changed your code to define $a inside testing(). If you will need to use it in multiple functions, then I would suggest changing testing() to take it as a parameter. Like this:
function testing(myClass $a) {
echo $a->hello();
}
Then pass it in this way:
$a = new myClass();
testing($a);
I believe $a is not defined in the function. Try using global $a first, and then calling hello().