mysqli constructor returns null - php

I am trying to write a db util class using the singleton pattern. My problem is that the "connection" object is always null. The connection settings are correct. What could i be doing wrong ? Also, i am relatively new to php development. What method should i use to figure out what's wrong ? Code follows.
class DBUtil {
public $connection = NULL; //mysqli_connection object
private static $instance = NULL;
private function _constructor($conn){
//$this->connection = mysqli_connect(TagMetroConfiguration::getConfigurationValueFor("db_servser_name"), TagMetroConfiguration::getConfigurationValueFor("db_username"), TagMetroConfiguration::getConfigurationValueFor("db_password"), TagMetroConfiguration::getConfigurationValueFor("db_name"));
$this->connection = new mysqli("localhost", "root", "toor", "testdb");
}
public static function getInstance(){
if(DBUtil::$instance == NULL){
try{
DBUtil::$instance = new DBUtil();
}catch(Exception $ex){
throw new Exception("Unable to create DB Instance");
}
}
return DBUtil::$instance;
}
}

Your constructor function should be named __construct (notice two underscores).
Also, in your constructor, you have one parameter, $conn. When you call new DBUtil(), you are not providing that input parameter, so perhaps it's calling the default contructor, not your custom one.
If you want the input parameter $conn to be optional, try __construct($conn = null).
Or try calling it as new DBUtil(null).

private function _constructor($conn) ??
should this be
private function __construct($conn)

There should be two underscores __ (__construct).

