PHP 8:将“资源”分配为属性、参数或返回类型

dak*_*kis 12 php stream psr-7 php-8

我正在将我的项目从 PHP 7.0 更新到 PHP 8.0,但我无法确定是否允许显式分配resource为数据类型:

  • 属于一类财产
  • 方法/函数参数
  • 由方法/函数返回

我现在所知道的是:

直到现在我读到:

我在某个地方错过了什么吗?

感谢您的时间。


为了更清楚起见,这就是我想要resource在项目中使用数据类型的方式(PSR-7 实现):

<?php

namespace MyPackages\Http\Message;

use Psr\Http\Message\StreamInterface;

/**
 * Stream.
 */
class Stream implements StreamInterface {

    /**
     * A stream, e.g. a resource of type "stream".
     *
     * @var resource
     */
    private resource $stream;

    /**
     * @param string|resource $stream A filename, or an opened resource of type "stream".
     * @param string $accessMode (optional) Access mode. 'r': Open for reading only.
     */
    public function __construct(string|resource $stream, string $accessMode = 'r') {
        $this->stream = $this->buildStream($stream, $accessMode);
    }

    /**
     * Build a stream from a filename or an opened resource of type "stream".
     *
     * Not part of PSR-7.
     *
     * @param string|resource $stream Filename, or resource.
     * @param string $accessMode Access mode.
     * @return resource
     * @throws \RuntimeException If the file cannot be opened.
     * @throws \InvalidArgumentException If the stream or the access mode is invalid.
     */
    private function buildStream(string|resource $stream, string $accessMode): resource {
        if (is_string($stream)) {
            //... some validations ...

            /*
             * Open the file specified by the given filename.
             * E.g. create a stream from the filename.
             * E.g. create a resource of type "stream" from the filename.
             */
            try {
                $stream = fopen($stream, $accessMode);
            } catch (\Exception $exception) {
                throw new \RuntimeException('The file "' . $stream . '" could not be opened.');
            }
        } elseif (is_resource($stream)) {
            if ('stream' !== get_resource_type($stream)) {
                throw new \InvalidArgumentException('The provided resource must be an opened resource of type "stream".');
            }
        }

        return $stream;
    }
}
Run Code Online (Sandbox Code Playgroud)

Chr*_*aas 13

不,您不能使用 键入提示resource

这里是2015 年提出它的RFC ,这里是实现的PR ,这里是关于它的讨论主题

要点是 PHP 社区希望摆脱资源,因为它们代表了一种旧的做事方式。而且,resource它太通用了,基本上相当于object它没有提供太多(如果有的话)好处。

从讨论来看:

其原因是资源类型与 PHP 没有对象的时代不合时宜,但仍需要使某些类型的数据变得不透明。资源类型是一种仅用于在内部函数之间调整 C 指针的类型。它没有语义价值。因为资源现在是多余的,考虑到对象的存在,它们的时间已经耗尽,并且它们将在某个时候被替换。为资源添加类型声明意味着如果我们用对象替换任何现有的资源使用,使用它的代码将会中断,从而阻止从资源迁移

安德里亚·福尔兹

长期计划是进行类似于 GMP 经历的过渡:它从 PHP 5.6 开始使用 GMP 对象,并使用之前的资源。

...

除了 Andrea 所说的(资源类型提示会导致问题,我们应该选择迁移到对象)之外,我还认为资源类型提示本身提供的价值相对较小。它仅表示您正在接受某些资源。不过,资源很多。这是文件句柄吗?是数据库连接吗?它是流式哈希上下文吗?它没有告诉。

尼基塔·波波夫