深入理解PHP之源码目录结构与功能说明

深入理解PHP之源码目录结构与功能说明

说明

本文将详细讲解PHP源码目录结构以及其中各个子目录的作用,帮助读者深入理解PHP的内部结构,从而更好地学习和使用PHP。

源码目录结构

PHP源码目录结构主要分为以下几个部分:

  • build:构建PHP的脚本和辅助工具;
  • ext:PHP的扩展库;
  • main:PHP的主要源代码,包括Zend引擎、内部函数和类库等;
  • sapi:PHP的SAPI接口,用于与Web服务器等程序进行交互;
  • TSRM:线程安全相关代码;
  • Zend:Zend引擎的源代码。

以下是具体的目录结构及其功能:

├── build // 构建PHP的脚本和辅助工具
├── ext // PHP的扩展库
│   ├── bcmath
│   ├── ...
│   └── zip
├── main // PHP的主要源代码
│   ├── output.c // PHP输出相关代码,处理echo、print等输出语句
│   ├── php.h // PHP的主要头文件,定义了一些常量和类型等
│   ├── php.ini-development // PHP开发版本的配置文件
│   ├── php.ini-production // PHP生产版本的配置文件
│   ├── php.ini-production.cli // PHP使用命令行运行时生产版本的配置文件
│   ├── php.ini-recommended // 推荐的PHP配置文件
│   ├── php_stdlib.h // PHP标准库头文件
│   ├── SAPI.h // PHP的SAPI接口头文件
│   ├── sapi_server.h // PHP的Web服务器SAPI接口头文件
│   ├── sapi_cli.h // PHP的命令行SAPI接口头文件
│   ├── zend_API.h // Zend引擎的API接口头文件
│   ├── zend_compile.h // Zend编译相关头文件
│   ├── zend_execute.h // Zend执行相关头文件
│   ├── zend_hash.h // Zend哈希表头文件
│   ├── zend_ini.h // Zend配置文件读取头文件
│   ├── zend_language_parser.h // Zend语言解析器头文件
│   ├── zend_mmap.h // Zend内存映射相关头文件
│   └── zend_operators.h // Zend操作符相关头文件
├── sapi // PHP的SAPI接口,用于与Web服务器等程序进行交互
│   ├── apache2handler // Apache2 SAPI接口相关代码
│   ├── cli // 命令行SAPI接口相关代码
│   ├── fpm // PHP FastCGI进程管理器相关代码
│   ├── litespeed // LiteSpeed SAPI接口相关代码
│   ├── phpdbg // PHP调试器SAPI接口相关代码
│   └── embed // PHP嵌入其他程序的SAPI接口相关代码
├── TSRM // 线程安全相关代码
└── Zend // Zend引擎的源代码
    ├── zend_API.c // Zend引擎的API接口代码
    ├── zend_compile.c // Zend编译相关代码
    ├── zend_execute.c // Zend执行相关代码
    ├── zend_hash.c // Zend哈希表相关代码
    ├── zend_ini.c // Zend配置文件读取相关代码
    ├── zend_language_parser.c // Zend语言解析器相关代码
    ├── zend_list.c // Zend列表相关代码
    ├── zend_mmap.c // Zend内存映射相关代码
    ├── zend_operators.c // Zend操作符相关代码
    └── zend_variables.c // Zend变量相关代码

示例-1: 自定义PHP扩展

通过PHP的扩展库,我们可以为PHP添加自定义的功能。下面是一个简单的示例:自定义一个PHP函数,用于计算斐波那契数列:

  1. 首先在ext目录下创建一个新的目录,命名为fibonacci,并创建config.m4文件:
PHP_ARG_ENABLE(fibonacci, whether to enable Fibonacci function,
[ --enable-fibonacci
   Enable Fibonacci support])

if test $PHP_FIBONACCI != "no"; then
  PHP_SUBST(FIBONACCI_SHARED_LIBADD)
  PHP_NEW_EXTENSION(fibonacci, fibonacci.c, $ext_shared)
fi
  1. 创建fibonacci.c文件,写入以下代码:
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "php.h"

PHP_FUNCTION(fibonacci)
{
    long n, i, t1 = 0, t2 = 1, next_term;

    if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &n) == FAILURE) {
        return;
    }

    for (i = 0; i < n; i++) {
        if (i <= 1) {
            next_term = i;
        } else {
            next_term = t1 + t2;
            t1 = t2;
            t2 = next_term;
        }
    }

    RETURN_LONG(next_term);
}

static zend_function_entry fibonacci_functions[] = {
    PHP_FE(fibonacci, NULL)
    {NULL, NULL, NULL}
};

zend_module_entry fibonacci_module_entry = {
    STANDARD_MODULE_HEADER,
    "fibonacci",
    fibonacci_functions,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    "1.0",
    STANDARD_MODULE_PROPERTIES
};

