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


我今天发现,除了对象和原语之外,PHP还有 资源。文档声明默认情况下 php按值传递名称。但我们知道在PHP 5中, 对象由句柄引用,因此当句柄按值传递时,您可以将句柄视为引用本身,整齐地避免问题。

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

例如:

/**
 * 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);
    }
}

1607
2018-05-01 14:53


起源

资源总是通过引用传递 - Mark Baker
资源是参考 - nice ass


答案:


资源不是实际连接。资源只不过是指向连接的指针。因此,当您关闭属于此资源的连接时,它是原始的还是复制的并不重要。


5
2018-05-01 14:59





不,是他们  默认情况下,它们通过引用传递,在这种情况下,它们作为任何其他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引擎重置了 所有 文件关闭后,在所有范围内引用$ fd。这意味着从这种副作用的角度来看,它们可能并不完全相同 相同 作为其他变量。


7
2018-05-01 15:00



确切地说,默认情况下,PHP中没有任何内容通过引用传递。 - SOFe
@PEMapModder不正确,对象通过ref传递。 - Nino Škopac
@NinoŠkopac你根本无法在PHP中传递对象。您只能传递对象引用。默认情况下,对象引用不会通过引用传递。比较 function f(&$o){ $o=new stdclass; } 和 function f($o){ $o = new stdclass; } - SOFe
@NinoŠkopac,从这个意义上讲,您实际上是在传递对象引用,它类似于资源引用。您仍在处理相同的最终基础数据,但通过了 &$object就像通过引用传递某事物的参考。同时,你不能在PHP中双引用变量,即 function f(&$a) { $a = "b"; } $b =& $c; f($b); 仍在修改 $c,但如果 $b = $object;,真正的$对象不会被修改。 - SOFe


资源既不是对象也不是变量。这只是一个 资源。基本上,这意味着你没有像对象那样真正地与资源进行交互。 PHP文档本身说:

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

基本上除非说你正在研究核心Zend引擎或者像PECL那样为PHP创建扩展,否则你真的会担心资源问题。从PHP编码标记点开始,我们在资源上执行操作的唯一时间就是检查是否返回了数据库连接尝试 NULL or a resource

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


1
2018-05-01 14:58



@raidenance:“我们唯一一次对资源进行处理”这一部分没有多大意义。文件操作,外部连接等都使用资源。 - nvanesch
@nvanesch:我的意思是当我们直接对资源进行操作时,比如说 if($myResource=="<something>")... - raidenace
好的,现在我明白了。我以为你的意思是这样的 fopen($fileResource, "Foo"); 几乎没用过 - nvanesch