PHP 伪协议(流包装器)使用指南


PHP 伪协议,在 PHP 官方文档中被更精确地定义为“流包装器(Stream Wrappers)”,是 PHP 语言中一项核心且强大的功能。它们提供了一种统一的抽象层,使得 PHP 的文件系统函数(如 fopen()file_get_contents()include() 等)能够以一致的方式与各种数据源进行交互 。这些数据源不仅限于本地文件,还包括远程 URL、内存中的数据、压缩文件内部的内容,甚至是标准输入/输出流 。

流包装器通过 scheme:// 的 URL 风格语法来指定,例如 file:// 用于访问本地文件系统,http:// 用于发起 HTTP 请求,而 php:// 则提供了对 PHP 内部 I/O 流的访问 。PHP 内置了多种流包装器,极大地增强了其在数据处理方面的灵活性。此外,PHP 还允许开发者通过 stream_wrapper_register() 函数注册自定义的流包装器,进一步扩展了其功能 。

流包装器的核心价值在于其提供了一种统一的数据访问接口,显著简化了 PHP 应用程序处理异构数据源的复杂性。开发者无需针对不同类型的数据源编写独立的逻辑,只需通过相应的流包装器即可实现数据的读取或写入,从而有效提高了开发效率和代码的可维护性 。

PHP 伪协议(流包装器)详解

file://:本地文件系统访问

file:// 是 PHP 默认的本地文件系统访问包装器,在文件路径中通常可以被隐式省略。它允许 PHP 函数直接读取、写入、创建或操作服务器上的本地文件 。

功能与用例:
file:// 用于访问服务器上的本地文件系统。例如,可以使用 file_get_contents() 函数读取文件的全部内容到字符串变量中 。fopen() 函数结合循环可以逐行读取文件 。

实战举例:

  • 读取文件内容:
    <?php
    $fileContents = file_get_contents('file.txt');
    echo $fileContents;
    ?>
    

此代码将 file.txt 的所有内容作为字符串返回 。

  • 逐行读取文件:
    <?php
    if (file_exists('file.txt')) {
        $file = fopen('file.txt', 'r');
        while (($line = fgets($file))!== false) {
            echo $line. '<br>';
        }
        fclose($file);
    } else {
        echo 'File does not exist';
    }
    ?>
    

此代码检查文件是否存在,以读取模式 ('r') 打开文件,使用 `fgets` 逐行读取,然后关闭文件 。

  • 创建新文件:
    <?php
    if (!file_exists('log.txt')) {
        $file = fopen("log.txt", "w");
        fclose($file);
    } else {
        echo 'File exists already';
    }
    ?>
    

此代码检查文件是否存在,如果不存在则以写入模式 ('w') 创建 `log.txt` 文件 。

  • 写入文件:
    <?php
    if (file_exists('log.txt')) {
        $file = fopen("log.txt", "w");
        fwrite($file, "This is a new log entry.\n");
        fclose($file);
    } else {
        echo 'File does not exist.';
    }
    ?>
    

此代码以写入模式打开 log.txt 并写入内容,会覆盖原有内容 。

  • 追加内容到文件:
    <?php
    if (file_exists('log.txt')) {
        $file = fopen("log.txt", "a");
        fwrite($file, "This is an appended log entry.\n");
        fclose($file);
    } else {
        echo 'File does not exist.';
    }
    ?>
    

此代码以追加模式打开 log.txt,将新内容添加到文件末尾而不覆盖原有内容 。

http://https://:远程 URL 访问

http://https:// 包装器允许 PHP 应用程序发起 HTTP 或 HTTPS 请求,用于获取远程资源 。这在现代 Web 应用中非常普遍,例如调用外部 API、获取远程图片、加载远程脚本或数据等 。

功能与用例:
这些包装器用于通过 HTTP 或 HTTPS 协议从远程服务器获取内容。

实战举例:

  • 获取远程网页内容:
    <?php
    $html = file_get_contents("http://example.com/data.json");
    echo $html;
    ?>
    

此代码将从 http://example.com/data.json 获取的 JSON 数据作为字符串返回 。

php://:I/O 流访问

php:// 包装器提供了一种访问 PHP 各种内部 I/O 流的特殊机制。这些流包括标准输入/输出、内存流和临时文件流,使得 PHP 能够以编程方式处理各种数据输入和输出,而无需实际的文件操作 。

php://filter

