Accessing a global array inside class constructor - php

My aim is to retrieve some data from a global array which is defined in another PHP file. My code is running inside database.php file and the array I want to use is inside config.php file. I understand that accessing a global array inside class is not a good idea, but I want to do it so because of some reasons.
My code is as below:
config.php
$CONFIG = array();
// ...
$CONFIG["DATABASE"] = array();
$CONFIG["DATABASE"]["USERNAME"] = "user";
$CONFIG["DATABASE"]["PASSWORD"] = "pass";
$CONFIG["DATABASE"]["HOSTNAME"] = "127.0.0.1";
$CONFIG["DATABASE"]["DATABASE"] = "my_db";
// ...
database.php
require('config.php');
class Database
{
protected $m_Link;
private $m_User;
private $m_Pass;
private $m_Host;
private $m_Data;
private $m_bConnected;
public function __construct()
{
global $CONFIG;
$this->m_User = $CONFIG["DATABASE"]["USERNAME"];
$this->m_Pass = $CONFIG["DATABASE"]["PASSWORD"];
$this->m_Host = $CONFIG["DATABASE"]["HOSTNAME"];
$this->m_Data = $CONFIG["DATABASE"]["DATABASE"];
$this->m_bConnected = false;
$this->Connect();
}
// ...
};
There is no error given (except for the failed database connection notification).
I can't access to the array elements. For instance $CONFIG["DATABASE"]["USERNAME"] returns an empty value even though it was initialized with "user" string in the config.php.
How should I modify my code so that it can this global array can be accessible inside the class constructor?
(Note: PHP version is 5.3.0)

Your code looks right, so I think you should just debug it. Try to output $CONFIG before creating instance of Database class, $CONFIG may be redefined/changed somewhere in your code. And don't just check one value in array - output whole array with var_dump/print_r.

Instead of
$CONFIG = array();
use
$GLOBALS['CONFIG'] = array();

I think some how global is not working in __construct(). I am not sure if it is a bug or it is designed as it is.
For code
<?php
class Test {
public $value;
function __construct() {
global $value;
$value = "I am a test.";
}
}
$test = new Test();
echo $test->value;
You will see nothing when above php runs.
However, if you do not use global, but use $this->value, everything works fine.
<?php
class Test {
public $value;
function __construct() {
$this->value = "I am a test.";
}
}
$test = new Test();
echo $test->value;
If you insist to get a reason. I think maybe __construct() is design to initialize the properties. Some code like $this->value = $value is using a lot in __construct(). So maybe the php designer thinks it is not good practice to use global in __construct(). However. I can not find a word mentioned it in php manual after all.

Related

How to fix PHPUnit losing global variable value between consecutive test runs from the same class? [duplicate]

I am putting PHPUnit testing into an existing project. Global constants variables are used extensively. In my unit test functions are failing because the global variables are null. Here is an example of a failing test
static $secret_key = "a secret Key";
class secret_key_Test extends PHPUnit_Framework_TestCase
{
function test_secret_key()
{
global $secret_key;
$this->assertEquals($secret_key, "a secret Key");
}
}
>> Failed asserting that 'a secret Key' matches expected null
Any help would be greatly appreciated
Update:
I have tried removing static and adding
protected $backupGlobals = FALSE;
To the class declaration without success.
This answer doesn't work. I asked a virtually identical question here and wound up with an answer that makes more sense; you can't overwrite the protected property $backupGlobals in the test Class that PHPUnit will see. If you're running on the command line, it seems that you can get Globals to work by creating an xml configuration file and setting up backupGlobals to false there.
EDIT: You need to declare $secret_key both global and assign a value to it in the global space when using PHPUnit. PHP defaults to placing globally initialized variables into the global namespace, but PHPUnit changes this default when backing up globals!
The following changes need to happen:
global $secret_key; // Declaring variable global in global namespace
$secret_key = "a secret Key"; // Assigning value to global variable
Your code should work now.
You should ask phpunit not to backup globals
protected $backupGlobals = FALSE;
like it is said in the original article from S. Bergmann: https://web.archive.org/web/20130407024122/http://sebastian-bergmann.de/archives/797-Global-Variables-and-PHPUnit.html
You will have to setup your global variable while bootstraping your testing. Here is a sample code of how I wrote test
/**
* Class to allow us set product on the fly
*/
class Product
{
public function __call($method, $args)
{
if (isset($this->$method)) {
$func = $this->$method;
return call_user_func_array($func, $args);
}
}
}
/**
* UssdShortcode Tester
*/
class ShortCodeTester extends WP_UnitTestCase {
protected $product;
public function setUp()
{
$this->product = new Product;
$this->product->get_id = function(){ return 50; };
$GLOBALS['product'] = $this->product;
}
/**
* A single example test.
*/
function test_it_can_display_ussd_shortcode() {
$displayer = new UssdShortCodeDisplayer;
$expected = view('show-product-short-code',['product_id' => $this->product->get_id() ]);
$results = $displayer->display($this->product->get_id());
// $this->assertRegexp('/'.$expected.'/', $results);
$this->assertEquals($expected,$results);
}
}

