Set $mysqli as a global variable for OOP - php

Ok,
This is sort of an involved problem, but any help or advice would be incredibly appreciated.
So I'm working with a site that (using .htaccess) redirects all traffic to a load.php. For any sql functionality, I have an abstract class that has a lot of query statements as functions that pass parameters to define the specifics of each query.
e.g.
$table->update("constraints")
I'm trying to figure out how to set the connection to the database on load.php, and then set the connection as a variable ($mysqli) that can then be referenced in my abstract query class without having to pass the parameter to every single query function call.
Again, any help or advice would be appreciated.
Here's an example of a function:
function clearTable (){
$mysqli = dbConnect::connect();
$sql = "TRUNCATE TABLE $this->tablename";
$mysqli->query($sql);
}
If I connect to the database in a construct function and set $this->mysqli and replace $mysqli = dbConnect::connect(); with $mysqli = $this->mysqli, none of the queries work. Though they work with a fresh reconnect on each call.

You should use Dependency Injection for this.
Basically it means that the class that needs the database connection doesn't create the connection, it just receives the already instasiated instance.
Example
In some init file:
// Create the db connection
$db = new Mysqli(......);
// Pass it to the query class that needs it
$queryClass = new QueryClass($db);
Then in your class file:
class QueryClass
{
protected $db;
public function __construct($db)
{
// $this->db will now be the same Mysql instance
$this->db = $db;
}
public function doSomeQuery()
{
$this->db->query(....);
}
}
A bonus for this is that you don't need to touch the QueryClass, if you ever want to start making some unit tests. You only need to pass a DB connection to a test database instead.

After looking through this a bit more, I can also create my db::connect() function to look like this:
class dbConnect {
private static $db;
private $mysqli;
private function __construct() {
$this->mysqli = new mysqli(HOST, USER, PASSWORD, DATABASE);
}
function __destruct() {
$this->mysqli->close();
}
public static function connect() {
if (self::$db == null) {
self::$db = new dbConnect();
}
return self::$db->mysqli;
}
}
and pass that as $this->mysqli in the query functions file

Related

Use MySQLi object based within a class

require("classes/controller.class.php");
$db = new mysqli(__DBHOST, __DBUSER, __DBPASS, __DBDATA);
if ($db->connect_errno) {
printf("Connect failed: %s\n", $db->connect_error);
exit();
}
$controller = new Controller;
Within the Controller class I want to use the $db MySQLi connection. So within a public function I used:
$result = $db->query("SELECT * FROM colors");
var_dump($result);
But I get this error:
Fatal error: Call to a member function query() on a non-object in /home/cloud/public/teamdresser/controllers/IndexController.php on line 8
Am I doing something wrong? Do I need to pass the $db connect first, or use global or something?
Thanks in advance
If $db is a global variable, you'll need to import it in your function:
public function YourFunction()
{
global $db;
$result = $db->query("SELECT * FROM colors");
..
}
Instead of doing this, you might want to consider encapsulating $db in a database class and create it as a singleton, or, arguably better, pass it to the constructor of Controller. But that remark might lead to new discussions about design, while complete books have been written about this subject. So for now, just import the global like described above. ;)
You could use a class with a singleton instance
class Database {
private static $_instance;
public static function getInstance() {
//If the connection is not initialized, this creates it and store
if (empty(Database::$_instance))
Database::$_instance = new Database();
return Database::$_instance;
}
private $_db;
private function __construct() {
$this->_db = new mysqli(__DBHOST, __DBUSER, __DBPASS, __DBDATA);
if ($db->connect_errno) {
printf("Connect failed: %s\n", $db->connect_error);
exit();
}
}
private function __destruct() {
$this->_db->close();
}
public function query($query) {
return $this->_db->query($query);
}
}
You called in this manner
$result = Database::getInstance()->query("SELECT * FROM colors");
You have created a connection and executed with calling a function. Once the script is terminated, the connection will be autorealeased by the destructor.
This should be only a start point. You could create all functionality that you want (e.g. escape parameters, insert, update, delete, and so on...)

OOP efficiency when using a class in another class

