首页 > 解决方案 > 为什么 PHP CLI 被认为是一种 SAPI?

问题描述

根据维基百科的定义:

换句话说,SAPI实际上是Web服务器提供的一个应用程序编程接口(API),用来帮助其他开发者扩展Web服务器的能力。

不同类型的 SAPI 存在于各种 Web 服务器扩展中。例如,除了上面列出的那些之外,PHP 语言的其他 SAPI 包括通用网关接口 (CGI) 和命令行接口 (CLI)。

但是,我认为当通过终端(命令行)运行 php 文件或php-cli interactive shell仅使用 zend 引擎来解释代码时。

有什么我错了或不知道的吗?

可能是因为通过 Web 服务器与客户端交互吗?



编辑:除了接受的答案之外,进一步解释以更好地理解该主题:

George Schlossnagle 的高级PHP 编程

在此处输入图像描述

PHP 与其他应用程序交互的最外层是服务器抽象 API (SAPI) 层。SAPI 层部分处理应用程序内 PHP 的启动和关闭,并提供挂钩以与应用程序无关的方式处理 cookie 和 POST 数据等数据。

在 SAPI 层之下是 PHP 引擎本身。核心 PHP 代码处理设置运行环境(填充全局变量和设置默认 .ini 选项),提供接口,例如流的 I/O 接口,解析数据,最重要的是,提供用于加载扩展的接口(都是静态的)编译的扩展和动态加载的扩展)。

PHP 的核心是 Zend 引擎,我们已经在这里深入讨论过。正如您所见,Zend 引擎完全处理脚本的解析和执行。Zend 引擎还为可扩展性而设计,允许完全覆盖其基本功能(编译、执行和错误处理),覆盖其行为的选择性部分(覆盖特定操作中的 op_handlers),以及在可注册的钩子上调用函数(在每个函数调用,在每个操作码上,等等)。这些功能允许轻松集成缓存、分析器、调试器和语义更改扩展。

SAPI 层

SAPI 层是允许将 PHP 轻松嵌入到其他应用程序中的抽象层。一些 SAPI 包括以下内容:

这个想法是,无论应用程序如何,PHP 都需要在许多常见的地方与应用程序进行通信,因此 SAPI 接口为每个地方提供了一个挂钩。例如,当应用程序需要启动 PHP 时,它会调用启动钩子。相反,当 PHP 想要输出信息时,它使用提供的 ub_write 钩子,SAPI 层的作者已经对其进行了编码,以便为 PHP 正在运行的应用程序使用正确的输出方法。

阅读更多

标签: php

解决方案


“为什么”总是一个狡猾的,有点哲学的问题。最终,“为什么 CLI 被视为 SAPI”的答案是“因为这就是开发人员定义它的方式”。如果他们称其为“CLI 模式”,您还会问“为什么”吗?

但是您确实提出了一个更具体的问题,可以解释为:

在 CLI 上运行程序时,为什么需要 SAPI 和 Zend 引擎?

或者更简洁:

CLI SAPI 有什么作用?

Zend 引擎自己接受一系列指令,并执行它们。它可以管理变量、算术、函数定义和调用、类定义等。但是,如果您无法从程序中获得任何输出,那么这些都不是很有用;最常见的情况是,您还想提供一些可变输入。

某些形式的输入和输出仅基于您正在运行的操作系统,而不是 SAPI——基于绝对路径读取或写入文件,或通过网络连接访问某些内容。理论上你可以有一个只允许访问这些的运行模式,但它会感觉非常有限。(这仍然是一个“SAPI”吗?绝对是一个哲学问题。)

考虑一些常见的事情echo:Zend 引擎可以直接管理的“输出”没有绝对定义。在 Web 服务器上下文中,您希望echo将一些输出添加到服务器将发送给客户端的 HTTP 响应中;在命令行上下文中,您希望它在运行命令的控制台中显示输出,或者如果您运行类似php foo.php | grep error.

CLI SAPI 没有提供与 Web 服务器 SAPI 相同的所有功能,但它在将运行在 Zend 引擎中的程序与外部世界连接时扮演了类似的角色。以下是它需要做的一些事情:

  • 将输出附加到父控制台或“标准输出”流
  • 使“标准输入”和“标准错误”流可用
  • 填充$argv$argc基于调用脚本的参数
  • 填充$_ENV进程继承的环境变量
  • 为“当前工作目录”定义一个初始值以用于相对文件路径

推荐阅读