Variable not being picked up

In my config.php file I have a variable that is set to 'localhost'.
$CONFIG['MySQLi']['host'] = "localhost";
However, when I include this config.php in my database class, I test it by calling the variable in an echo through the __construct() method
public function __construct() {
echo $CONFIG['MySQLi']['host'];
}
But then for some reason, I get this error:
Notice: Undefined variable: CONFIG in C:\xampp\htdocs\Muse\classes\class.database.php on line 15
However I get no errors for importing the config.php file. Would someone be able to explain why this is happening? Thankyou
The function doesn't know about variables that were defined outside due to variable scope.
public function __construct() {
global $CONFIG;
}
should resolve this. However, this is usually considered bad practice.
Alternatively you can use static attributes as shown by Kohjah Breese, pass the config array to the constructor (as suggested by AlexP) or use a construct like the following.
/config/mysqli.php
<?php
return array(
//what now is $CONFIG['MySQLi']
);
and in the function
public function __construct() {
$config = include '/config/mysqli.php';
}
For anybody who still wants the answer to this question, another good way to do it is by DEFINING a variable.
define('VARIABLE', 'VALUE');
And then call it by doing VARIABLE. E.g.
<?php echo VARIABLE; ?>
AS above, function do not have access to standard variables stored outside of them, but a better solution is to create a class you want to store global variables in. I use something like this:
class Conf
{
// Project
static $CODE = 'F';
static $NAME = 'For';
static $ACCESS = 'public';
static $CHARSET = 'utf-8';
static $DATA = array();
static $CACHE = false;
static $HTMLINDENT = true;
// Diagnostic
static $SHOWEXECTIME = true;
// Paths
static $PATH_FILESYSTEM = '';
static $PATH_CORE = '/var/www/sites/core';
static $PATH_DOMAIN = 'localhost';
static $PATH_URL = 'http://localhost/sites/for/';
static $PATH_CACHE = 'cache/';
static $PATH_CSS = 'css/';
static $PATH_DATA = 'data/';
static $PATH_JS = 'js/';
static $PATH_LOG = 'logs/';
static $PATH_XML = 'xml/';
static $PATH_XSL = 'xsl/';
// DB Details
static $DB_USER = 'root';
static $DB_PASS = 'pass';
static $DB_DSN = 'mysql:host=localhost;dbname=for;charset=utf8';
}
My tests showed this to be the quickest solution. Some people use constants, which are very slow. Globals have been depreciated, and are a security risk.
You can access any of these vars from anywhere in PHP using Conf::$NAME; etc.

PHP Class: Array deinitialized after constructor?

Im making a class in php, but Im having some problems with one of the class variables. I declare a private variable, then in the constructor set it. However, later in the class I have a method that uses that variable. The variable in this case is an array. However, the method says the array is blank, but when I check it in the constructor, it all works out fine. So really the question is, why does my array clear, or seem to clear, after the constructor?
<?php
class Module extends RestModule {
private $game;
private $gamearray;
public function __construct() {
require_once (LIB_DIR."arrays/gamearray.php");
$this->gamearray = $gamesarray;
$this->game = new Game();
$this->logger = Logger::getLogger(__CLASS__);
$this->registerMethod('add', array(Rest::AUTH_PUBLIC, Rest::AUTH_USER, Rest::AUTH_ADMIN), true);
$this->registerMethod('formSelect', array(Rest::AUTH_PUBLIC, Rest::AUTH_USER, Rest::AUTH_ADMIN), false);
}
public function add(){
$game = Utility::post('game');
}
public function formSelect(){
$gamename = Utility::get('game');
$this->$gamearray[$gamename];
}
}
The array is pulled in from another file because the array contains a lot of text. Didn't want to mash up this file with a huge array declared in the constructor. The scrolling would be tremendous. Any explanation would be nice, I like to understand my problems, not just fix em'.
You have a typo:
public function formSelect(){
$gamename = Utility::get('game');
$this->gamearray[$gamename]; // Remove the $ before gamearray
}
Moreover, in your case, include is better than require_once.
If you want to go deeper, you could rewrite $gamearray assignment like this:
// Module.php
$this->gamearray = include LIB_DIR.'arrays/gamearray.php';
// gamearray.php
return array(
// Your data here
);

Creating an object and using it in another