You should do like this :
class DBUtil {
private static $instance;
private function _construct(){
$this->$instance = new mysqli("localhost", "root", "toor", "testdb");
}
public static function getInstance(){
if(!isset(self::$instance){
try{
self::$instance = new DBUtil();
}catch(Exception $ex){
throw new Exception("Unable to create DB Instance");
}
}
return self::$instance;
}

Related

How to create global connection?

I want create a global connection, so in the entire script I can access to a single object. Actually I made this class:
<?php
class Database {
private static $db;
private $connection;
private function __construct($conn) {
$this->connection = $conn;
$this->init();
}
private function init(){
// here the connection is going to execute
$host = $this->_connection['host'];
//etc...
}
function __destruct() {
$this->connection->close();
}
public static function getConnection($conn) {
if (self::$db == null) {
self::$db = new Database($conn);
}
return self::$db->connection;
}
}
?>
I pass the details of connection like this: $db = Database::getConnection($connection); Now $connection contains an array with the credentials access. Here no problem all working good. The main problem is that $db = Database::getConnection($connection); is called only when the index create the instance of the connection. My goal is call the $connection object in any models or controller, example:
class Model
{
function __construct()
{
$this->db = Database::getConnection();
}
}
how you can see I can't pass the connection parameter 'cause I want just use the connection previously established by the index.php call. How I can access to this connection without pass parameter?
You need to both make the $conn parameter optional and make sure it is passed on the first call:
public static function getConnection($conn=null) {
if (self::$db == null) {
if ($conn === null) {
throw new Exception('Can not initialize the database');
}
self::$db = new Database($conn);
}
return self::$db->connection;
}
Then you need to call the getConnection somewhere during the application start and pass the configuration to it.
After that you can use it without parameters.
If, by mistake, you don't configure the database, you'll have a clear error.
You could try this
public static function getConnection($conn = null) {
if (self::$db != null) {
return self::$db->connection;
}
//maybe add some validation here to ensure that the $conn value has been set
self::$db = new Database($conn);
return self::$db->connection;
}
or this works as well although it will throw an error if you don't set the $conn on the first call.
public static function getConnection($conn = null) {
if (self::$db == null && $conn) {
self::$db = new Database($conn);
}
return self::$db->connection;
}
It changes your logic a bit but should now work as you expect it to.
If the $conn is not supplied then it wont throw an error.

PHP - pass PDO connection to all functions

I have a try catch block that connects via PDO to a database. I would like to be able to reference it in all my functions without having to pass it as a parameter. How would I do this? The mentioned code is:
try {
$database = new PDO('mysql:host=127.0.0.1;dbname=coop1','root','');
$database->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}catch(PDOException $e) {
echo $e->getmessage();
die();
}
EDIT:
I created a singleton class (attempt below) that executes the try catch block upon _construct
final class database {
private static $instance = NULL;
private function __construct() {
try {
$database = new PDO('mysql:host=127.0.0.1;dbname=coop1','root','');
$database->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch(PDOException $e) {
echo $e->getmessage();
die();
}
}
public static function getInstance() {
static $instance = null;
if (self::$instance === NULL) {
$instance = new database();
}
return $instance;
}
}
Declare it as a static attribute of a singleten class. Than you can access it with
$pdo = Singleton::instance()->getConnection();
Alternatively I can suggest taking a look at MArtin Fowler's relational database mapping pattern. It goes a step further, than centralizing ony the connection itself.
Alternatively Doctirne project has a complete implementation of that: www.doctrine-project.org
final class database {
private static $instance = NULL;
private $pdo; //added private variable for pdo
private function __construct() {
try {
$database = new PDO('mysql:host=127.0.0.1;dbname=coop1','root','');
$database->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch(PDOException $e) {
echo $e->getmessage();
die();
}
$this->pdo = $database; //saved the connection into the new variable
}
public static function getInstance() {
static $instance = null;
if (self::$instance === NULL) {
$instance = new database();
}
return $instance;
}
//added a function to get the connection itself
function getConnection(){
return $this->pdo;
}
}
So now you use it:
$pdo = database::getInstance()->getConnection();

Singleton syntax in PHP code

I understand the singleton pattern, but I don't understand the following syntax:
public static function get()
{
static $db = null;
if ( $db == null )
$db = new DatabaseConnection();
return $db;
}
private function __construct()
{
$dsn = 'mysql://root:password#localhost/photos';
$this->_handle =& DB::Connect( $dsn, array() );
}
Why every time we call DatabaseConnection::get() we could ge the same singleton object? Because the code read from me will like:
static $db = null; //set $db object to be null
if($db==null) // $db is null at the moment every time because we just set it to be null
// call the private constructor every time we call get() *
$db = new DatabaseConnection();
return $db; // return the created
Then how the get() function could always return a same object?
I am new to Php, most of the syntax to me will read like java, please any one could explain this to me?
Also is there any instructions/tutorial that I could read for understanding more syntax sugar like:
$array_object[] = $added_item
Try this inside your class:
private static $db;
public static function get(){
if(!self::$db){
self::$db = new DatabaseConnection();
}
return self::$db;
}

Having issue with understanding two singleton Php code for conecting to mongoDb

I have these two code to use to connect to mongodb.
First i used this code but this doesn't seem to work.I dont know why.
class DbConnection
{
static $db = NULL;
static function getMongoCon()
{
if (self::$db === null)
{
try {
$m = new Mongo("mongodb://username:password#localhost:27017");
} catch (MongoConnectionException $e) {
die('Failed to connect to MongoDB '.$e->getMessage());
}
self::$db = $m;
}
else
{
return self::$db;
}
}
}
After this i used this way to connect mongo in another class
$db=DbConnection::getMongoCon();
$database=$db->databasename;
$collection=$db->users;
But this doesn't seem to work always . i always get error $db not defined or some other undefined error.
Second Code is this . which i used to connect to mongodb without having to create multiple connection. This works fine without having problem.
class DbConnection{
static protected $_instance;
protected $db = null;
final protected function __construct() {
$m = new Mongo("mongodb://username:password#localhost:27017");
$this->db = $m->selectDB( "databasename" );
}
static public function getInstance() {
if (!(self::$_instance instanceof self)) {
self::$_instance = new self();
}
return self::$_instance;
}
public function getConnection() {
return $this->db;
}
final protected function __clone() { }
}
To use this code in another class i used
$db=DbConnection::getInstance()->getConnection();
$collection=$db->users;
I dont know why second one worked but not the first code. if i use both in mysql both works fine.
Also can this be issue than in second code i have create connection to mongodatabase and kept it open and directly used in another class.
please describe simply why the second code worked fine and first didn't worked.
In the first piece of code, when the $db variable is null and you create a new connection, your getMongoCon function doesn't return anything, hence when you try to use it on the example, $db=DbConnection::getMongoCon(); end ups asigning null to the $db variable.
To make it work correctly, you should do something like this:
...
static function getMongoCon()
{
if (self::$db === null)
{
try {
$m = new Mongo("mongodb://username:password#localhost:27017");
} catch (MongoConnectionException $e) {
die('Failed to connect to MongoDB '.$e->getMessage());
}
self::$db = $m;
}
return self::$db;
}
...

PHP Singleton Database Query

In PHP, I have following Singleton Database Class:
class Database
{
private static $instance;
private function __construct()
{
self::$instance = new mysqli('localhost', 'root', 'Matthias', 'financecontrol', '3307');
if (!self::$instance) {
throw new Exception('Could not connect to database in function __construct.');
}
}
public static function getInstance()
{
if (!self::$instance) {
self::$instance = new Database();
}
return self::$instance;
}
}
Whenever I try to perform a query on the database in another PHP file, for example to check whether a user already exists:
function userExists($username)
{
try {
$connection = Database::getInstance();
$result = $connection->query("select * from user where username='$username'");
if (!$result) {
throw new Exception("Connection to database failed in function userExists.");
}
if ($result->num_rows > 0) {
return true;
} else {
return false;
}
} catch (Exception $ex) {
$errorPager = new ErrorpageGenerator();
$errorPager->generateErrorPage($ex->getMessage());
return false;
}
}
I get an error message "PHP Fatal error: Call to undefined method Database::query() in User.php on line 44"
I've tried adding a query function in the Database class, but that did not seem to fix the problem. Any ideas? Thanks
You have to add this method of course. But you cannot assign Database() and the mySQLi object to m_pInstance
so do:
class Database
{
private static $conn;
// ...
public function __construct()
{
self::$conn = new mysqli('localhost', 'root', 'root', 'database', '3307');
//...
and then
public function query($sql)
{
return self::$conn->query($sql);
// or
return mysqli_query(self::$conn, $sql);
}
EDIT
Working code:
class Database
{
private static $instance = null;
private static $conn;
private function __construct()
{
self::$conn = new mysqli('localhost', 'root', 'root', 'database', '3307');
}
public static function getInstance()
{
if (self::$instance == null) {
self::$instance = new Database();
}
return self::$instance;
}
public function query($sql)
{
return self::$conn->query($sql);
}
}
You get this error, because Database::$m_pInstance is contains an instance of Database class and not instance of MySQLi. You have created a "conflict" between to parts of the code:
public static function getInstance()
{
if (!self::$m_pInstance) {
self::$m_pInstance = new Database(); // << PROBLEM
}
return self::$m_pInstance;
}
Which overrides what your constructor does:
private function __construct()
{
self::$m_pInstance = new mysqli( /* .. */ ); // PROBLEM
if (!self::$m_pInstance) {
throw new Exception('Could not .. blah');
}
else {
return self::$m_pInstance;
}
}
Even though the constructor assigns self::$m_pInstance the instance of MySQLi object, it gets overridden by self::$instance = new Database(); right after.
Also, in php __constuct() method should not return, ever.
That said, i think is should warn you that singleton is considered to be an anti-patterns, and should be avoided. Your code also has the unintended side-effect, forcing you to have only one database (not connection, the database) available per application.
You might benefit from watching few lectures:
Advanced OO Patterns (slides)
Global State and Singletons
Don't Look For Things!
Your code does not look right.
first, you assign $m_pInstance a new Database instance. But then, in the constructor, you assign it a new mysqli instance. I am unsure how php handles this case, but it seems that it treats it as Database object as indicated by your error message. The Database class however does not have a query method.
So the solution would be to save the mysqli object in a different field and add getters and setters for it or delegate the methods to it.

Categories