在PHP中通过引用传递数据库连接

时间:2008-10-27 20:41:27

标签: php mysql database

问题是数据库连接是应该通过引用还是通过值传递?

对我来说,我是专门质疑PHP到MySQL的连接,但我认为它适用于所有数据库。

我听说在PHP中将变量传递给函数或对象时,它会被复制到内存中,因此会立即使用两倍的内存。我还听说只有在对值进行了更改后才会复制它(例如从数组中添加/删除键)。

在数据库连接中,我认为它在函数内被更改,因为查询可能会改变最后一个插入id或num行。 (我想这是另一个问题:连接中存储了num rows和insert id之类的东西,或者实际调用是否回到了数据库?)

那么,如果通过引用或值传递连接,那么内存或速度是否重要? PHP 4对5有什么不同吗?

// $connection is resource
function DoSomething1(&$connection) { ... }
function DoSomething2($connection) { ... }

7 个答案:

答案 0 :(得分:16)

PHP资源是一种特殊类型,它本身就是一个引用。通过值传递或通过引用明确传递它不会产生任何影响(即,它仍然是参考)。您可以在PHP4下自行检查:

function get_connection() {
  $test = mysql_connect('localhost', 'user', 'password');
  mysql_select_db('db');
  return $test;
}

$conn1 = get_connection();
$conn2 = get_connection(); // "copied" resource under PHP4

$query = "INSERT INTO test_table (id, field) VALUES ('', 'test')";
mysql_query($query, $conn1);
print mysql_insert_id($conn1)."<br />"; // prints 1

mysql_query($query, $conn2);
print mysql_insert_id($conn2)."<br />"; // prints 2

print mysql_insert_id($conn1); // prints 2, would print 1 if this was not a reference

答案 1 :(得分:5)

这不是你应该关注的速度,而是记忆。

在PHP 4中,应该通过引用显式传递数据库连接和结果集等内容。在PHP 5中,这是自动完成的,因此您不必将其明确化。

BTW,用于创建数据库句柄的单例方法是一个好主意:您可以$db = & Database::Connection();并始终获得正确的句柄。这样可以避免使用全局,静态方法可以为您做额外的魔术(比如自动打开它)。当你的应用程序扩展到足以需要多个数据库时要小心:那么你的魔法功能必须知道如何将你的技术交给正确的人。 IME这并不是非常困难;解决这个问题的基本方法是需要DB句柄的代码层知道如何请求正确的。

答案 2 :(得分:4)

正在降低调用时传递引用,因此我不会使用首先描述的方法。另外,一般来说,默认情况下,资源在PHP 5中通过引用传递。因此,不应该要求提供任何引用,除非确实需要,否则不应该打开多个数据库连接。

就个人而言,我使用单例工厂类进行数据库连接,每当我需要数据库引用时,我只需调用Factory :: database(),这样我就不必担心多个连接或传递/接收引用。

<?php
Class Factory
{
  private static $local_db;

/**
* Open new local database connection
*
* @return MySql
*/
public static function localDatabase() {
    if (!is_a(self::$local_db, "MySql")) {
        self::$local_db = new MySql(false);
        self::$local_db->connect(DB_HOST, DB_USER, DB_PASS, DB_DATABASE);
        self::$local_db->debugging = DEBUG;
    }
    return self::$local_db;
}
}
?>

答案 3 :(得分:1)

数据库连接实际上并不包含基础值,因此您不必担心丢失函数内的赋值。比喻说,您可以将DB 连接视为跑道编号 - “确定,数据库连接12被清除以用于查询” - 查询和结果集使用连接,可能需要一段时间的独占访问权限,但连接对底层数据一无所知。

答案 4 :(得分:1)

有些人说你不需要为PHP 5担心这个问题。如果你有一个用于所有访问的数据库OBJECT,这是不正确的。在这种情况下,您需要通过引用传递,否则它将实例化一个新的DB对象,该对象(通常)会创建与数据库的新连接。

我发现这是使用XDebug&amp; WinCacheGrind,它会显示所有被调用的析构函数 - 在我的例子中,是一个半数或更多的数据库对象。

澄清一下:我指出这一点的原因是这是使用数据库连接的常用方法,而不是原始连接资源。

答案 5 :(得分:0)

我真的没有针对php的具体答案,但总的来说,如果您没有明确确定在传递值时遇到性能问题,我会觉得您希望通过引用传递此信息。

答案 6 :(得分:0)

一般来说,PHP中的引用并不快。这是一种常见的误解,因为它们在语义上与C指针类似,因此熟悉C的人通常认为它们的工作方式相同。不是这样。事实上,引用比副本慢一点,除非你实际分配给变量(在任何情况下都是坏的样式,除非变量是一个对象)。

PHP有一种称为写时复制的机制,这意味着变量在需要之前不会实际复制。您可以将庞大的数据结构传递给函数;只要它只是从它读取,它没有任何区别。但是,引用需要在内部寄存器中添加一个额外的条目,因此它实际上需要一些额外的处理(尽管几乎不可察觉)。