I have a configuration file where I am defining my database configuration.
My configuration file is
<?php
$config['database']="mydb";
$config['host']="localhost";
$config['username']="root";
$config['password']="";
?>
I have a config class where I am assigning my configuration settings my config class is like
class Config {
//put your code here
protected $host = "";
protected $user = "";
protected $password = "";
protected $database = "";
protected function __construct(){
include_once 'configuration.php';
$this->host=$config['host'];
$this->user=$config['username'];
$this->password=$config['password'];
$this->database=$config['database'];
}
}
now I am trying to establish my database connection to my connection class like
include_once 'Config.php';
class Connection extends Config{
private $conn;
function __construct() {
parent::__construct();
try {
$this->conn = new PDO("mysql:host=$this->host;dbname=$this->database", $this->user, $this->password);
} catch (PDOException $pe) {
echo "Error connecting to database. " . $pe->getMessage();
}
}
function getConnectionObject() {
return $this->conn;
}
public function destroyConn() {
$this->conn = null;
}
}
My problem is when I am trying to get this connection for further class it showing me blank object
My code for access database connection object is
class Functions extends Connection {
private $conOb;
function __construct() {
parent::__construct();
$this->conOb = parent::getConnectionObject();
}
function getConnectionObject() {
parent::getConnectionObject();
}
}
if I am defining my database configuration in my connection class I am able to Access my connection object in my Function class but if I am trying to set it by configuration file getting Null connection object.
Please let me know where I am making mistake. Thanks in advance .
You're missing the return keyword
class Functions extends Connection {
private $conOb;
function __construct() {
parent::__construct();
$this->conOb = parent::getConnectionObject();
}
function getConnectionObject() {
return parent::getConnectionObject();
}
}
By the way, you don't have to redeclare the method getConnectionObject() if you don't add anything to it.
You can simply do :
class Functions extends Connection {
function __construct() {
parent::__construct();
}
}
$db = new Functions();
$dbh = $db->getConnectionObject();
And if you change the visibility of the property $conn to protected in the class Connection, you can use your connection in subclasses like that :
class Functions extends Connection {
function __construct() {
parent::__construct();
}
function doSomething() {
$this->conn->query('SELECT....');
}
}
As a side note, i encourage you to take a look at the PHP coding style standards.
Related
I have a singleton database connection class- db.php (found by googling):
<?php
/*
* Mysql database class - only one connection alowed
*/
class db {
private $_connection;
private static $_instance; //The single instance
private $_host = "localhost";
private $_username = "user_name";
private $_password = "password";
private $_database = "database";
/*
Get an instance of the Database
#return Instance
*/
public static function getInstance() {
if(!self::$_instance) { // If no instance then make one
self::$_instance = new self();
}
return self::$_instance;
}
// Constructor
private function __construct() {
$this->_connection = new mysqli($this->_host, $this->_username,
$this->_password, $this->_database);
// Error handling
if(mysqli_connect_error()) {
trigger_error("Failed to conencto to MySQL: " . mysql_connect_error(),
E_USER_ERROR);
}
// Magic method clone is empty to prevent duplication of connection
private function __clone() { }
// Get mysqli connection
public function getConnection() {
return $this->_connection;
}
public function closeConnection(){
$this->_connection->close();
}
}
?>
To test the connectivity, If I extend that database class in ext.php like this:
<?php
class ext extends db {
private $conn;
function __construct(){
$this->connect();
if(isset($this->conn)){
echo 'Connection is established<br />';
}
$this->closeConn();
}
public function connect(){
$this->conn = parent::getInstance()->getConnection();
}
public function closeConn(){
parent::closeConnection();
}
}
?>
and in my index.php page:
<?php
spl_autoload_register(function ($class) {
include '../classes/' . $class . '.php';
});
$test = new ext();
?>
now my output is as below:
Connection is established
Fatal error: Call to a member function close() on a non-object in (line number) of db.php
my question is how can I close connection in extended class (ext.php)?
The solution would be like this:
First, create a private instance variable of parent class db in ext class, like this:
class ext extends db {
...
private $parentInstance;
...
}
Then use this instance variable $parentInstance to create and close your connection, like this:
class ext extends db {
private $conn;
private $parentInstance;
function __construct(){
$this->connect();
if(isset($this->conn)){
echo 'Connection is established<br />';
}
$this->closeConn();
}
public function connect(){
$this->parentInstance = parent::getInstance();
$this->conn = $this->parentInstance->getConnection();
}
public function closeConn(){
$this->parentInstance->closeConnection();
}
}
Sidenote: There's one small syntax error in db class as well. The closing parentheses of constructor method is missing.
Below is the solution to my question. I didn't have my class written wrong. I accidentally used a "die" function inside my master DB class that made all my queries fail. I was tracking down the wrong problem.
I hope you guys find this class example useful. It's clean, and very useful for wrapping SQL calls in a single location for multiple databases. By allowing the extension, you can track your calls much easier my var name.
class A extends DB {
protected $connection;
function __construct()
{
$this->db_host = "server.com:3327";
$this->db_name = "db_name_one";
$this->db_username = "root";
$this->db_password = 'pw';
// .. equals all the setup vars
parent::__construct();
}
}
class B extends DB {
function __construct()
{
$this->db_host = "server.com:3327";
$this->db_name = "db_name_two";
$this->db_username = "root";
$this->db_password = 'pw';
// .. equals all the setup vars
parent::__construct();
}
}
class DB {
function __construct()
{
$this->connect()
}
public function connect()
if (!$connection = # mysql_connect ($this->db_host,$this->db_username,$this->db_password,$this->second_flag))
die ('I cannot connect to the database because: ' . mysql_error());
if (!mysql_selectdb($this->db_name,$connection))
$this->showerror();
return $connection;
}
public function executeSQL($query)
{
$results = mysql_query($query,$this->connection);
if (!$results) {
die(...);
}
return $results;
}
}
$db1 = new A();
$db2 = new B();
$db1->executeSQL("select * from table");
I don't know if there's a legitimate reason to extend the DB class here. Unless those extending classes add something to the DB (e.g. they adapt it to a different database), then they have nothing to do with being a DB as such. Just because they use a DB doesn't mean they should extend one.
The simplest thing to do is: make one class that handles your database interaction. When you make a new instance of that class, it establishes a new connection to the database. This way you can have as many independent connections as you want. You then simply pass those instances to whoever needs them:
class DB {
protected $connection;
public function __construct() {
$this->connection = mysql_connect(..);
if (!$this->connection) {
throw new Exception(..);
}
}
..
}
class A {
protected $db;
public function __construct(DB $db) {
$this->db = $db;
}
..
}
$db = new DB;
$a = new A($db);
I am new to php oop , so struggling a bit .
i have a database connection class viz :
class config{
protected $HOST = "localhost";
protected $USERNAME = "something" ;
protected $PASSWORD = "something";
protected $DATABASE = "something";
// Constructor - open DB connection
function __construct() {
try {
$this->db = new mysqli($this->HOST, $this->USERNAME, $this->PASSWORD, $this-
>DATABASE);
$this->db->autocommit(FALSE);
}
catch(Exception $e)
{
if($this->db->connect_errno > 0){
echo 'Caught exception: ', $e->getMessage(), "\n";
}
}
}
// Destructor - close DB connection
function __destruct() {
$this->db->close();
}
}
$api = new Config();
Now i have another class from which i need to perform some tasks ...but i get FATAL error .
second class :
class Myclass extends config {
function __construct(){}
public function myfunction()
{
try{
$stmt = $this->db->stmt_init(); /* Error here : Fatal error: Call to a member
function stmt_init() on a non-object */
$query = "SELECT ABC FROM table " ;
$stmt = $this->db->prepare($query); /* Error here : Fatal error: Call to a member
function prepare() on a non-object */
}
catch(){}
}
}
Please guide me with proper remedial code snippet
In your child class, you need to call the parent constructor. PHP won't automatically call parent constructor's when a child class is instantiated.
class Myclass extends config {
function __construct($h, $u, $p, $d){ parent::__construct($h, $u, $p, $d); }
Also, you don't have a $db property in the parent class, so add that
class config{
protected $db;
protected $HOST = "localhost";
protected $USERNAME = "something" ;
protected $PASSWORD = "something";
protected $DATABASE = "something";
Edit: Dependency Injection approach:
class config{
public $HOST = "localhost";
public $USERNAME = "something" ;
public $PASSWORD = "something";
public $DATABASE = "something";
}
class Myclass
{
protected $db;
function __construct($db)
{
$this->db = $db;
}
public function myfunction()
{
// do whatever with $this->db
}
}
$config = new Config();
try
{
$db = new mysqli($config->HOST, $config->USERNAME, $config->PASSWORD, $config->DATABASE);
$db->autocommit(FALSE);
}
catch(Exception $e)
{
if($db->connect_errno > 0){
echo 'Caught exception: ', $e->getMessage(), "\n";
}
}
$myclass = new Myclass($db);
Have a look into Dependency Injection. This is a favorable approach for dealing with classes that need access to a database. Instead of having all your classes extend the database, just pass the datsbase object as a parameter when creating new classes (that need the db).
Your derived class constructor is not calling the base constructor, so $this->db does not have the value it's supposed to. In PHP you must do this explicitly.
In this particular case, you should remove the derived constructor altogether since it's not doing anything. This will let PHP use the base constructor directly.
I have the following, however I'm unable to access the database functions outside of the initial db class?
Thanks!
database.php
class db
{
private $connection;
public function __construct()
{
$this->connection = new PDO();
}
}
admin.php
class admin
{
private $connection
public function __construct(db $connection)
{
$this->connection = $connection;
}
function myFunc()
{
// How do I access the connection here?
}
}
main.php
//include db.php
//include admin.php
$connection = new db();
$admin = new admin($connection);
// How do I access the DB here?
First of all, why are you encapsulating PDO just to class containing that one object? Cannot you use PDO directly?
One of the common practices would be to implement getter in db class, like:
class db {
...
public function getPDO(){
return $this->connection;
}
}
Another way is to re-implement every function (why would you do that?!), or use __call magic function...
Or just make $connection public ;)
Or you could extend PDO class (I'm not sure whether it'll work):
class DB extends PDO {
public function __construct ( $dsn, $username = null, $password = null, $driver_options = array()){
parent::__construct( $dsn, $username, $password, $driver_options);
... more of your stuff
}
public function myFunc(){
$this->...
}
}
ok, you really need to go and read up on object-oriented design, and access modifiers. I'll explain what you need to do here, but this is a band-aid solution, and you need to deeply understand how things are working here.
In your admin class, you defined the connection as a private attribute of the class. So in the myFunc function, you simply do $this->connection to access the connection that you created in the constructor.
In your main.php file, the object you are getting rom initializing a DB object is not the connection. It is the db object as a whole, so you can not pass the connection by itself to the admin class (it is defined as private, so nobody outside the class can view it). However, why do you need to pass it to the admin class? Managing the DB connection should be the responsibility of the DB class.
In other words, what are you trying to achieve by exposing the DB connection to the admin class?
Upate: based on the reply here is a suggested answer:
class Database {
private $connection;
public function __construct() {
$this->connection = new PDO();
}
}
class Admin {
private $db;
public function __construct() {
$this->db = new Database();
}
public function myFunc() {
$this->db->query('...');
}
}
In your main.php file:
$admin = new Admin();
$admin->myFunc();
Keep in mind, every admin object is going to create a new connection to the DB, so if you create many admin objects you might face some issues. You can get around this by declaring the DB to be a singleton.
How about this:Updated
<pre>
<?php
class DB {
private $host;
private $user;
private $pass;
private $dbase;
private $connection;
public function __construct($host,$user,$pass,$dbase)
{
$this->host = $host;
$this->user = $user;
$this->pass = $pass;
$this->dbase = $dbase;
$this->connection = new PDO("mysql:host=$this->host;dbname=$this->dbase", $this->user, $this->pass);
}
public function connect()
{
return $this->connection;
}
public function close()
{
unset($this->connection);
return true;
}
}
$dbh = new DB('localhost','root','','inventory');
$result = $dbh->connect()->query("SELECT * FROM products")->fetchAll(PDO::FETCH_ASSOC);
print_r($result);
?>
</pre>
Updated with files separation
database.php
class db
{
private $connection;
public function __construct()
{
$this->connection = new PDO();
}
}
admin.php
class admin
{
private $connection
public function __construct(db $connection)
{
$this->connection = $connection;
}
function myFunc()
{
return $this->connection->prepare('SQL');
}
function getConnection()
{
return $this->connection;
}
}
main.php
require_once 'database.php';
require_once 'admin.php';
$connection = new db();
$admin = new admin($connection);
$admin->myFunc()->execute();
I need to use $GLOBALS['db'] in my classes ($db is defined in my index.php), but I don't want to use $GLOBALS['db'] when I have to call it.
I wrote this code at the beginning of my classes :
class ClassName
{
var $db;
public function __construct()
{
$this->db = $GLOBALS['db'];
}
public function test()
{
$val = $this->db->oneValue('SELECT first_name FROM users LIMIT 0, 1');
echo $val->first_name;
}
}
But I'm not enjoying this; I prefer to use directly $db in my code. Is there a solution to be able to call $GLOBALS['db'] by $db?
Simples, just inject in the constructor or a setter method: (I'm assuming $db is an object here, not an array of connection parameters etc)
class ClassName
{
protected $db;
public function __construct($db)
{
$this->setConnection($db);
//Any other constructor things you want to happen...
}
/*
* This is just here for convenience, this could be protected if you only want to set
* the db connection via the constructor
*/
public function setConnection($db)
{
$this->db = $db;
}
public function test()
{
$val = $this->db->oneValue('SELECT first_name FROM users LIMIT 0, 1');
echo $val->first_name;
}
}
As mentioned in some comments above, this is a form of dependency injection which will give you more ability to re-use code inside your project (A Good Thing TM).
I prefer using singleton pattern for databases.
this is the DB class i am using for my app.
class Database {
protected static $_dbh;
const HOST = 'localhost';
const DATABASE = 'dbname';
const USERNAME = 'username';
const PASSWORD = 'password';
private function __construct() { }
public static function getInstance() {
if(!isset($_dbh)) {
try {
#Connection String.
self::$_dbh = new PDO('mysql:host='.self::HOST.';dbname='.self::DATABASE,self::USERNAME,self::PASSWORD);
self::$_dbh->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch(PDOException $e) {
#Print Errors.
echo $e->getMessage();
}
}
return self::$_dbh;
}
}
as i am using singleton pattern the connection will be re-used. you can now use the connection everywhere in your app by calling static connection method i.e
class ClassName
{
protected static $_dbh;
public function __construct() {
self::$_dbh = Database::getInstance();
}
public function test() {
$sth = self::$_dbh->query('SELECT first_name FROM users LIMIT 0, 1');
$row = $sth->fetchAll(PDO::FETCH_ASSOC);
echo $row['first_name'];
}
}