ZEND_GET_MODULE(fibonacci)
  1. 在PHP源码根目录执行以下命令进行编译:
./buildconf
./configure --enable-fibonacci
make
sudo make install
  1. 在PHP中调用该函数:
echo fibonacci(10); // 输出55

示例-2: 自定义PHP SAPI接口

通过PHP的SAPI接口,我们可以自定义PHP与Web服务器等程序的交互方式。下面是一个简单的示例:自定义一个PHP SAPI接口,以HTTP GET方式获取参数并输出Hello, xxx!:

  1. 在sapi目录下创建一个新的目录,命名为custom,并创建Makefile.frag文件:
SAPI =        $(top_builddir)/sapi/custom/php
CC =          gcc
CFLAGS =      -I. -I$(top_srcdir)/Zend -I$(top_srcdir)/main \
              -I$(top_srcdir)/sapi -I$(top_srcdir) \
              $(EXTRA_INCLUDES)
LDFLAGS =     -export-dynamic $(EXTRA_LDFLAGS)
EXTRA_INCLUDES =
EXTRA_LDFLAGS =
OBJS =        custom.o \
              $(top_builddir)/Zend/zend_alloc.o \
              $(top_builddir)/Zend/zend_buildenv.o \
              $(top_builddir)/Zend/zend_builtin_functions.o \
              $(top_builddir)/Zend/zend_execute.o \
              $(top_builddir)/Zend/zend_globals.o \
              $(top_builddir)/Zend/zend_hash.o \
              $(top_builddir)/Zend/zend_indent.o \
              $(top_builddir)/Zend/zend_language_parser.o \
              $(top_builddir)/Zend/zend_list.o \
              $(top_builddir)/Zend/zend_opcode.o \
              $(top_builddir)/Zend/zend_operators.o \
              $(top_builddir)/Zend/zend_ptr_stack.o \
              $(top_builddir)/Zend/zend_stack.o \
              $(top_builddir)/Zend/zend_variables.o \
              $(top_builddir)/main/php_open_temporary_file.o \
              $(top_builddir)/main/php_logos.o

all: $(SAPI)

$(SAPI): $(OBJS)
        $(CC) $(LDFLAGS) -o $@ $(OBJS)

clean:
        rm -f $(SAPI) $(OBJS)
  1. 创建custom.c文件,写入以下代码:
#include "php.h"
#include "SAPI.h"
#include "zend_API.h"

static sapi_module_struct custom_module = {
    "custom",                 // name
    "Custom PHP Module",      // pretty name
    php_uname('s'),           // php.sapi_name
    NULL,                     // startup
    NULL,                     // shutdown
    NULL,                     // activate
    NULL,                     // deactivate
    NULL,                     // message_handler
    NULL,                     // phpinfo
    "1.0",                    // version
    NULL,                     // globals_ctor
    NULL,                     // globals_dtor
    NULL,                     // post_startup
    NULL,                     // child_terminate
    STANDARD_SAPI_MODULE_PROPERTIES
};

static PHP_FUNCTION(hello)
{
    char *name;
    size_t name_len;

    if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &name, &name_len) == FAILURE) {
        return;
    }

    php_printf("Hello, %s!", name);
}

static zend_function_entry custom_functions[] = {
    PHP_FE(hello, NULL)
    {NULL, NULL, NULL}
};

zend_module_entry custom_module_entry = {
    STANDARD_MODULE_HEADER,
    "custom",
    custom_functions,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    "1.0",
    STANDARD_MODULE_PROPERTIES
};

void _custom_module_startup(sapi_module_struct *sapi_module)
{
    sapi_module->php_ini_path_override = NULL;
}

static int custom_module_startup(sapi_module_struct *sapi_module)
{
    _custom_module_startup(sapi_module);
    return zend_startup_module(&custom_module_entry);
}

#ifdef COMPILE_DL_CUSTOM
ZEND_GET_MODULE(custom)
#endif

int main(int argc, char *argv[])
{
    sapi_startup(&custom_module);
    if (php_module_startup(&custom_module, NULL, 0) == FAILURE) {
        return 1;
    }
    php_output_activate(NULL, NULL);
    PHP_EMBED_MAIN_BEGIN();
    php_printf("Content-type: text/html\r\n\r\n");
    zend_execute_scripts(ZEND_REQUIRE, NULL, 1, "hello.php");
    PHP_EMBED_MAIN_END();
    return 0;
}
  1. 在PHP源码根目录执行以下命令进行编译:
cd sapi/custom
make
  1. 在sapi目录创建custom_server.php文件,写入以下代码:
<?php
$request_uri = $_SERVER['REQUEST_URI'];
parse_str(parse_url($request_uri, PHP_URL_QUERY), $params);
$name = $params['name'] ?? 'World';
echo hello($name);
  1. 进入PHP源码目录,执行以下命令启动自定义SAPI服务:
sapi/custom/php -S localhost:8000 -t sapi/custom sapi/custom_server.php
  1. 在浏览器访问http://localhost:8000/?name=PHP,可以看到输出Hello, PHP!。

总结

通过以上两个示例,我们可以了解PHP源码的目录结构和各个子目录的作用,并了解如何利用PHP扩展库和SAPI接口进行自定义开发。同时也可以为读者带来更好的学习和使用PHP的体验。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:深入理解PHP之源码目录结构与功能说明 - Python技术站

(0)
上一篇 2023年5月23日
下一篇 2023年5月23日

相关文章

  • PHP中多维数组的foreach遍历示例

    下面是详细的攻略: 什么是多维数组 多维数组是指数组中包含有其他数组的数组,即数组的元素又是一个数组。 例如:$arr = array( array(‘name’=>’张三’, ‘age’=>20), array(‘name’=>’李四’, ‘age’=>22), array(‘name’=>’王五’, ‘age’=>25…

    PHP 2023年5月27日
    00
  • PHP中的Streams详细介绍

    以下是关于 “PHP中的Streams详细介绍”的完整攻略。 什么是PHP的Streams 在PHP中,Streams是一种用于在不同的数据源之间进行读写的抽象接口。此接口可以应用于文件 I/O、网络 I/O、压缩文件、加密等。PHP的Streams提供了依赖于底层操作系统的基础I/O的一种可移植方式,并为不同类型的流提供统一接口,优化了数据的读写效率。 S…

    PHP 2023年5月26日
    00
  • 微信小程序实现预览图片功能

    下面是“微信小程序实现预览图片功能”的完整攻略: 准备工作 在实现预览图片功能前,需要先准备好以下工作: 在app.json中声明组件 usingComponents 属性:”usingComponents”: {“van-preview”: “../../miniprogram_npm/vant-weapp/dist/preview/index”}。这样在…

    PHP 2023年5月23日
    00
  • php网站来路获取代码(针对搜索引擎)

    下面是详细讲解PHP网站来路获取代码(针对搜索引擎)的完整攻略及示例说明。 1. 什么是“来路”? “来路”指的是用户访问你的网站的来源网站或搜索引擎。通过获取用户的来路信息,可以更好地了解你的网站的流量来源,从而更好地优化你的营销策略。 2. 如何获取来路信息? 获取来路信息的方法有很多种,其中一种比较常用的方法是通过PHP脚本获取来路信息。 首先,需要在…

    PHP 2023年5月24日
    00
  • 微信小程序与php 实现微信支付的简单实例

    下面是详细讲解“微信小程序与php 实现微信支付的简单实例”的完整攻略。 1. 准备工作 在进行微信小程序与php实现微信支付之前,需要先准备一些必要的工作: 注册微信公众号,创建商户号; 配置商户号支付的相关信息,并获取相应的微信支付API密钥; 下载安装开发环境(如:php和微信小程序开发工具); 准备服务器环境。 2. 连接小程序和服务器 微信支付必须…

    PHP 2023年5月23日
    00
  • php面向对象全攻略 (十六) 对象的串行化

    下面是我对“PHP面向对象全攻略(十六)对象的串行化”的完整攻略: 什么是对象的串行化? 对象的串行化是将对象的状态转化为可以存储或传输的格式,在适当的时候可以将其重新还原为原来的状态。具体来说,它包括对象的序列化和反序列化两个过程。在PHP中,对象的串行化可以通过PHP提供的序列化和反序列化函数来实现。 对象的序列化 对象的序列化是将对象的状态表示为可存储…

    PHP 2023年5月26日
    00
  • php实现搜索一维数组元素并删除二维数组对应元素的方法

    实现搜索一维数组元素并删除二维数组对应元素的方法,可以分为以下几个步骤: 定义一个一维数组,存储需要搜索的元素; 定义一个二维数组,存储需要删除对应元素的数组; 使用foreach循环遍历二维数组,对每个子数组使用array_search函数搜索一维数组中是否存在对应元素; 如果存在对应元素,则使用unset函数删除该子数组; 循环结束后,获得删除后的二维数…

    PHP 2023年5月26日
    00
  • php截取中文字符串不乱码的方法

    完整攻略:php截取中文字符串不乱码的方法 在php中,由于中文字符的编码问题,普通的字符串截取方法会导致中文字符乱码。那么,如何才能截取中文字符串又不会乱码呢?以下是一些解决方法。 一、使用mb_substr()函数截取字符串 mb_substr()函数是php内置的截取字符串的函数,它可以适应不同编码的中文字符,不会出现乱码问题。具体用法如下: $str…

    PHP 2023年5月26日
    00
合作推广
合作推广
分享本页
返回顶部