0
\$\begingroup\$

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
\$\endgroup\$

2 Answers 2

1
\$\begingroup\$

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.

\$\endgroup\$
5
  • \$\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 with static::$link unless there is another way to access it? \$\endgroup\$
    – anon
    Commented Nov 13, 2015 at 15:14
  • \$\begingroup\$ What error do you get? \$\endgroup\$ Commented 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
    Commented Nov 13, 2015 at 15:51
  • \$\begingroup\$ What I meant was what error you get when trying to access it through $this->. Make the private $link variable non-static and replace every static::$link with $this->link. \$\endgroup\$ Commented 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
    Commented Nov 13, 2015 at 15:57
1
\$\begingroup\$

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();
\$\endgroup\$
0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.