php://filter 包装器不直接执行文件,而是用于在数据流通过时应用各种过滤器,对数据进行转换 。最常见的用途是进行编码/解码(如 base64-encodebase64-decode)或压缩等操作 。

功能与用例:
php://filter 用于对数据流进行转换,例如 Base64 编码或解码。它通过 resource 参数指定要过滤的流,并通过 readwrite 参数指定要应用的过滤器 。

实战举例:

  • 读取并转换为大写:
    <?php
    /* 这将把 www.example.com 的内容全部输出为大写 */
    readfile("php://filter/read=string.toupper/resource=http://www.example.com");
    ?>
    

此代码通过 string.toupper 过滤器将 `http://www.example.com` 的内容转换为大写并输出 。

  • 读取并转换为大写后进行 ROT13 编码:
    <?php
    /* 这将执行与上面相同的操作,但还会进行 ROT13 编码 */
    readfile("php://filter/read=string.toupper|string.rot13/resource=http://www.example.com");
    ?>
    

此代码在转换为大写后,再通过 string.rot13 过滤器进行 ROT13 编码 。

  • 写入时进行 ROT13 编码:
    <?php
    /* 这将通过 rot13 过滤器过滤字符串 "Hello World",然后写入当前目录的 example.txt */
    file_put_contents("php://filter/write=string.rot13/resource=example.txt","Hello World");
    ?>
    

此代码在写入 example.txt 之前,将字符串 “Hello World” 通过 `string.rot13` 过滤器进行编码 。

php://input

php://input 允许读取 HTTP 请求体中的原始 POST 数据,而无需依赖 $_POST 超全局变量($_POST 仅处理 application/x-www-form-urlencodedmultipart/form-data 格式的数据)。这对于处理非标准格式的 POST 数据,如 JSON 或 XML 请求体,非常有用 。

功能与用例:
php://input 用于读取 HTTP 请求的原始 POST 数据,特别适用于接收 JSON 或 XML 等非表单数据 。

实战举例:

  • 获取 JSON 格式的 POST 数据:
    <?php
    // 获取 JSON 内容
    $json = file_get_contents('php://input');
    // 解码 JSON 数据
    $data = json_decode($json);
    ?>
    

此代码从请求体中读取原始 JSON 数据并进行解码 。

php://memoryphp://temp

