I have written a class that connects to a database using MySQLi and has methods for the connection itself and returns the instance of the MySQLi class.
This works, but feels a little "clunky" and can be a bit slow, can someone help me to improve this?
The class is as follows:
<?php
/**
* Connect to a db.
*/
class mysqli_connector
{
/** Private to implement Singleton pattern */
private function __construct() { }
private static $init;
/** @return mysqli_connector */
public static function Init()
{
return static::$init = (
null === static::$init ? new self() : static::$init
);
}
/** @var mysqli */
private static $link;
/**
* Sets and gets the link to the database based on params
* @param string $host
* @param string $username
* @param string $password
* @param string $dbname
* @return mysqli
*/
public function link($host = '', $username = '', $password = '', $dbname = '')
{
static::$link = mysqli_init();
if ($host != '' && $username != '' && $password != '' && $dbname != '')
{
static::$link->real_connect($host, $username, $password, $dbname);
}
else if ($host != '' && $username != '' && $password != '' && $dbname == '')
{
static::$link->real_connect($host, $username, $password);
}
else if ($host != '' && $username != '' && $password == '' && $dbname == '')
{
static::$link->real_connect($host, $username);
}
else if ($host != '' && $username == '' && $password == '' && $dbname == '')
{
static::$link->real_connect($host);
}
else
{
static::$link->real_connect();
}
return static::$link;
}
}
EDIT
I use the class as such:
<?php
require_once 'include/class/_db/mysqli-connector.php';
$connector = mysqli_connector::Init();
$link = $connector->link("myhost", "mysuser", "mypass", "mydbname");
var_dump($link); # Make sure it works!
?>
Output from the var_dump($link);
object(mysqli)[2]
public 'affected_rows' => int 0
public 'client_info' => string 'mysqlnd 5.0.11-dev - 20120503 - $Id: /* removed for security */ $' (length=79)
public 'client_version' => int 50011
public 'connect_errno' => int 0
public 'connect_error' => null
public 'errno' => int 0
public 'error' => string '' (length=0)
public 'error_list' =>
array (size=0)
empty
public 'field_count' => int 0
public 'host_info' => string 'localhost via TCP/IP' (length=20)
public 'info' => null
public 'insert_id' => int 0
public 'server_info' => string '5.6.26' (length=6)
public 'server_version' => int 50626
public 'stat' => string 'Uptime: 118450 Threads: 1 Questions: 149 Slow queries: 0 Opens: 70 Flush tables: 1 Open tables: 63 Queries per second avg: 0.001' (length=135)
public 'sqlstate' => string '00000' (length=5)
public 'protocol_version' => int 10
public 'thread_id' => int 117
public 'warning_count' => int 0
2 Answers 2
First, don't use else. Or try to avoid it. The link
method can be reduced drastically by just reading the docs.
host
Can be either a host name or an IP address. Passing the NULL value or the string "localhost" to this parameter, the local host is assumed. When possible, pipes will be used instead of the TCP/IP protocol.
Usually, using NULL
in a variable will help you achieve the default behavior of things. Take advantage of it.
/**
* Sets and gets the link to the database based on params
* @param string $host
* @param string $username
* @param string $password
* @param string $dbname
* @return mysqli
*/
public function link($host = null, $username = null, $password = null, $dbname = null)
{
static::$link->real_connect($host, $username, $password, $dbname);
return static::$link;
}
Secondly, why is $link
static? You're already using the Singleton Pattern, to make the $link variable static is double redundant against the pattern.
-
\$\begingroup\$ I use static for the
$link
as I am unable to access it otherwise, it does not allow me to use$this->link
, I am stuck withstatic::$link
unless there is another way to access it? \$\endgroup\$anon– anon2015年11月13日 15:14:33 +00:00Commented Nov 13, 2015 at 15:14 -
\$\begingroup\$ What error do you get? \$\endgroup\$Marco Aurélio Deleu– Marco Aurélio Deleu2015年11月13日 15:15:56 +00:00Commented Nov 13, 2015 at 15:15
-
\$\begingroup\$ I don't get any errors, as I said in my question, the class works fully and operationally, I just don't get what you mean by You're already using the Singleton Pattern, to make the $link variable static is double redundant against the pattern. \$\endgroup\$anon– anon2015年11月13日 15:51:10 +00:00Commented Nov 13, 2015 at 15:51
-
\$\begingroup\$ What I meant was what error you get when trying to access it through
$this->
. Make theprivate $link
variable non-static and replace everystatic::$link
with$this->link
. \$\endgroup\$Marco Aurélio Deleu– Marco Aurélio Deleu2015年11月13日 15:52:47 +00:00Commented Nov 13, 2015 at 15:52 -
\$\begingroup\$ Using $this when not in object context - Visual Studio debugger too with PHP Tools from Devsense \$\endgroup\$anon– anon2015年11月13日 15:57:07 +00:00Commented Nov 13, 2015 at 15:57
Each class method must do exactly what it intends to do. So, you must separate the connection from getting the database link. By doing so, it will be more clear what the methods are doing.
The connection you are trying to do can be simplified by using call_user_func_array and func_get_args functions.
class MySQLi_Connector
{
protected $link;
protected static $instance;
public static function getInstance()
{
if (!isset(self::$instance)) {
self::$instance = new self();
}
return self::$instance;
}
// you can give all the parameters for connection here
public function connect()
{
$instance = self::getInstance();
$instance->link = mysqli_init();
// before calling it you can check the arguments
call_user_func_array(array($instance->link, 'real_connect'), func_get_args());
// you can check the result to see if the connection succeeded
// return the instance for chainability
return $instance;
}
public function link()
{
return self::getInstance()->link;
}
}
and use it like:
$link = MySQLi_Connector::getInstance()
->connect("myhost", "mysuser", "mypass", "mydbname")
->link();
var_dump($link); # Make sure it works!
Later on you simply get the link as
$link = MySQLi_Connector::getInstance()->link();