PHP - 如何让mysqli_connect()返回一个RESOURCE,以便它可以与define()

时间:2016-09-19 14:21:45

标签: php mysql global handle mysql-connect

我在PHP中测试不同的MySQL连接方法时注意到了一些事情。

在PHP中建立数据库连接时,我经常使用odbc_connect()。我将odbc_connect()返回的资源变量保存到一个全局常量(使用define()函数),我可以在整个应用程序中方便地访问它。像这样:

使用odbc_connect()并将返回值保存为常量可以正常工作:

<?php
define("_conn", odbc_connect("Driver={MySQL ODBC 5.3 Unicode Driver};Database=MyDB;", "user", "pass"));
?>

将mysql_connect()(不推荐使用的)的返回值保存到常量中也可以正常工作:

<?php
define("_conn", mysql_connect("localhost", "user", "pass", "MyDB"));
?>

但是,尝试将mysqli_connect()的返回值保存为常量会 NOT 工作:

<?php
define("_conn", mysqli_connect("localhost", "user", "pass", "MyDB"));
?>
Warning: Constants may only evaluate to scalar values in C:\...\script.php on line 164

这很不幸,因为使用mysqli_connect()来建立连接并将句柄保存到常量中会很好,其中odbc_connect()是不可用的。我做了研究,发现我可以使用MySQL返回RESOUCE(并且可以与define()函数一起使用)的唯一两个数据库连接函数是odbc_connect()和mysql_connect()(不推荐使用)。请看这个链接:http://php.net/manual/en/resource.php

有没有办法让mysqli_connect()返回一个RESOUCE,这样我就可以在常量中使用它的返回值(使用define()函数)?

PDO也不会返回RESOUCE。

3 个答案:

答案 0 :(得分:2)

我建议在这种情况下使用单例模式 这是一个例子:

<?php
 class PDOConnection {

/**
 * singleton instance
 * 
 * @var PDOConnection 
 */
protected static $_instance = null;

/**
 * Returns singleton instance of PDOConnection
 * 
 * @return PDOConnection 
 */
public static function instance() {

    if ( !isset( self::$_instance ) ) {

        self::$_instance = new PDOConnection();

    }

    return self::$_instance;
}

/**
 * Hide constructor, protected so only subclasses and self can use
 */
protected function __construct() {}

function __destruct(){}

/**
 * Return a PDO connection using the dsn and credentials provided
 * 
 * @param string $dsn The DSN to the database
 * @param string $username Database username
 * @param string $password Database password
 * @return PDO connection to the database
 * @throws PDOException
 * @throws Exception
 */
public static function getConnection() {


    $dsn = 'mysql:dbname=_____;host=_____';
    $username = '_____';
    $password = '_____';

    $conn = null;
    try {

        $conn = new \PDO($dsn, $username, $password);

        //Set common attributes
        $conn->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);

        return $conn;

    } catch (PDOException $e) {

        //TODO: flag to disable errors?


    }
    catch(Exception $e) {

        //TODO: flag to disable errors?


    }
}

/** PHP seems to need these stubbed to ensure true singleton **/
public function __clone()
{
    return false;
}
public function __wakeup()
{
    return false;
}
}

?>

然后你可以在任何地方使用它:

$dbh =  PDOConnection::getConnection();

答案 1 :(得分:0)

嗯,如您所见,PHP不允许存储non-scalar values in constants

但您仍然可以根据自己的需要实现Singleton模式或Registry

答案 2 :(得分:0)

在这种情况下,我肯定不会推荐单例模式,实际上,在一般情况下也是如此,因为它在很多情况下很难测试和扩展,并且不能用于同时处理多个连接,这可能是在某些时候需要。

单身模式只能让它变得容易全球化&#34;你的应用程序之间的连接,当然,因为,当时,那里有许多写得不好的PHP应用程序,它将开始每个脚本与新的连接导致许多重复的连接打开。 但实际上,使用全局直接在需要的对象上比使用单例更好地解决这个问题。当然,最好是实现某种依赖注入或注册模式来实现这一点,但是我认为这是一般的单例模式有多糟糕,尤其是在处理数据库时更是如此。

您甚至不需要实现自己的数据库处理程序,甚至不需要使用任何供应商,就像在Doktor OSwaldo example中完成一样,您可以从PDO获得所需的一切:

$db = new PDO('mysql:host=localhost;dbname=myDb', 'user', 'pass');

您可以将其包装到函数/方法中以在返回之前操作连接,甚至可以实现简约连接存储:

function getConnection($which= 'default') {
    static $connections = [
        // connectionName => connectionOptions
        'default' => [
            'dsn'  => 'mysql:host=localhost;dbname=myDb',
            'user' => 'user',
            'pass' => 'pass',
            // 'option' => value,
            // ...
        ],
        // ...
    ], $dbStore = [];

    if (isset($dbStore[$which])) {
        return $dbStore[$which];
    }

    if (!isset($connections[$which])) {
        throw new \Exception("DB setup not supported");
    }

    $dbStore[$which] = new \PDO($connections[$which]['dsn'], $connections[$which]['user'], $connections[$which]['pass']);

    // eventually set some options that could be stored in $connections[$which]
    // $dbStore[$which]->setAttribute( ...

    return $dbStore[$which];
}

这将提供相同的易用性,并保证单独使用重复连接,但仍允许您一次使用多个连接:

// get default connection
$defaultDb = getConnection();

// get another connection
$anotherDb = getConnection('another');

当然,您最好在某种配置中存储连接选项(例如,在第一次调用getConnection时获取它)。这个例子仍然没有理想的可测试性(只是它的简单易于模拟),但它几乎就像在许多情况下一样。