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.
Related
Is it possible to be able to dynamically set a php static class variable? In the example below i want to pass a string representation of the variable i want to set to a function "databaseInit" which then sets the var...
class app {
static $database_smf;
static $database_phpbb;
/**
* Initialise the app
*/
static function init(){
// No initialise the db connection
self::databaseInit('database_phpbb');
self::databaseInit('database_smf');
}
static function databaseInit( $database ){
// is it possible to dynamically set the static var based on the param provided? eg:
self::[$database] = true;
}
}
You can use a plain variable variable name:
static function databaseInit( $database ){
self::$$database = true;
}
.. but you should really rework it to just keep an array and manipulate the keys of the array instead, as that will keep all the settings inside a single namespace instead of potentially doing weird stuff with other static variables if a name is mistyped, etc.
class app {
static $databases = [];
...
static function databaseInit($database) {
self::$databases[$database] = true;
}
}
And the next step would be to make the class non-static instead, so it can be easier tested and will keep its state locally instead.
Yes that is possible.
Just a little change in your code:
Use:
self::$$database = true;
Instead of:
self::[$database] = true;
class app {
static $database_smf;
static $database_phpbb;
Full code:
/**
* Initialise the app
*/
static function init(){
// No initialise the db connection
self::databaseInit('database_phpbb');
self::databaseInit('database_smf');
}
static function databaseInit( $database ){
// is it possible to dynamically set the static var based on the param provided? eg:
self::$$database = true;
}
}
I started using classes in PHP, and I have the following code:
class webConfig
{
public $SALT1 = "3525";
public $SALT2 = "2341";
public $SALT3 = $SALT1.$SALT2;
}
But this gives me 500 Internal Server Error, which means that I am doing something wrong.
Is there any way of doing this without using any function, including construct?
This does not work aswell:
class webConfig
{
public $SALT1 = "3525";
public $SALT2 = "2341";
public $SALT3 = $this->SALT1.$this->SALT2;
}
In PHP; Expressions are not allowed as Default Values of any Property. For this reason, PHP is simply saying that you should not even imagine doing that in the first place. But, fortunately then; this is why you have the Constructor Method — to help you initialize some class Properties, assign Default values to Member Properties using Expression (like in your case), etc.... Using a Constructor, your class could look like the Snippet below and it is expected to work as well:
<?php
class webConfig {
public $SALT1 = "3525";
public $SALT2 = "2341";
public $SALT3;
public function __construct(){
// SET THE VALUE $SALT3 HERE INSTEAD
$this->SALT3 = $this->SALT1 . $this->SALT2;
}
}
Alternatively; you may even initialize all the Properties of the Class within the Constructor like so:
<?php
class webConfig {
public $SALT1; //<== NOTICE THAT THIS PROPERTY IS NOT INITIALIZED.
public $SALT2; //<== NOTICE THAT THIS PROPERTY IS NOT INITIALIZED.
public $SALT3; //<== NOTICE THAT THIS PROPERTY IS NOT INITIALIZED.
public function __construct(){
$this->SALT1 = "3525";
$this->SALT2 = "2341";
$this->SALT3 = $this->SALT1 . $this->SALT2; //<== YET AGAIN; SET THE VALUE
//<== OF $SALT3 LIKE BEFORE
}
}
class global_class extends Timemine
{
private $DBPrefix = '';
public function __construct()
{
global $DBPrefix;
// Load settings
self::loadsettings();
$this->database = $db;
$this->DBPrefix = $DBPrefix;
.
.
$DBPrefix is declared outside as a private but inside the function its redeclared? as global.
Is this correct?
Thank you.
$DBPrefix is actually not redeclared. There are two versions of the variable. The first one (private $DBPrefix = '';) is a member variable, the second one (global $DBPrefix) is a local scope variable of the constructor (which refers to a third global version of the variable, but let's leave this aside). See the PHP docs about variable scope for more information
The value of the member variable is then set to the same value as the local scope variable with this line: $this->DBPrefix = $DBPrefix; So after this line both versions have the same value. Technically, your code is correct.
However, using globalis usually bad. It is probably better to pass $DBPrefix in the constructor like:
public function __construct($DBPrefix) {
// Load settings
self::loadsettings();
$this->database = $db;
$this->DBPrefix = $DBPrefix;
}
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.
i have a config class which is an abstract class. I would like to set it up so it automatically detects which server the site is on and then assigns appropriate constants. I get an error on line ten $this->hostName = $_SERVER['SERVER_NAME']; expecting `T_FUNCTION.
What is the correct way to do this and is there a better way to do this? Here is the first part of my class
abstract class config{
public $hostName;
public $hostSlices;
public $domain;
echo $_SERVER['SERVER_NAME'];
//strips out the "www" from the server name but only if it has the name on it .
$this->hostName = $_SERVER['SERVER_NAME'];
$this->hostSlices = explode(".",$this->hostName);
if($this->hostSlices[0]=="www"){array_shift($this->hostSlices);}
$this->domain = join(".",$this->hostSlices);
//depending on which domain is used, different config setup is used.
switch ($this->domain){
case "localhost":*/
const HOST = "localhost";//would http://localhost/ work as well. In that case, then this and the SITE_ROOT could be the same variable and i would preferentially set them depending on the host that the site is on.
const USER = "root";
const PWD = "xxxxxxx";
const NAME = "hurunuitconz";//database name
//public $name = "hello from the config class";//you cannot access variables from an abstract class you should define constants and then the can be used anywhere
###########Location of file groups########
const SITE_ROOT = "http://localhost";
const ADMIN_IMAGES = 'http://localhost/images/user_images/admin_images';
break;
case "charles.hughs.natcoll.net.nz":
const HOST = "charles.hughs.natcoll.net.nz";//would http://localhost/ work as well. In that case, then this and the SITE_ROOT could be the same variable and i would preferentially set them depending on the host that the site is on.
const USER = "charles_andrew";
const PWD = "xxxxxxx";
const NAME = "charles_hurunuitconz";//database name
###########Location of file groups########
const SITE_ROOT = "http://charles.hughs.natcoll.net.nz/_Assignments/Industry/www";//this is just confusing the way natcoll makes us do this.
const ADMIN_IMAGES = 'http://charles.hughs.natcoll.net.nz/_Assignments/Industry/www/images/user_images/admin_images';
break;
}
An abstract class shouldn't allow you to set private data (only an inherited concrete class).
Also, take a look at this link in stackoverflow for an interesting discussion on SERVER_NAME vs. HTTP_HOST
You have to wrap all that code in a constructor or better yet a function called init() or somthing. Then when you override init in the child classes you would call parent::init(). Did you mean to make this class static, not abstract?
The way you're structuring your code is just not right. PHP does allow for many crazy things, but defining constants and outputting code as a part of an abstract class makes no sense whatsoever in terms of OOP.
What you probably mean to do is to have a helper class that defines configuration settings based upon the local server name. To do so, you have a couple options:
Option 1) Create a regular class with a constructor.
class Config {
public $x;
public $y;
public function __construct() {
switch (...) {
$this->x = 2;
$this->y = 3;
}
}
}
And use it like this:
$config = new Config();
echo "Variable y: " . $config->y;
Option 2) Static method in an abstract class.
abstract class Config {
public $boolInitialized = false;
public static function init() {
if (self::$boolInitialized) {
return;
}
self::$boolInitialized = true;
switch (...) {
self::$x = 1;
self::$y = 2;
}
}
public static function getX() {
self::init();
return self::$x;
}
}
And use it like this:
echo Config::getX();
You cant output something in a class without declaring first a method
this will fail
abstract class fo
{
public $fo;
echo $fo;
}
**but this will work**
abstract class fo
{
public $fo;
public function __construct()
{
$this->fo = $_SERVER['SERVER_NAME'];
}
public function sayFo()
{
echo $this->fo;
}
}