这两个包装器提供对内存或临时文件(当数据量超过一定阈值时,php://temp 会自动将数据写入临时文件)的读写访问 。它们常用于处理不需要持久化存储的临时数据,例如在数据处理管道中作为中间缓冲区 。

功能与用例:
php://memoryphp://temp 用于在内存中或临时文件中存储和处理数据,适用于不需要持久化存储的场景 。

实战举例:

  • 在内存中读写数据:
    <?php
    $temp_stream = fopen('php://memory', 'r+');
    fwrite($temp_stream, "Hello from memory!");
    fseek($temp_stream, 0); // 将指针移回开头
    echo fread($temp_stream, 1024); // 读取数据
    fclose($temp_stream);
    ?>
    

此代码演示了如何在内存流中写入和读取数据。

data://:数据嵌入

data:// 包装器允许将小文件或数据直接以 Base64 编码或 URL 编码的形式嵌入到 URL 字符串中 。这常用于在 HTML 或 CSS 中嵌入图片、字体等小型资源,从而减少 HTTP 请求的数量,提高页面加载效率 。

功能与用例:
data:// 用于将数据直接嵌入到 URL 字符串中,常用于在 HTML 或 CSS 中嵌入小型资源 。

实战举例:

  • 打印嵌入的 Base64 编码数据:
    <?php
    // 打印 "I love PHP"
    echo file_get_contents('data://text/plain;base64,SSBsb3ZlIFBIUAo=');
    ?>
    

此代码将 Base64 编码的字符串 “SSBsb3ZlIFBIUAo=” 解码并打印出 “I love PHP” 。

  • 获取嵌入数据的媒体类型:
    <?php
    $fp = fopen('data://text/plain;base64,', 'r');
    $meta = stream_get_meta_data($fp);
    // 打印 "text/plain"
    echo $meta['mediatype'];
    ?>
    

此代码打开 data:// 流并获取其媒体类型,输出 “text/plain” 。

  • URL 编码的纯文本数据:
    <?php
    $data = 'Günther says: 1+1 is 2, 10%40 is 20.';
    $fp = fopen('data:text/plain,'.urlencode($data), 'rb');
    echo stream_get_contents($fp);
    ?>
    

当传递纯字符串而非 Base64 编码时,需要进行 URL 编码以避免数据丢失 。

zip://:ZIP 归档文件访问

zip:// 包装器允许 PHP 函数直接访问 ZIP 压缩文件内部的特定文件,而无需先将整个归档文件解压到磁盘 。这对于处理压缩文件中的数据非常有用,例如,读取 OpenOffice 文档(本质上是 ZIP 文件)中的 XML 配置文件 。

功能与用例:
zip:// 用于访问 ZIP 压缩文件内部的特定文件,无需解压整个归档文件 。

实战举例:

  • 读取 ZIP 归档文件内的 XML 文件:
    <?php
    $reader = new XMLReader();
    // 访问 ZIP 文件 test.odt 内的 meta.xml 文件
    $reader->open('zip://'. dirname(__FILE__). '/test.odt#meta.xml');
    $odt_meta = array();
    while ($reader->read()) {
        if ($reader->nodeType == XMLREADER::ELEMENT) {
            $elm = $reader->name;
        } else {
            if ($reader->nodeType == XMLREADER::END_ELEMENT && $reader->name == 'office:meta') {
                break;
            }
            if (!trim($reader->value)) {
                continue;
            }
            $odt_meta[$elm] = $reader->value;
        }
    }
    print_r($odt_meta);
    ?>
    

此代码使用 XMLReader 和 `zip://` 协议读取 `test.odt` 压缩包中的 `meta.xml` 文件内容 。

phar://:PHP 归档文件访问

phar:// 包装器用于访问 PHAR (PHP Archive) 文件。PHAR 是一种将完整的 PHP 应用程序或库打包成单个文件的格式,类似于 Java 的 JAR 文件,便于分发和部署 。它允许将多个 PHP 文件、图片、CSS 等资源打包在一起,并通过 phar:// 协议像访问普通文件一样访问其中的内容 。

功能与用例:
phar:// 用于访问 PHAR 归档文件内部的文件,类似于访问普通文件 。

实战举例:

  • 访问 PHAR 归档文件内的文件:
    <?php
    // 包含 PHAR 归档文件中的一个内部文件
    include 'phar://coollibrary.phar/internal/file.php';
    
    // 直接读取 PHAR 归档文件中的图片内容
    header('Content-type: image/jpeg');
    echo file_get_contents('phar:///fullpath/to/coollibrary.phar/images/wow.jpg');
    ?>
    

此代码展示了如何使用 include 和 `file_get_contents` 函数访问 PHAR 归档文件中的 PHP 脚本和图片 。

expect://:交互流处理

expect:// 包装器用于处理交互流,使得 PHP 能够访问进程的标准输入、输出和错误流 。这是一个极其危险的包装器,通常在生产环境中被禁用 。

功能与用例:
expect:// 用于执行系统命令,但由于其高风险性,通常不建议在生产环境中使用 。

实战举例:

  • 执行系统命令:
    <?php
    echo file_get_contents("expect://ls");
    ?>
    

此代码尝试执行 ls 命令并输出结果 。

glob://:路径名模式匹配

glob:// 包装器用于匹配文件路径模式,允许遍历符合特定模式的文件 。

功能与用例:
glob:// 用于查找匹配特定模式的文件路径,例如搜索目录并打印文件名和大小 。

实战举例:

  • 遍历匹配模式的文件:
    <?php
    foreach (glob("glob://*.txt") as $file) {
        echo file_get_contents($file);
    }
    ?>
    

此代码遍历当前目录下所有 .txt 文件并输出其内容 。

ftp://:FTP 访问

ftp:// 包装器用于访问 FTP 服务器,允许 PHP 函数读取和写入 FTP 服务器上的数据 。

功能与用例:
ftp:// 用于从 FTP 服务器读取或写入数据,例如自动从外部 FTP 获取文件 。

实战举例:

  • 从 FTP 服务器读取文件:
    <?php
    // 假设 FTP 服务器地址为 ftp.example.com,用户名为 username,密码为 password
    $ftp = fopen("ftp://username:password@ftp.example.com/file.txt", "r");
    if ($ftp) {
        echo stream_get_contents($ftp);
        fclose($ftp);
    } else {
        echo "Failed to open FTP stream.";
    }
    ?>
    

此代码尝试通过 FTP 协议连接到服务器并读取 file.txt 的内容 。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值