I have a class called DB (class.pdo.php) that does all the handling on mysql queries using PDO and another class called user that I use to manage a login system.
My question relates to always having to instantiate the $db in every public function of users so I can use DB. Is this efficient? Shouldn't I be instantiating DB inside the __construct() of users?
This is my code
require_once("../../class.pdo.php");
class user {
private $db = null;
public function __construct(){
/* Empty? */
}
public function find_by_email($email){
$db = new db();
$db->query('SELECT * FROM users WHERE email = :email LIMIT 1');
$db->bind(':email',$email);
$result = $db->single();
return $result;
}
public function create($email,$password,$first_name,$last_name){
$db = new db();
$db->query("INSERT INTO users(email,password,first_name,last_name,created_at) VALUES (:email,:password,:first_name,:last_name,NOW())");
$db->bind(':email',$email);
$db->bind(':password',$password);
$db->bind(':first_name',$first_name);
$db->bind(':last_name',$last_name);
$result = $db->execute();
return $db->lastInsertId();
}
[more similar functions ommited]
Well, despite of some comments suggesting the use of the Singleton pattern, I totaly disagree in using it for this purpose.
Your application will not always use a single connection to just one database.
Let me show you how I'd do this:
class DbConnector {
private $dbh;
private $dsn;
public function __construct($dsn) {
$this->dsn = $dsn;
}
private function connect() {
if($this->dbh === null) {
$this->dbh = new PDO($this->dsn);
}
}
public function disconnect {
if($this->dbh !== null) {
$this->dbh = null;
}
}
public function query($sql) {
$this->connect();
//... do the rest
}
public function fetchAll($sql) {
$this->connect();
//... do the rest
}
public function insert($table, $values) {
$this->connect();
//... do the rest
}
public function update($table, $values, $cond) {
$this->connect();
//... do the rest
}
public function delete($table, $cond) {
$this->connect();
//... do the rest
}
}
class User {
private $dbConn;
public function __construct(DbConnector $dbConn) {
$this->dbConn = $dbConn;
}
public function create($email,$password,$first_name,$last_name){
$this->dbConn->query("INSERT INTO users(email,password,first_name,last_name,created_at VALUES (:email,:password,:first_name,:last_name,NOW())");
$this->dbConn->bind(':email',$email);
$this->dbConn->bind(':password',$email);
$this->dbConn->bind(':first_name',$email);
$this->dbConn->bind(':last_name',$email);
$this->dbConn->execute();
return $this->dbConn->lastInsertId();
}
// ...
}
Results:
No singleton used = testable.
Connection to the database is just openned when needed
Your connection is persistent. If you open and close connections in every method, you loose the capability of creating transactions.
What about using the Singleton pattern to create one object for the connection and use it everytime you need it, instead of creating new objects all the time?
I would do something similar with lazy loading: don't initiate in the constructor unless you're sure you actually need the connection every time an object is created but absolutly don't create a new object on each method call. Instead, save the resulting object into an object var which is checked on each method call and initiates the connection if missing.
class user {
protected $_db = null;
private function _init_db() { $this->_db = new XXX; }
public function create( $x, $y, $z ) {
if ( ! $this->_db ) $this->_init_db();
# use $this->_db ..
}
public function find_by_email( $x, $y, $z ) {
if ( ! $this->_db ) $this->_init_db();
# etc
}
}
This has the advantages of avoiding global static state (singletons..) and only creates the connection / object at the very last moment so you're sure you actually need it and it's not just a useless connection.
Speaking of efficiency, the main problem with your code is that it establishes new connection for the every method called. This one is indeed inefficient to the point of killing your database server. And it's incomparable to the other problem you have.
So, in general, you can have whatever way you want - either get somehow an instance of db class in the every function or use a class variable - but either way have to use single PDO instance throughout whole application.
Also I find your functions quite inefficient from the amount of code point of view, and would have optimized them this way
public function create($email,$password,$first_name,$last_name){
$sql = "INSERT INTO users(email,password,first_name,last_name,created_at) VALUES (?,?,?,?,NOW())";
$this->db->query($sql);
$result = $db->execute(func_get_args());
return $db->lastInsertId();
}
From a object point of view, I'd leave database instantiating within the methods, rather than an entire class.
Each method should only see the variables and data it needs, in order to perform its function.
For instance, a createUser() method would need to see variables or properties such as $username, $usergroupId, as well as $database etc.
However, you may have a function which is called randomPassword(), which generates a random password from numbers and letter.
This randomPassword() function doesn't need the database object and therefore, an already initialised database connection in the object scope would be wasteful.
It would be better only to create the new database object in methods that required it.
In addition, in my application, I don't create a new database connection each time I used new database. Instead, I've opted for a singleton PDO database object which keeps the connection active.
I can then just call the database object statically to retrieve an existing connection. Therefore, if, in the process of running my application I need to have 20 database objects, my application then only returns the same object, and the same connection.

use an object previously declared in an other class

This is my general php page:
<?php
require_once('includes.php');
require_once('cms.class.php');
.....
rest of the page
?>
in includes.php an pro object called $db is initiated which I want to use in the class specified in the cms.class.php
includes.php:
$db = new PDO('mysql:host=localhost;dbname=xxxxx','xxxxx','xxxxxx');
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$db->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
How can I use this database object in my classes without having multiple places where my credentials are stored?
You need want a dependency manager or a bootstrapper or whatever you want to call it.
class Dependency_Manager {
private $db;
public function __construct($settings) {
$this->db = new PDO('mysql:host=localhost;dbname=' . settings["dbname"],settings["username"],$setings["password"]);
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$db->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
}
public function getDB() {
return $db;
}
}
class CMS {
public function __construct(PDO $db) {
/* .. */
}
}
$setting = array(/* etc */);
$dm = new Dependency_Manager($settings);
$cms = new CMS($dm->getDB());
This approach scales very well and can handle any dependecy. It also aims to put all the settings in one place so you don't have configuration settings littered everywhere. The $dm is the only one who knows the settings, if you need to construct something based on the settings, put it in the $dm.
There are 2 ways that you could go about this.
The first way, injection, is growing in popularity. Injection means you would supply $db to your class. You could do something like this.
Injection:
class CMS_class {
protected static $db;
public function __construct($db) {
if ( ! isset(self::$db))
self::$db = $db;
}
public function __get($name) {
if ($name === 'db')
return self::$db;
}
}
Now when you construct the CMS class you pass it the $db variable which is accessible via ->db, but there is only one instance.
The second method would be to call it globally in every function you use it.
Global:
class CMS_class {
function hello_world() {
global $db;
var_dump($db);
}
}
This way is losing popularity because globals are generally frowned upon and you will have to declare it in every function that you need $db.
There are other good answers out there that relate to your question.
How can I use "Dependency Injection" in simple php functions, and should I bother?

How do you manage database connections in php?

So recently I've really started to use php actively, and I need some insights on different ways to use database connections.
At first I just used the simple mysql_connect():
<?php
$connection = mysql_connect(DB_HOST, DB_USER, DB_PASS) or die(mysql_error());
mysql_select_db(DB_DB, $connection);
?>
After a while I created a database class which I started to include and initialize in every file - something like this:
<?php
class MySQL_DB {
var $connection;
function MySQL_DB(){
$this->connection = mysql_connect(DB_HOST, DB_USER, DB_PASS) or die(mysql_error());
mysql_select_db(DB_DB, $this->connection);
}
function query($q){
$res = mysql_query($q, $this->connection) or die(mysql_error());
return $res;
}
}
$database = New MySQL_DB;
?>
And this is what I'm using at the time - and it's working fine - but there are always ways to improve.
So my question to you is how do you manage your database connections?
Do you use classes?
What does your classes contain (just
the connection or even functions?)
What practices do you recommend?
I recommend to use PDO. Don't reinvent the weel. It's a nice OO-interface to many database engines.
Additionally I create a small function which just inititializes PDO object. So all connection settings can be changed in one place.
Your current approach is pretty standard, and works well. I used it for a long time. It's true that modules like PDO provide base functionality like this now, which is very nice as well and can get you away from problems with home-brew code.
However, I've taken the connection management one step further. If you get into a complex application, you might get into a situation where you have multiple databases, or heavy database use. Including a single database connection file and having a global $database variable becomes unwieldy for multiple databases, and it's unnecessary for application requests that might not need a database connection. Remember, connecting to the database is expensive.
What I've done is create a singleton DatabaseManager class that handles the database object for me, and makes sure multiple connections to a given DB don't get instantiated. Instead of initializing a new database object at the top of your app, you simply call on the DatabaseManager every time you need the object.
$db = DatabaseManager::getDatabase();
Here's an example class that I had whipped up for a CodeIgniter project. You can see in the getDatabase() function it simply loads CodeIgniter's default database object, which you would substitute for your own class (and run the connection routine for it) if you weren't using CI. This is a pretty simplistic management class, and could be extended to manage multiple connections to different databases fairly easily.
<?php
/**
* Implements the Singleton pattern to prevent multiple instantiations and connections
* to the application database.
*
*/
class Database_manager
{
private static $instance;
public $db;
/**
* Constructor function is declared private to prevent instantiation.
*
*/
protected function __construct()
{
parent::__construct();
}
/**
* Returns an instance of a Database_manager.
*
* #return object Database_manager object
*/
public static function getInstance()
{
if (self::$instance == null) {
$className = __CLASS__;
self::$instance = new $className();
}
return self::$instance;
}
public static function getDatabase()
{
$instance = self::getInstance();
if ($instance->db == null) {
//utilize CodeIgniter's database loader
$instance->db = $instance->load->database('',true);
if (! is_object($instance->db)) throw new Exception("Could not load database.");
}
return $instance->db;
}
}
Perhaps the most common advantage I get out of using this style of connection management is when I have to take down an application for database maintenance. By not instantiating a database connection until I need it, I can easily put up a "maintenance in progress" message on a site (short circuiting normal MVC dispatching), and not worry about requests to the application opening a DB connection while maintenance is in progress.
Usage of classes are the way to go to increase customized re-usability.
Bring in all generic implementations into the class. You are on the right track.
This website has the following clean approach.
This website link is no longer present. Archive Link.
class connection {
// Possible Modules are as follows:
// DBX_MYSQL, DBX_ODBC, DBX_PGSQL, DBX_MSSQL, DBX_FBSQL, DBX_SYBASECT, DBX_OCI8, DBX_SQLITE
private $module = DBX_MYSQL;
private $host = "localhost";
private $database = "test";
private $username = "testuser";
private $password = "testpass";
private $link;
private $result;
public $sql;
function __construct($database=""){
if (!empty($database)){ $this->database = $database; }
$this->link = dbx_connect($this->module,$this->host,$this->database,$this->username,$this->password);
return $this->link; // returns false if connection could not be made.
}
function query($sql){
if (!empty($sql)){
$this->sql = $sql;
$this->result = dbx_query($this->link,$sql,DBX_RESULT_UNBUFFERED);
return $this->result;
}else{
return false;
}
}
function fetch($result=""){
if (empty($result)){ $result = $this->result; }
return dbx_fetch_row($result);
}
function __destruct(){
dbx_close($this->link);
}
}
In your database manager example, you did not define a parent for your class.
Therefore, invoking parent::__constructor() yields an exception,
and also, you cannot use the load property of code ignitor.
Which class did you use as an extension for your DatabaseManager?
Since i do not know where you placed your databasemanager code, nor which class you used as its parent, i circumvented the exceptions by making the getDatabase() method receive an input parameter which i called $loader.
Normally, this $loader object will be the model class requiring access to a database.
public static function getDatabase($loader)
{
$instance = self::getInstance();
if ($instance->db == null) {
//utilize CodeIgniter's database loader
$instance->db = $loader->load->database('default',true);
if (! is_object($instance->db)) throw new Exception("Could not load database.");
}
return $instance->db;
}
Best regards.

Converting mysql to mysqli - how to get superglobal connection object?

I am trying to convert code from mysql to mysqli.
The code uses a single mysql_connect in a file which is included by every other file.
mysql_connect returns a MySQL link identifier that is a superglobal so you can rely on having a database connection available in any of your own functions.
It looks like with mysqli_connect this is not the case, the object returned isn't global.
Does this mean I have to add : global $mysqli; at the top of every function, or is there an way of making it a superglobal?
Relying on the fact that PHP will use the last opened connection resource if you don't specify one, is probably not a very good idea.
What happens if your application changes and you need two connections, or the connection is not there?
So it seems you need to do some refactoring anyway.
Here's a solution similar to Karsten's that always returns the same mysqli object.
class DB {
private static $mysqli;
private function __construct(){} //no instantiation
static function cxn() {
if( !self::$mysqli ) {
self::$mysqli = new mysqli(...);
}
return self::$mysqli;
}
}
//use
DB::cxn()->prepare(....
I usually make a function:
$mysqli = new mysqli(...);
function prepare($query) {
global $mysqli;
$stmt = $msqyli->prepare($query);
if ($mysqli->error()) {
// do something
}
return $stmt;
}
function doStuff() {
$stmt = prepare("SELECT id, name, description FROM blah");
// and so on
}
and then call that. That being said, I've since abandoned mysqli as being too bug-ridden to be considered usable. Shame really.
A very simple way to do this would be with a fixed database class, just to hold the mysqli connection object:
class Database {
public static $connection;
}
Database::$connection = new mysqli(HOST, USERNAME, PASSWORD, DATABASE);
Then you can access it in the normal ways:
$sql = 'SELECT * FROM table';
$result = Database::$connection->query($sql);
$result = mysqli_query(Database::$connection, $sql);
echo 'Server info ' . mysqli_get_server_info(Database::$connection);
To introduce some oop to you and solve your problem, you could use a class like this:
class MyDatabase
{
private static $_connection;
public static function connect()
{
$mysqli = new mysqli(...);
self::$_connection = $mysqli;
}
public static function getConnection()
{
return self::$_connection;
}
}
In your database-connection file you would load this class and execute MyDatabase::connect(); once.
To get the $mysqli-connection anywhere in your script, just call MyDatabase::getConnection();.

Categories