PHP学习心得:如何编写可扩展的模块

介绍

在 PHP 中,模块是可扩展性的核心。一个模块可以增强或者修改 PHP 的行为,并将其编译为静态或者动态共享库。本文将介绍如何编写可扩展的模块,以及一些技巧来确保模块的稳定性和高效性。

1. 编写模块

模块结构

一个典型的 PHP 模块通常包括以下文件:

- php_xxx.h:定义模块的数据结构和函数原型声明。

- xxx.c:实现模块的功能代码。

- config.m4:关于模块编译的 Makefile 和配置文件。

下面是一个简单的例子。

// 文件:php_hello.h

#ifndef PHP_HELLO_H

#define PHP_HELLO_H

extern zend_module_entry hello_module_entry;

#define phpext_hello_ptr &hello_module_entry

#define PHP_HELLO_VERSION "1.0.0"

#ifdef PHP_WIN32

#

define PHP_HELLO_API __declspec(dllexport)

#elif defined(__GNUC__) && __GNUC__ >= 4

#

define PHP_HELLO_API __attribute__ ((visibility("default")))

#else

#

define PHP_HELLO_API

#endif

#ifdef ZTS

#include "TSRM.h"

#endif

PHP_MINIT_FUNCTION(hello);

PHP_MSHUTDOWN_FUNCTION(hello);

PHP_RINIT_FUNCTION(hello);

PHP_RSHUTDOWN_FUNCTION(hello);

PHP_MINFO_FUNCTION(hello);

PHP_FUNCTION(hello_world);

#endif /* PHP_HELLO_H */

模块初始化

当编译完 PHP 模块后,需要将其加载到 PHP 运行时,以便 PHP 可以找到并使用这个模块。

在 PHP 模块加载时,会自动调用模块中的一个叫做 MINIT 的函数。这个函数会注册模块的函数和类。我们在这个函数中注册模块中的函数。

// 文件:hello.c

#include "php_hello.h"

static const zend_function_entry hello_functions[] = {

PHP_FE(hello_world, NULL)

PHP_FE_END

};

zend_module_entry hello_module_entry = {

STANDARD_MODULE_HEADER,

"hello",

hello_functions,

PHP_MINIT(hello),

PHP_MSHUTDOWN(hello),

PHP_RINIT(hello),

PHP_RSHUTDOWN(hello),

PHP_MINFO(hello),

PHP_HELLO_VERSION,

STANDARD_MODULE_PROPERTIES

};

ZEND_GET_MODULE(hello);

PHP_FUNCTION(hello_world)

{

RETURN_STRING("Hello World", 1);

}

PHP_MINIT_FUNCTION(hello)

{

return SUCCESS;

}

PHP_MSHUTDOWN_FUNCTION(hello)

{

return SUCCESS;

}

PHP_RINIT_FUNCTION(hello)

{

return SUCCESS;

}

PHP_RSHUTDOWN_FUNCTION(hello)

{

return SUCCESS;

}

PHP_MINFO_FUNCTION(hello)

{

php_info_print_table_start();

php_info_print_table_header(2, "hello support", "enabled");

php_info_print_table_end();

}

现在,我们需要将模块编译为动态共享库,可以使用 phpize 工具,生成 Makefile。

$ phpize

$ ./configure --enable-hello

$ make

检查是否生成了 hello.so 动态共享库。

$ ls modules/

hello.so

2. 扩展 PHP

在 PHP 中,C 语言扩展提供了几种添加功能的方法。

添加 PHP 函数

上面的例子中,通过 PHP_FUNCTION 宏定义了一个 "hello_world" 函数。这个函数可以在 PHP 中使用。

添加 PHP 类

一个 C 扩展可以向 PHP 中添加一个类,就像在 PHP 中定义类一样。在 C 扩展中添加的类与通过 PHP 实现的类相同,可以用来创建对象,调用方法,获取属性等。

修改 PHP 内核

C 扩展可以访问和修改 PHP 内核。PHP 提供了许多 API,可以让开发人员访问 PHP 内核中的各个部分,例如,zval 值,哈希表以及其他内部数据结构。

3. 扩展 Laravel

Laravel 是一个流行的 PHP Web 框架。Laravel 框架是开源的,越来越多的人将其作为 Web 开发的首选框架。在 Laravel 中,可以通过编写扩展来添加额外的功能。

有两种 Laravel 扩展类型:服务提供者和扩展包。

服务提供者

服务提供者是 Laravel 5 的核心组件之一。可以通过编写自定义服务提供者来扩展 Laravel 的功能。

服务提供者的主要目的是注册绑定到 Laravel 依赖注入器中的绑定,如:

namespace App\Providers;

use Illuminate\Support\ServiceProvider;

class HelloServiceProvider extends ServiceProvider

{

public function register()

{

$this->app->bind('hello', function () {

return new \App\Services\HelloService();

});

}

}

扩展包

Laravel 扩展包是具有独立功能的单元,可以轻松地添加到 Laravel 项目中。

可以选择创建一个全新的 Laravel 扩展包,或者通过 composer 依赖项来管理已存在的 Laravel 扩展包。

下面是一个例子,展示了如何创建一个 Laravel 扩展包。

首先,使用 composer 创建一个新的项目:

$ composer create-project --prefer-dist laravel/laravel acme

$ cd acme/

接着,使用 Artisan 命令行工具来创建 Laravel 扩展包:

$ php artisan make:package acme/hello

生成了一个名为 hello 的包。在 packages/acme/hello 目录下新建了一个 ServiceProvider 类。

namespace Acme\Hello;

use Illuminate\Support\ServiceProvider;

class HelloServiceProvider extends ServiceProvider

{

public function register()

{

$this->app->bind('hello', function () {

return new Hello();

});

}

}

现在,只需将这个 ServiceProvider 放入主项目,然后添加

'providers' => [

// ...

Acme\Hello\HelloServiceProvider::class,

]

到主项目的 config/app.php 文件中即可。

总结

本文介绍了如何编写可扩展的 PHP 模块,使用 PHP 扩展来扩展 PHP 的各个方面,以及如何在 Laravel 框架中使用服务提供者和扩展包。编写可扩展的代码可以使您的代码更加灵活,易于维护并具有更高的可重用性。

后端开发标签