I am fairly new to object oriented programming. I made this class which connects to mysql database to be called from models. Is there any way i can include 'database.class.php'(my db class file)
in index.php, make it global and then access it from any object like so
$object = new object;
$object->dofunc();
Also another question is dofunc() expects an array for argument, how do i make this array also global so it can be accessed from ANY where!
Here is my db class
<?php
class Database {
private $db;
public function connect($config) {
if (is_array($config)) {
extract($config);
$db = mysqli_connect($host, $username, $password);
if ($db) {
echo "balbabla";
if (mysqli_select_db($db, $database)) {
}
else {
throw new exception("<br/><strong>Could not connect to $database under $host</strong>");
}
}
else {
throw new exception("<br/><strong>Could not connect to mySQL database! Please check your details</stromg>");
}
}
}
}
?>
Also this is the file that contains the array
<?php
//Configuration for the MVC Framework
$_SETTINGS = array();
//Routing settings!
//Default controller(This controller will be loaded if there is none mentioned in the URI)
$_SETTINGS['default_controller'] = 'User';
//Default method(This will be the default method run if no method is mentioned in the URI)
$_SETTINGS['default_method'] = 'Register';
//Database settings
$DB_SETTINGS['host'] = 'localhost';
$DB_SETTINGS['username'] = 'root';
$DB_SETTINGS['password'] = 'foobar';
$DB_SETTINGS['database'] = 'freelance';
?>
Thanks in advance
Is there any way i can include 'database.class.php'(my db class file) in index.php, make it global
You can, but you shouldn't.
Also another question is dofunc() expects an array for argument, how do i make this array also global so it can be accessed from ANY where!
Again you shouldn't.
Dependency injection is the way to go.
To access a global variable from within a function, use the global keyword. For example, to access $DB_SETTINGS from Database::connect(), you could do:
public function connect() {
global $DB_SETTINGS;
...
The array would then be accessible inside that function.
As for globally accessible classes, they are automatically just that. Defining a class makes it available anywhere.

Handling Global Variables between different Classes and Functions in PHP

What is the best way to make a variable accessable to all classes.
For example, I want to have a configuration file (Call it config.php) that is going to have a variable like so:
$server_url = "www.myaddress.com";
And I have a main library type file that contains a bunch of classes that need to access the $server_url. So here begins that main library file:
require 'config.php';
class one {
function a() {
$html = "<a href='$server_url/main.php'>LINK</a>"
return $html;
}
function b() {
$html = "<a href='$server_url/about.php'>LINK</a>"
return $html;
}
}
class two {
function new() {
$html = "<a href='$server_url/blah.php'>LINK</a>
}
}
What would be the best way to make $server_url from the config.php available to every function? Or at least available to all the functions in a class?
Personally I would use a static entity to hold all configuration values.
Usually, most php applications have a single entry point (index.php) that can load up the config.php file and make the static entity available from that point.
If your application has multiple entry points, then you will need to include config.php in each of these points.
Something like this:
<?php
class Configurator{
private static $_configuration = array();
public static function write($key, $value) {
self::$_configuration[$key] = $value;
}
public static function read($key) {
return self::$_configuration[$key];
}
}
Configurator::write('server', 'http://localhost');
Configurator::read('server');
?>
CakePHP has a similar class: http://api.cakephp.org/view_source/configure/
Make the config into a class in itself and use a static methods either along the line of serverUrl() or get('server_url'). Then call them like any other static methods to classes (I'll choose the latter in this example):
$html = "<a href='" . Config::get ('server_url') . "/main.php'>LINK</a>";
The config class could be pretty slim, use a constructor like:
public function __construct (array $config)
{
foreach ($config as $key => $value)
{
$this->$key = $value;
}
}
And add the get() method along these lines:
public function get ($key)
{
return $this->$key;
}
This way you can read the config from an array that you can have as a separate, actual config file, and reuse the same code for multiple projects.
You'll also be able to access the variables from anywhere in the project and you'll get a sort of pseudo-namespacing (in case the project needs to run on an older version of PHP).
Please, don't copy the code verbatim, it's written as an example.
think of globals are evil. Try to use design patterns to get access to some configs globally.
I'm a big fan of singletons to get global access to objects, arrays or other data-types.
<?php
class st {
static $_this;
function __construct(){
self::$_this = $this;
}
static function &getInstance(){
return self::$_this
}
static function set($key, $value){
self::$_this[$key] = $value;
}
static function &get($key){
return self::$_this[$key];
}
}
// Usage
new st();
st::set('foo', 'bar');
// In some class
st::get('foo'); //return 'bar'
// Or when there are some classes/objects
st::getInstance()->foo->bar();
$st =& st::getInstance();
$st->foo->bar();
?>
Roughly wrote down a small singleton, but don't know whether there is a syntax error.
While handling with getInstance it's certain that you define the variable by reference =&
Define a constant in config.php like:
define('SERVER_URL', '...');
In your class:
echo SERVER_URL;
What works for me the best is to use a config file like config.ini
And then to use $my_config = parse_ini_file(file path/config.ini');
Now everywhere in my code including inside functions and classes, I will use
The PHP superglobal like this:
$GLOBALS["my_config"]['my_global_var']

Categories