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;
}
Related
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
}
}
I have database credential variables from a file, named config.php :
$db_server = 'localhost';
$db_user = 'username';
$db_password = 'secret'
$db_name = 'dbname';
now, I have a PHP class under /class folder and it works perfectly fine for CRUD process. named MysqlCrud.class.php :
class Database {
private $db_host = 'localhost'; // Change as required
private $db_user = 'username'; // Change as required
private $db_pass = 'secret'; // Change as required
private $db_name = 'dbname'; // Change as required
}
but, I want to use centralised variables from config.php. that's why I add some lines like this :
include('../config.php');
class Database {
global $db_server;
global $db_user;
global $db_password;
global $db_name;
private $db_host = $db_server; // Change as required
private $db_user = $db_user; // Change as required
private $db_pass = $db_password; // Change as required
private $db_name = $db_name; // Change as required
}
but, I got this following error message :
Parse error: syntax error, unexpected 'global' (T_GLOBAL), expecting function (T_FUNCTION) in /home/*** on line **
why I can't use variables from config.php file inside Database class? what did I do wrong here? thank you.
The problem with the approach you've chosen to use is that the class is no longer reusable. Any time you instantiate the Database class, it will use the global variables.
I'd be more inclined to set it up like this:
Database.php
class Database {
private $host;
private $db_name;
private $username;
private $password;
function __construct($host, $db_name, $username, $password) {
$this->host = $host;
$this->db_name = $db_name;
$this->username = $username;
$this->password = $password;
}
}
Then in the file you use the Database class:
include('../config.php');
$db = new Database($db_server, $db_name, $db_user, $db_password);
Maybe you can try it like this:
function connDB()
{
$conn=mysql_connect("localhost", "root", "") or die(mysql_error());
mysql_select_db("database") or die(mysql_error());
return $conn;
};
Put this function in your config file or another file such as globalFunctions.php (which contains every general function you need). Just call this function everytime you need it.
Inside a class you can ONLY have member declaration. Global variables are NOT class members, therefore you can't have them inside the class. But you can have them inside methods.
class Database {
private $db_host;
//... the rest of them here
//class constructor. Gets called every time you create an instance of this class.
function __construct() {
global $db_server;
global $db_user;
global $db_password;
global $db_name;
$this->db_host = $db_server;
//.... you get the idea
}
}
Edit 2017-07-11:
Don't do this. Don't use global variables. They are easy to overwrite somewhere and you'd end up debugging a lot. Plus requiring the global keyword is dirty. A proper partial solution is provided by #br3nt. But it still uses global variables and initializes the $db variable in a global scope.
If you have access to the site config in Apache for example, for that website, you can use mod_env to set configuration in environment variables. Example:
<VirtualHost *:80>
.....
SetEnv DB_USER=myDatabaseUser
SetEnv DB_PASSWORD=12345
...
</VietualHost>
And then you can read this in PHP with getEnv('DB_USER') http://php.net/manual/en/function.getenv.php
Another option is to make your config return an array:
config.php
<?php
return [
'db_user'=>'myDbUser,
'db_password'=>'12345'
];
And you should have a single point of entry that ensures read-only access to that config.
Config.class.php
<?php
class Config {
private $_config;
public function __construct() {
$this->_config = include('path/to/config.php');
}
public function __get($key) {
if(isset($this->_config[$key])) {
return $this->_config[$key];
}
return null;
}
}
usage:
$config = new Config();
$dbUser = $config->db_user;
$dbPassword = $config->db_password;
Edit 2, same day
Why are globals bad?
Having global variables is nice because you can access them everywhere, right? Is it also a good practice to have all class members as public? No. Let's say you have a global variable used in many places. Someone accidentally writes this:
if($myGlobalVariable='something') { ... }
And his code works with just a weird bug that nobody cares about. But your code breaks because you actually depend on the exact value of $myGlobalVariable. And you look at the config, and see that it's the right value, and then scratch your head.
This is just one case. Unhindered read+write access to shared resources can be dangerous. It's easy to override, and no error will be output. It also pollutes the global space.
It's also a code smell if you have global functions in a config file. Think of config files as static text files that shouldn't even contain code. The only reason they're PHP files is because of speed, ease, and harder to break security that way.
Here is an option to set your class members to a global value using __construct()
include('../config.php');
class Foo {
private $db_host;
private $db_user;
private $db_pass;
private $db_name;
public function __construct() {
global $db_server;
global $db_user;
global $db_password;
global $db_name;
$this->db_host = &$db_server; // Change as required
$this->db_user = &$db_user; // Change as required
$this->db_pass = &$db_password; // Change as required
$this->db_name = &$db_name; // Change as required
}
}
Since we are using Assignment by Reference the inner class members are the same variables as the global ones (thus change as required).
Also if you want to avoid writing global you can use the reserved variable $GLOBALS, which as described in the documentation is:
An associative array containing references to all variables which are currently defined in the global scope of the script. The variable names are the keys of the array.
So your code could became something like this:
$GLOBALS = array(
'DB_HOST' => 'localhost',
'DB_USER' => 'user',
'DB_PASS' => 'secret',
'DB_NAME' => 'my_db'
);
class Foo {
private $db_host;
private $db_user;
private $db_pass;
private $db_name;
public function __construct() {
$this->db_host = &$GLOBALS['DB_HOST']; // Change as required
$this->db_user = &$GLOBALS['DB_USER']; // Change as required
$this->db_pass = &$GLOBALS['DB_PASS']; // Change as required
$this->db_name = &$GLOBALS['DB_NAME']; // Change as required
}
}
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.
I have the following "Student" Class:
class Student {
public $user_id;
public $name;
public function __construct($user_id) {
$info = $this->studentInfo($user_id);
$this->name = $info['name'];
$this->is_instructor = $info['is_instructor'];
$this->user_id = $info['id'];
}
public static function studentInfo($id) {
global $db;
$u = mysql_fetch_array(mysql_query("SELECT * FROM $db[students] WHERE id='$id'"));
if($u) {
return $u;
}
}
public static function getCoursesByInstructor() {
global $db;
return mysql_query("SELECT courses.*, course_types.name FROM $db[courses] as courses
JOIN $db[course_types] as course_types ON courses.course_type_id=course_types.id
WHERE instructor_id='$this->user_id'");
}
}
I'm trying to do:
$u = new Student(1);
$courses = $u->getCoursesByInstructor();
But am getting the following error:
Fatal error: Using $this when not in object context in /Applications/MAMP/htdocs/flight1/phpincludes/classes/students.class.php on line 54
You're getting that error because you're function is a static function, and therefore you cannot use the $this pointer within it because it supposed to point to an object. So just remove the static keyword from your function definitions.
You are using static methods non-statically. Static methods are only bound to its class, but not to an object, thus $this is not available. This especially means, that $this->userid, that you use in getCoursesByInstructor(), is not valid. I recommend to make the method non-static.
public function getCoursesByInstructor() { /* your code here */ }
Remove the static keyword from the functions you declared inside your Student class.
The static keyword is, simply put, used to indicate a function that is accessible without the need of creating an instance of that class. On the other hand, $this is used to refer to class instance variables. That's why those two don't go well togheter, you're trying to access an instance variable (by using $this) in a static context.
The issue with your code is you are requesting $this inside your static function. See this. You have $this->user_id inside the query.
return mysql_query("SELECT courses.*, course_types.name FROM $db[courses] as courses
JOIN $db[course_types] as course_types ON courses.course_type_id=course_types.id
WHERE instructor_id='$this->user_id'");
To fix this issue you have to modify this function. I can suggest you following way.
public static function getCoursesByInstructor($userID) {
global $db;
return mysql_query("SELECT courses.*, course_types.name FROM $db[courses] as courses
JOIN $db[course_types] as course_types ON courses.course_type_id=course_types.id
WHERE instructor_id='$userID'");
}
And you have to change your other functions with the same theory.
Cheers !
I'm declaring a simple database class that includes an array of prepared statement, but for the life of me, I can't find the syntax error here.
class Database {
private static $users_table = "users";
private static $statements = array("username_available" => "SELECT COUNT(*) FROM " . self::$users_table . " WHERE Username='?'");
}
Any help here?
You should not have quotes around the ? for your parameter. Also, you cannot declare the private static $statements as an array. Instead, you must initialize it in the constructor.
class Database {
private static $users_table = "users";
private static $statements;
public function __construct() {
$this->statements = array("username_available" => "SELECT COUNT(*) FROM " . self::$users_table . " WHERE Username='?'");
// etc...
}
}
you cannot concatenate while assigning values on class variables declaration: you can assign just a scalar value or another array (or an object if I remember correctly).
You can assign expressions into a method, like the class constructor, or maybe another static method
class Database {
private static $users_table = "users";
private static $statements = null;
public function __construct(){
if(self::$statements === null){
self::$statements = array("username_available" => "SELECT COUNT(*) FROM " . self::$users_table . " WHERE Username=?");
}
}
}
This code should work in your case. And as Michael said you should remove quotes around the question mark.
I don't think PHP likes declaring static class variables from concatenations or otherwise requires evaluation. You can't set a static variable to the result of a function call either:
private static $time = time(); # this will fail too. Value must be a literal value
In other words, a propety values in a class definition can't come from something that's evaluated.
So you have to hardcode the value of the $users_table string into the $statements:
private static $statements = array("username_available" => "SELECT COUNT(*) FROM `users` WHERE Username=?");
You're having problems due to requiring an evaluation when setting a class property.
This is because a PHP class property, "must be able to be evaluated at compile time and must not depend on run-time information in order to be evaluated.". See the examples on the previously linked page.
To keep the same format you could just have a static method, that simply returns the value you want:
<?php
class Database {
private static $users_table = "users";
private static function statements() {
return array("username_available" =>
"SELECT COUNT(*) FROM " . self::$users_table . " WHERE Username=?");
}
}
?>
Working example