3

我正在将我的项目从 PHP 7.0 更新到 PHP 8.0,但我无法确定是否允许将其明确指定resource数据类型:

  • 一个类属性
  • 方法/函数参数的,
  • 由方法/函数返回

我现在所知道的是:

  • resource是构建混合类型的类型之一,
  • 一些内部函数,如fopen,正在返回 type 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;
    }
}
4

1 回答 1

4

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

这是2015 年提出的RFC ,这是带有实现的PR ,这是关于它的讨论线程。

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

从讨论中:

原因是资源类型与 PHP 没有对象的时代已经过时了,但仍需要使某些类型的数据不透明。资源类型是一种仅存在于内部函数之间围绕 C 指针进行混洗的类型。它没有语义价值。因为资源现在是冗余的,考虑到对象的存在,它们的时间已经不多了,它们将在某个时候被替换。为资源添加类型声明意味着如果我们用对象替换任何现有的资源使用情况,使用它的代码将中断,从而防止从资源迁移

安德里亚·福尔兹

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

...

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

尼基塔波波夫

于 2021-03-30T13:17:57.387 回答