2008-10-27 53 views
11

问题是,数据库连接是否应通过引用或值传入?通过引用在PHP中传递数据库连接

对我来说,我特别质疑一个PHP到MySQL的连接,但我认为它适用于所有数据库。

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

在数据库连接中,我认为它在函数内部发生了变化,因为查询可能会改变最后一个插入id或num行等内容。 (我想这是另一个问题:是否存储在连接中的数字行和插入ID或实际调用返回到数据库?)

因此,如果连接已通过,是否内存或速度问题通过参考或价值?它对PHP 4和5有什么影响?

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

回答

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 
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; 
} 
} 
?> 
+2

“功能DoSomething1(&$连接){...}”不是呼叫时间通过引用 – 2008-10-27 21:06:23

0

我真的没有对PHP的一个明确的答案,但在总体上,似乎我说,你想通过引用传递这个,如果你不明确地确定您遇到性能问题,通过传递时值。

1

数据库连接实际上并不持有基本价值观,所以你不必担心失去一个函数内的转让。比喻来说,你可以想到一个DB 连接为跑道编号 - “OK,DB连接12被清除以用于查询” - 查询和结果集使用连接,并且可能需要独占访问一段时间,但连接不知道底层数据的任何内容。

0

一般来说,PHP的引用不会更快。这是一个常见的误解,因为它们在语义上类似于C指针,所以熟悉C的人通常会认为它们以相同的方式工作。并非如此。实际上,除非实际赋值给变量(除非变量是对象,否则在任何情况下都是错误的样式),否则引用比拷贝要慢一点。

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

1

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

我发现这个使用XDebug & WinCacheGrind,它善意地显示所有被调用的析构函数 - 在我的情况下,是半个或更多的数据库对象。

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

5

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

在PHP 4中,像数据库连接和结果集这样的东西应该通过引用显式传递。在PHP 5中,这是自动完成的,所以您不必明确说明。

顺便说一句,创建数据库句柄的单例方法是一个好主意:你可以做$db = & Database::Connection();并总是得到正确的句柄。这样可以避免使用全局变量,并且静态方法可以为您执行额外的魔法(如自动打开它)。当你的应用程序扩展到需要多个数据库的时候,要小心一点:那么你的魔术功能就必须知道如何让你回到正确的一个。 IME这不是非常困难;解决这个问题的基本方法是需要DB句柄的代码层知道如何请求正确的代码层。