i'd like to set up some global variables for storing several things.
i've tried it like this:
function init_web()
{
$webname = "myweb";
$web['webname'] = $webname;
$web['server_root'] = $_SERVER['DOCUMENT_ROOT']."/$webname/";
$web['lang']="en";
}
the problem is that i can't access those variables inside of functions ..
i've tried using global $web; but didnt help.
what's the trick to get it global?
thanks
While you'll get the usual "global variables are bad" crying, here's the basics:
$web = array(); // define the var at the "top level" of the code tree, outside any functions/classes.
function init_web() {
global $web; // make it visible in the function
$web['lang'] = 'en'; // make some settings
}
basically, you had it, but hadn't defined the variable outside the function. Just saying 'global' within the function won't magically create one outside the function - it already has to exist before you try to "internalize" it to the function and change/access its contents.
You are on the right track:
$web = array();
function init_web()
{
global $web;
$webname = "myweb";
$web['webname'] = $webname;
$web['server_root'] = $_SERVER['DOCUMENT_ROOT']."/$webname/";
$web['lang']="en";
}
You can define them constant
define('WEBNAME',"myweb");
and can use everywhere in your application because constant are global in nature by default.
and this is the way to store constant as constant as they never changed dynamically until you move to new server or change configuration.
you can use session variables:
session_start(); // at the top of the php page
function init_web()
{
$webname = "myweb";
$_SESSION['webname'] = $webname;
$_SESSION['server_root'] = $_SERVER['DOCUMENT_ROOT']."/$webname/";
$_SESSION['lang']="en";
}
now they can be 'globally' accessable :-)
Declare $web outside the function and reference it inside with the $GLOBALS superglobal:
// Declare in global scope
$web = array();
function init_web()
{
$webname = "myweb";
// Access via superglobal in function scope
$GLOBALS['web']['webname'] = $webname;
$GLOBALS['web']['server_root'] = $_SERVER['DOCUMENT_ROOT']."/$webname/";
$GLOBALS['web']['lang']="en";
}
If you're just storing scalar values (strings, ints, floats - not arrays, objects), you should use define().
This will make your configurations global and constant.
As to answer your question,
First define your variables outside the scope of that function (perhaps in a config file) and then use the global keyword to make it global when you need them.
Related
I am well aware that globals are evil and this is an issue I will deal with later. It's not my codebase, but I've been assigned some cleaning up tasks.
Trying to smarten up a codebase, I decided to implement simple routing by using a package known as AltoRouter - I've worked with it before and it has worked fine for my purposes.
Now, the codebase is using a large amount of variables declared in the global scope. Usually, these variables are then fetched by using the globalkeyword. But for some reason, this doesn't work when I'm working inside a closure.
Consider this simple routing example:
<?php
require 'vendor/autoload.php';
$router = new AltoRouter();
$router->map('GET', '/shops/[i:id]', function($id) {
$_GET['shop_id'] = $id;
require 'go_to_shop.php';
});
$match = $router->match();
if( $match && is_callable( $match['target'] ) ) {
call_user_func_array( $match['target'], $match['params'] );
}
This calls my closure that sets a variable and requires a file.
This produces an error:
Fatal error: Call to a member function get() on null in
/vagrant/Core/CampaignHandler.php on line 71
Now, the code being called doing this is the following (line 70-71):
// Inside a method
global $serviceContainer;
$dispatcher = $serviceContainer->get("dispatcher");
The $serviceContainer is being declared by including a file early on:
$serviceContainer = new ServiceContainer();
$serviceContainer->set("dispatcher", new EventDispatcher());
Basically, if I move the contents of the closure outside of the closure, everything works perfectly - but as soon as I'm doing it from inside the closure, all variables accessed via the global scope is empty - and I have no idea as to why.
I've tried using use on the closure, this didn't work either.
I'm mostly looking for an explanation rather than a solution.
Globals are evil for a reason. You get the error because the global is not initialized at the time when function is being called. The mess of globals and requires is the exact issue and you are already trying to deal with it.
There is no problem to use globals in closure per se. This example works perfectly fine:
global.php:
<?php
class Foo {
public function bar() { return 'bar';}
}
$foo = new Foo;
test.php:
<?php
require 'global.php';
$test = function($param) {
global $foo;
echo $param, $foo->bar();
}
call_user_func_array($test, ['baz']);
so php test.php outputs bazbar;
I'm pretty sure that the $serviceContainer variable does not exist in the global scope, but the question leaves that part out.
Can't you pass the container to the anonymous function using a use( $serviceContainer ) statement? That'd be a far cleaner solution then having to rely on globals.
function($id) use( $serviceContainer ) {
$_GET['shop_id'] = $id;
require 'go_to_shop.php';
}
Off-topic: not sure what you're doing with that id variable later on and why you're putting it back into the $_GET variable like that, but please be careful.
Please check the manual for anonymus functions–also known as closures, which in real are objects.
http://php.net/manual/en/functions.anonymous.php
Theses callables have specific functions for extending their scopes.
See: Example #3 Inheriting variables from the parent scope.
$message = 'hello';
// No "use"
$example = function () {
var_dump($message);
};
$example();
// Inherit $message
$example = function () use ($message) {
var_dump($message);
};
$example();
Sure you want to assign a value to the $_GET global var?
$_GET['shop_id'] = $id;
The shop ID in your route you can extract from altorouter parameters. (See documentation.)
$router->map( 'GET', '/', function() { .. }, 'home' );
// assuming current request url = '/'
$match = $router->match();
/*
array(3) {
["target"] => object(Closure)#2 (0) { }
["params"] => array(0) { }
["name"] => 'home'
}
*/
Or if you want to store an ID for a session use $_COOKIES or $_SESSION global variables.
Is there any way to do this / specify this in the php.ini configuration file? It would be really nice, at least for local server purposes, just to write functions without having to write the global keyword every time a global variable is used within the method.
Any way to do this?
EDIT:
What I mean is being to simply write this:
Example file "index.php":
$MY_ARRAY = array();
include("functions.php");
And then in "functions.php":
function addToArray($pMessage) {
$MY_ARRAY[] = "<a href='somelink.php'>$pMessage</a>";
}
Instead of:
And then in "functions.php":
function addToArray($pMessage) {
global $MY_ARRAY;
$MY_ARRAY[] = "<a href='somelink.php'>$pMessage</a>";
}
Yeah! You can setup a prepend file in PHP.
See: http://www.php.net/manual/en/ini.core.php#ini.auto-prepend-file
I still do not understand the purpose. But if I need to just remove the GLOBAL keyword from mentioning everytime, I would prefer to use a class with static array.
Something like this:
<?php
// Config.php
class Config {
public static $MY_ARRAY = array();
}
?>
And then include this file from your loader just call like this:
function addToArray($pMessage) {
Config::$MY_ARRAY[] = "<a href='somelink.php'>$pMessage</a>";
}
That will work.
I want to validate a form with php.
Therefor I created a class "benutzer" and a public function "benutzerEintragen" of this class to validate the form:
class benutzer
{
private $username = "";
private $mail = "";
private $mail_check = "";
private $passwort = "";
private $passwort_check = "";
public $error_blank = array();
public $error_notSelected = array();
public $error_notEqual = array();
public function benutzerEintragen () {
$textfields[0] = $this->username;
$textfields[1] = $this->mail;
$textfields[2] = $this->mail_check;
$textfields[3] = $this->passwort;
$textfields[4] = $this->passwort_check;
foreach ($textfields as $string) {
$result = checkFormular::emptyVariable($string);
$error_blank[] = $result;
}
In the function "benutzerEintragen" i filled the variables "username,mail" and so on with the appropriate $_POST entries (not shown in the code above). The call
checkFormular::emptyVariable($string)
just returns "TRUE" if the field is not set or empty otherwise FALSE.
Now when i try to create a new instance of this class, execute the function and get access to $error_blank[0] the array is empty!
if (($_SERVER['REQUEST_METHOD'] == 'POST')){
$BENUTZER = new benutzer();
$BENUTZER->benutzerEintragen();
echo $BENUTZER->error_blank[0];}
So the last line is leading to a "Notice: Undefined offset: 0". It seems to be related to the array structure, because if i do
echo $BENUTZER->mail;
I get any input I wrote in the form, which is correct. Also the foreach loop seems to do the right thing when i run the debugger in phpEd, but it seems like the array "error_blank" is erased after the function is executed.
Any help would be greatly appreciated. Thanks in advance.
There is a scope problem here. You do have a class attribute with the name. Unlike in Java where using a local variable with the same name as a class variable automatically selects the class attribute this is not the case in PHP.
Basically you are saving your output in a local variable which gets discarded once you leave the function. Change $error_blank[] = $result; to $this->error_blank[] = $result; and you should be fine.
First of all this seems overly complicated way to do a simple task, but that wasn't actually the question.
You are creating a new $error_blank variable that is only in function scope. If you wish to use the class variable you should use $this->error_blank[]
I have a file which I include say:
require_once("../../constructor/database.php");
$stuff_inside_include_file->doThis() ; //ACCESSIBLE
function createUser(){
$stuff_inside_include_file->doThat(); //NOT-ACCESSIBLE (object not found)
}
function deleteUser(){
. ...
If I move the require statement into the scope of the function, then it works. Otherwise, it doesn't. Is there a better solution?
Thank you in advance.
You can try:
function createUser($stuff_inside_include_file){
$stuff_inside_include_file->doThat();
}
it should work, I think.
The best solution would be to not create global variables, but this would also work:
require_once("../../constructor/database.php");
$stuff_inside_include_file->doThis() ; //ACCESSIBLE
function createUser(){
global $stuff_inside_include_file;
$stuff_inside_include_file->doThat(); //ACCESSIBLE
}
function deleteUser(){
. ...
But really.. "Think globally, act in local scope".
I believe this is an issue with the variable not being global.
e.g.
$i = 10;
function pooppoop() {
$i = 11;
#this only sets the local variable i to 11
}
So you will want to put a global $i; at the top of your function. Obviously replace $i with the variable you are having trouble accessing.
I looks like the $stuff_inside_include_file variable is in the global scope, so you should be able to do this:
function createUser(){
global $stuff_inside_include_file;
$stuff_inside_include_file->doThat();
}
I am trying to assign a variable to a class in PHP, however I am not getting any results?
Can anyone offer any assistance? The code is provided below. I am trying to echo the URL as shown below, by first assigning it to a class variable.
class PageClass {
var $absolute_path = NULL;
function get_absolute_path(){
$url = $this->absolute_path;
echo $url;
}
}
$page = new PageClass();
$page->absolute_path = "http://localhost:8888/smile2/organic/";
$page->get_absolute_path(); //this should echo the URL as defined above - but does not
It also works for me.
Take a look at a live example of your code here.
However, there are a few things you should change about your class.
First, Garvey does make a good point that you should not be using var. That's the older PHP4, less OOP conscious version. Rather declare each variable public or private. In fact, you should declare each function public or private too.
Generally, most classes have private variables, since you usually only want to change the variables in specific ways. To achieve this control you usually set several public methods to allow client functions to interact with your class only in restricted predetermined ways.
If you have a getter, you'd probably want a setter, since these are usually used with private variables, like I described above.
A final note is that functions named get usually return a value. If you want to display a value, it is customary to use a name like display_path or show_path:
<?php
class PageClass
{
private $absolute_path = NULL;
public function set_absolute_path($path)
{
$this->absolute_path = $path;
}
public function display_absolute_path()
{
echo $this->absolute_path;
}
}
$page = new PageClass();
$page->set_absolute_path("http://localhost:8888/smile2/organic/");
$page->display_absolute_path();
// The above outputs: http://localhost:8888/smile2/organic/
// Your variable is now safe from meddling.
// This:
// echo $this->absolute_path;
// Will not work. It will create an error like:
// Fatal error: Cannot access private property PageClass::$absolute_path on ...
?>
Live Example Here
There's a section on classes and objects in the online PHP reference.
class PageClass {
public $absolute_path = NULL;
function get_absolute_path(){
$url = $this->absolute_path;
return $url;
}
}
$page = new PageClass();
$page->absolute_path = "http://localhost:8888/smile2/organic/";
echo $page->get_absolute_path();
Works fine for me.
Have you checked that the script and esp. the code in question is executed at all?
E.g. add some unconditional debug-output to the script. Or install a debugger like XDebug to step through the code and inspect variables.
<?php
class PageClass {
var $absolute_path = NULL; // old php4 declaration, see http://docs.php.net/oop5
function get_absolute_path() { // again old php4 declaration
$url = $this->absolute_path;
echo "debug: "; var_dump($url);
echo $url;
}
}
$page = new PageClass();
$page->absolute_path = "http://localhost:8888/smile2/organic/";
echo "debug: page->get_absolute_path\n";
$page->get_absolute_path();