I have config.php with this...
$dbhost = "localhost";
I want to be able to use the $dbhost variable inside a class.
User.class.php
include 'config.php';
class User {
private $dbhost = ???
}
There's a couple other questions like this, but they were for some other specific uses, and I guess it's just a basic thing that I can't really find anything else about it on the web.
UPDATE: Wow, thanks for all the help everybody. New to this site, but I might just stick around and give back where I can.
You could use a global variable, defining a constant would be better, but using a setter/getter method is best. When you are using a class, any outside resource that it uses should be passed to it. This design patter is called dependency injection if you want to research it further.
In this example, I've combined the setter and getter into a single method, and included the ability to set the value when you first create the instance, using a constructor:
class User
{
private $host = null;
public function host($newHost = null)
{
if($newHost === null)
{
return $this->host;
}
else
{
$this->host = $newHost;
}
}
function __construct($newHost = null)
{
if($newHost !== null)
{
$this->host($newHost);
}
}
}
//Create an instance of User with no default host.
$user = new User();
//This will echo a blank line because the host was never set and is null.
echo '$user->host: "'.$user->host()."\"<br>\n";
//Set the host to "localhost".
$user->host('localhost');
//This will echo the current value of "localhost".
echo '$user->host: "'.$user->host()."\"<br>\n";
//Create a second instance of User with a default host of "dbserver.com".
$user2 = new User('dbserver.com');
//This will echo the current value of "dbserver.com".
echo '$user2->host: "'.$user2->host()."\"<br>\n";
For something like a db host, use a constant:
// define it first
define('DBHOST', 'localhost');
// then anywhere you can use DBHOST:
class User {
function __construct() {
echo DBHOST;
}
}
http://php.net/manual/en/language.constants.php
several ways I think.
First pass it to the class constructor:
include 'config.php';
class User {
private $dbhost;
function __construct($dbhost){
$this->dbhost=$dbhost;
}
}
$user= new User($dbhost);
Or use a setter:
include 'config.php';
class User {
private $dbhost;
function setDbhost($dbhost){
$this->dbhost=$dbhost;
}
}
$user= new User();
$user->setDbhost($dbhost);
Or using CONSTANTS:
define('DBHOST', 'localhost');
class User {
private $dbhost;
function __construct(){
$this->dbhost=DBHOST;
}
}
OR using global:
include 'config.php';
class User {
private $dbhost;
public function __construct() {
global $dbhost;
$this->dbhost=$dbhost;
}
}
If you are planning to use variables (and not constants), then use the following code.
In config.php
$dbhost = "localhost";
In User.class.php
include 'config.php';
class User {
global $dbhost;
}
Related
I'm kinda new to PDO with MYSQL, here are my two files:
I have a connection class that I use to connect to the database:
class connection{
private $host = 'localhost';
private $dbname = 'devac';
private $username = 'root';
private $password ='';
public $con = '';
function __construct(){
$this->connect();
}
function connect(){
try{
$this->con = new PDO("mysql:host=$this->host;dbname=$this->dbname",$this->username, $this->password);
$this->con->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);
}catch(PDOException $e){
echo 'We\'re sorry but there was an error while trying to connect to the database';
file_put_contents('connection.errors.txt', $e->getMessage().PHP_EOL,FILE_APPEND);
}
}
}
I have an account_info class that i use to query the data from the database:
class account_info{
function getAccountInfo(){
$acc_info = $this->con->prepare("SELECT * FROM account_info");
$acc_info->execute();
$results = $acc_info->fetchAll(PDO::FETCH_OBJ);
foreach ($results as $key) {
$results->owner_firstname;
}
}
}
I include both these files in my index.php page:
include_once 'classes/connection.class.php';
include_once 'classes/accountinfo.class.php';
$con = new connection();
$info = new account_info();
$info->getAccountInfo();
I just cant get it to work I'm not getting any output, I think it has something to do with the scope, but I don't know the correct why to fix it as I'm new to this PDO and OOP stuff.
Thanks in advance.
Solution 1
Replace class account_info { with class account_info extends connection {
Replace
$con = new connection();
$info = new account_info();
with
$info = new account_info();
and it should work.
Solution 2 (suggested)
I highly suggest you to solve your problem with dependency injection in this case.
Just replace your account class with:
class account_info {
private $con;
public function __construct(connection $con) {
$this->con = $con->con;
}
public function getAccountInfo(){
$acc_info = $this->con->prepare("SELECT * FROM account_info");
$acc_info->execute();
$results = $acc_info->fetchAll(PDO::FETCH_OBJ);
foreach ($results as $key) {
$results->owner_firstname;
}
}
}
and use it in index.php like this:
include_once 'classes/connection.class.php';
include_once 'classes/accountinfo.class.php';
$con = new connection();
$info = new account_info($con);
$info->getAccountInfo();
Explanation
As a general good rule: always specify the scope keyword for functions (public, protected or private).
The first solution is called inheritance and what we basically did was extending the account class with the connection class in order to inherit all the methods and properties from the connection class and easily use them. In this case you have to watch out for naming conflicts. I suggest you to take a look at the class inheritance in the PHP manual.
The second solution is called dependency injection and it is a wildly encouraged design pattern that makes your classes accept other classes in their constructor in order to explicitly define the class dependency tree (in this case account depend from connection and without the connection we can't make account work).
Another, of thousands of possible solution, would be the one that someone posted below which is a design pattern called Singleton. However that patter has been reevaluated recently as anti-pattern and should not be used.
A common method is to use a singleton pattern in your database class.
Something like this:
class connection {
private static $hInstance;
public static function getInstance() {
if (!(self::$hInstance instanceof self)) {
self::$hInstance = new self();
}
return self::$hInstance;
}
/* your code */
}
Then, you can simply use
$database = connection::getInstance();
$database->con->prepare(....)
etc
I just started doing OOP, so I apologize in advance if there is a simple solution.
Basically I need to use my $mysqli object inside a class. I've seperated it into two files.
config2.php
class Config
{
public $host = 'localhost';
public $username = '****';
public $password = '****';
public $database = '****';
function report_error($query)
{
$email = '*#hotmail.com';
$subject = 'MySQL error.';
$message = "IP: {$_SERVER['REMOTE_ADDR']} \n URL: http://{$_SERVER['SERVER_NAME']}{$_SERVER['REQUEST_URI']} \n\n MySQL query: {$query} \n\n MySQL error: " . $mysqli->error();
mail($email, $subject, $message);
die('Oops, an error has occured. The administrator has been notified.');
}
}
$config = new Config();
$mysqli = new mysqli($config->host, $config->username, $config->password, $config->database);
if($mysqli->connect_error)
report_error($mysqli);
administration.php
require('includes/config2.php');
$mysqli->real_escape_string(); // Works out of scope.
class Account
{
public $username = $mysqli->real_escape_string(); // Doesn't work in scope.
public $password;
function login()
{
}
}
Thanks for the help guys, I appreciate it :).
You should pass the object to the constructor of Account and save it as a private instance variable.
Account is directly dependent on an instance of mysqli, so there is nothing wrong with making that clear by specifying it as a required parameter in the constructor. That is the only way you can make sure that whenever Account is used the mysqli object is there too. If you access it from a global state instead (by either having a static accessor or by directly accessing the global scope) you can never guarantee that it is really there.
You should encapsulate the $mysqli object and make it static
usually you would encapsulate the DB in some class called "DBConnection" or similar. And this instance should manage the real $mysqli object as singleton
in (very)short:
class Config
{
public $host = 'localhost';
[...]
public static $connectionObj
public static getConnection(){
if (!isset($this->connectionObj ){
$connectionObj = new mysqli($this->host, $config->this, $config->this, $this->database);
if($mysqli->connect_error){
report_error($mysqli);
}
}
return $this->connectionObj;
}
}
You get access to this object from everywhere:
$mysqlObj = Config.getConnection()
DISCLAIMER:
This is very short, untested code and database should not went into config class but its own database class with all SQL functions as methods, this is just for reusing your provided code
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.
I'm new to OOP. Originally I was defining variables and assigning values to them within the class and outside of the constructor, but after an OOP lesson in Java today, I was told this is bad style and should be avoided.
Here is my original PHP database connection class that I mocked-up:
class DatabaseConnection {
private $dbHost = "localhost";
private $dbUser = "root";
private $dbPass = "";
private $dbName = "test";
function __construct() {
$connection = mysql_connect($this->dbHost, $this->dbUser, $this->dbPass)
or die("Could not connect to the database:<br />" . mysql_error());
mysql_select_db($this->dbName, $connection)
or die("Database error:<br />" . mysql_error());
}
}
Is the above considered okay? Or is the following a better way?
class DatabaseConnection {
private $dbHost;
private $dbUser;
private $dbPass;
private $dbName;
function __construct() {
$this->dbHost = "localhost";
$this->dbUser = "root";
$this->dbPass = "";
$this->dbName = "test";
$connection = mysql_connect($this->dbHost, $this->dbUser, $this->dbPass)
or die("Could not connect to the database:<br />" . mysql_error());
mysql_select_db($this->dbName, $connection)
or die("Database error:<br />" . mysql_error());
}
}
What should I be focusing on to make sure I am understanding OOP correctly?
First of all: this is pointless.
You are creating an object wrapper for the 10+ year old mysql_* function. This php extension is no longer maintained and the process of deprecation has already begun. You should not use this API for any new projects in 2012.
Instead you should learn how to use PDO or MySQLi and work with prepared statements.
That said .. lets take a look at your code:
Constructor should receive all the parameters required for creating new instance, parameters should not be hard-coded in the class definition. What if you need to work with two databases at the same time ?
When connection is created, it should be stored in object's scope variable. Something along the lines of $this->connection = mysql_conn.... Instead you store it in local variable, which you "loose" right after constructor is done.
You should not use private variables for everything. They are not visible to classes which would extend your original class. Unless it is intentional, you should choose protected for this.
The or die('..') bit most go. Do not stop the whole application if connection fails. Instead you should throw an exception, which then can be handled outside of the constructor.
Well, it's not going to run quite yet. You need to change your variables so that they match your connection params:
$dbHost = "localhost";
Should be
$this->dbHost = 'localhost';
I normally don't put my login params inside of the class at all. I would pass them into the constructor when the object is created. Use an outside config file so you can actually use this class on more than one build. :)
Update::
Okay, so here are a few little OOP configuration gold-nuggets that help you build a dynamic Database class.
Check out http://redbeanphp.com/ It will allow you to do a psuedo ORM style of data modelling. Super easy to install, and ridiculously easy to get your database up and running. http://redbeanphp.com/manual/installing
Create a configuration file that contains things like constants, template setups, common functions, and an AUTOLOADER Configuration files are key when working in version controlled environments. :)
Build your Database class as an abstract class http://php.net/manual/en/language.oop5.abstract.php
abstract class Database
{
public function update()
{
}
public function deactivate()
{
}
public function destroy()
{
}
//etc.
}
class MyAppObject extends Database
{
}
Put all of your class files into a library folder, and then put your configuration file into that library. Now, to make your life easier you can use an autoloader function to bring your classes to life whenever you need them, without having to include any specific class. See below:
//note: this is never explicitly instantiated
//note: name your files like this: MyAppObject.class.php
function my_fancypants_autoloader( $my_class_name )
{
if( preg_match( "%^_(Model_)%", $my_class_name ) ) return;
require_once( "$my_class_name.class.php" );
}
spl_autoload_register( 'my_fancypants_autoloader' );
Now all you have to do is include one configuration file in your .php files to access your classes.
Hope that points you in the right direction! Good luck!
Since your are only using them into the __construct method, you don't need them as class attributes. Only the $connection has to be kept for later use imho.
It might be much much better to not give any default values to those arguments but let them being set from the outside.
$db = new DatabaseConnection("localhost", "user", "password", "db");
They are plenty of PHP tools for that already, find them, read them and learn from that. First of all, use PDO and what is true in Java isn't always true in PHP.
The latter is probably better, but with an adjustment: pass some arguments to the constructor, namely the connection info.
Your first example is only useful if you've got one database connection and only if you're happy hard-coding the connection values (you shouldn't be). The second example, if you add say, a $name parameter as an argument, could be used to connect to multiple databases:
I'm new to OOP. Originally I was defining variables and assigning values to them within the class and outside of the constructor, but after an OOP lesson in Java today, I was told this is bad style and should be avoided.
class DatabaseConnection {
private $dbHost;
private $dbUser;
private $dbPass;
private $dbName;
function __construct($config) {
// Process the config file and dump the variables into $config
$this->dbHost = $config['host'];
$this->dbName = $config['name'];
$this->dbUser = $config['user'];
$this->dbPass = $config['pass'];
$connection = mysql_connect($this->dbHost, $this->dbUser, $this->dbPass)
or die("Could not connect to the database:<br />" . mysql_error());
mysql_select_db($this->dbName, $connection)
or die("Database error:<br />" . mysql_error());
}
}
So using this style, you now have a more useful class.
Here is mine and it works rather well:
class Database
{
private static $_dbUser = 'user';
private static $_dbPass = 'pwd';
private static $_dbDB = 'dbname';
private static $_dbHost = 'localhost';
private static $_connection = NULL;
/**
* Constructor
* prevents new Object creation
*/
private function __construct(){
}
/**
* Get Database connection
*
* #return Mysqli
*/
public static function getConnection() {
if (!self::$_connection) {
self::$_connection = #new mysqli(self::$_dbHost, self::$_dbUser, self::$_dbPass, self::$_dbDB);
if (self::$_connection -> connect_error) {
die('Connect Error: ' . self::$_connection->connect_error);
}
}
return self::$_connection;
}
}
By making the __construct empty, it prevents a new class being instantiated from anywhere. Then, make the function static so now all I need to do to get my connection is Database::getConnection() And this is all in an include file, in a password protected folder on the server and just included with each class file. This will also check to see if a connection is already open before attempting another one. If one is already established, it passes the open connection to the method.
<?php
class config
{
private $host='localhost';
private $username='root';
private $password='';
private $dbname='khandla';
function __construct()
{
if(mysql_connect($this->host,$this->username,$this->password))
{
echo "connection successfully";
}
}
function db()
{
mysql_select_db($this->$dbname);
}
}
$obj=new config();
?>
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.