php资源是通过引用传递的吗?

Posted

技术标签:

【中文标题】php资源是通过引用传递的吗?【英文标题】:Are php resources passed by reference? 【发布时间】:2013-04-25 14:08:42 【问题描述】:

我今天发现,除了对象和原语,php 还有resources。该文档指出默认情况下php passes names by value。但我们知道,在 PHP 5 中,objects are referenced by handle 等虽然句柄是按值传递的,但您可以将句柄本身视为引用,巧妙地避免了这个问题。

但是资源呢?它们是像对象一样只是句柄本身被视为引用,还是它们实际上是在传递时被复制的值?

例如:

/**
 * Close the ftp connection and throw an exception.
 *
 * @hack Because php doesn't have a `finally` statement,
 *       we workaround it to make sure the ftp connection is closed.
 * @param resource $conn FTP Buffer
 * @param Exception $e
 */
function ftpCloseWithException($conn, $e) 
    ftp_close($conn); // <-- Is this the same FTP Buffer resource or a new one?
    throw $e;

/**
 * Copy the README file from ftp.mozilla.org or do something equally arbitrary using ftp.
 */
function getMozReadme() 
    try 
        $conn = ftp_connect('ftp.mozilla.org');
        …
     catch (Exception $e) 
        ftpCloseWithException($conn, $e);
    

【问题讨论】:

资源总是通过引用传递 资源是参考 【参考方案1】:

不,默认情况下,它们不是通过引用传递,在这种情况下,它们将作为任何其他 PHP 变量处理。检查这个例子:

function test($fd) 
    $fd = NULL;


$fd = fopen('/tmp/test', 'w+');
test($fd);
var_dump(is_resource($fd)); // bool(true);

...但由于资源的性质,它们指向单个外部资源。这可以是一个文件、一个数据库连接或类似的东西。因此,对资源(或其副本)的任何操作都会对该单个外部资源产生直接影响。

检查这个例子:

function close($fd) 
    fclose($fd);


$fd = fopen('/tmp/test', 'w+');
close($fd);
var_dump(is_resource($fd)); // bool(false);

在上面的示例中,PHP 引擎在文件关闭后将所有范围内的 all 引用重置为 $fd。这意味着从这种副作用的角度来看,它们可能与其他变量不完全相同。

【讨论】:

准确地说,在 PHP 中默认情况下不会通过引用传递任何内容。 @PEMapModder 不正确,对象通过引用传递。 @NinoŠkopac 您根本无法在 PHP 中传递对象。您只能传递对象引用。默认情况下,对象引用不会通过引用传递。比较function f(&amp;$o) $o=new stdclass; function f($o) $o = new stdclass; @NinoŠkopac 从这个意义上说,您实际上是在传递对象引用,这类似于资源引用。您仍在处理相同的最终基础数据,但传递 &amp;$object 就像通过引用传递某物的引用。同时,PHP中不能对变量进行双重引用,即function f(&amp;$a) $a = "b"; $b =&amp; $c; f($b);仍然会修改$c,但如果$b = $object;,则不会修改真正的$object。【参考方案2】:

资源不是实际的连接。资源只不过是指向连接的指针。因此,当您关闭属于该资源的连接时,无论是原始连接还是复制连接,行为都没有区别。

【讨论】:

说“没关系”并不能回答问题或指定行为。 在这种情况下,说没关系并不意味着“我不在乎”。这意味着他们之间的行为没有区别。我将编辑文本【参考方案3】:

资源既不是对象也不是变量。它只是一个资源。基本上,这意味着您并没有真正与资源进行交互,例如一个对象。 PHP 文档本身说:

“由于资源变量包含打开文件、数据库连接、图像画布区域等的特殊处理程序,因此转换为资源没有任何意义。”

基本上,除非说您正在开发核心 Zend 引擎或为 PHP 创建扩展(如 PECL),否则您真的会非常担心资源问题。从 PHP 编码戳点来看,我们对资源做的唯一事情就是检查数据库连接尝试是否返回 NULL or a resource

您有一个名为get_resource_type() 的函数,它返回资源的type,例如说“文件”以返回fopen() 函数,但它只是一个命名标识符,没有什么可解决的..

【讨论】:

@raidenance:“我们唯一一次在资源上做事”这部分没有多大意义。文件操作、外部连接等都使用资源。 @nvanesch:我的意思是当我们直接对资源进行操作时,比如if($myResource=="&lt;something&gt;")... 好吧,现在我明白了。我以为你的意思是像 fopen($fileResource, "Foo"); 这样的东西几乎没有被使用过

以上是关于php资源是通过引用传递的吗?的主要内容,如果未能解决你的问题,请参考以下文章

PHP类知识----值传递和引用传递

地图是通过价值或Go中的参考传递的吗?

PHP 变量是按值传递还是按引用传递?

在 PHP 5 中如何通过引用传递对象?

通过 const 引用传递对象?

PHP 错误:“无法通过引用传递参数 2”