This article is based on PHP7.4 and explains how to create a PHP extension from scratch. This article will explain the basic steps to create an extension. In the example, we will implement the following functionality.

 1 2 3  

Output content:

 1 2 3  // $php74 ./hello.php$ hello word 

Implement a hello method in the extension to output hello word! after calling the hello method.

## Generating the extension archetype

First we need to have a copy of php-src.

 1 2 3 4 5  git clone https://github.com/php/php-src.git cd php-src git checkout PHP-7.4.5 cd php-7.4.10/ext ls 

You can see that there is an ext_skel.php file.

 1 2 3  bcmath com_dotnet date enchant ffi ftp gmp imap ldap mysqli odbc pcntl pdo_dblib pdo_oci pdo_sqlite posix reflection simplexml soap spl sysvmsg tidy xmlreader xsl zlib bz2 ctype dba exif fileinfo gd hash intl libxml mysqlnd opcache pcre pdo_firebird pdo_odbc pgsql pspell session skeleton sockets sqlite3 sysvsem tokenizer xmlrpc zend_test calendar curl dom ext_skel.php filter gettext iconv json mbstring oci8 openssl pdo pdo_mysql pdo_pgsql phar readline shmop snmp sodium standard sysvshm xml xmlwriter zip 

This file is already distributed with php, so we can customize it very easily.

  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18  php ext_skel.php --ext hello --author aoppp --std Copying config scripts... done Copying sources... done Copying tests... done Success. The extension is now ready to be compiled. To do so, use the following steps: cd /path/to/php-src/hello phpize ./configure make Don't forget to run tests once the compilation is done: make test Thank you for using PHP! 

The hello directory is created in the ext directory.

## Extended Archetype Description

 1 2 3 4 5 6 7  -rw-r--r-- 1 longshilin staff 405 Feb 27 16:07 .gitignore -rw-r--r-- 1 longshilin staff 11 Feb 27 16:07 CREDITS -rw-r--r-- 1 longshilin staff 3231 Feb 27 16:07 config.m4 -rw-r--r-- 1 longshilin staff 204 Feb 27 16:07 config.w32 -rw-r--r-- 1 longshilin staff 3355 Feb 27 16:07 hello.c -rw-r--r-- 1 longshilin staff 1425 Feb 27 16:07 php_hello.h drwxr-xr-x 5 longshilin staff 160 Feb 27 16:07 tests 
• config.m4 configuration file

The extended config.m4 file tells the UNIX build system which extension configure options are supported, which extension libraries you need, and which source files to compile as part of it. For all frequently used autoconf macros, including PHP specific and autoconf built-in ones.

The purpose of config.m4 is to generate configure files in conjunction with the phpize utility. The configure file is used for environment testing. It checks if the environment required for the extension to compile and run is met. Now let’s start modifying the config.m4 file.

where dnl is a comment symbol.

The above code says that if you write an extension that depends on other extensions or lib libraries, you need to uncomment the PHP_ARG_WITH related code. Otherwise, remove the comments from the PHP_ARG_ENABLE related code snippet. We write extensions that do not depend on other extensions and lib libraries. Therefore, we remove the comment before PHP_ARG_ENABLE.

The above image is generated with the specification that it does not depend on other extensions.

• php_hello.h header file Similar to the C header file, it contains some custom structures and function declarations, which need not be changed in this demo for now.

• hello.c code file

The real logic code is in this file.

## Write the code

hello.c is all logic code inside, so we just add code to operate in this file.

### Understanding the extension entry

The entry point for the entire extension is the zend_module_entry structure, the specific definition can be seen in the zend_modules.h file in the Zend directory, there are a dozen attributes, quick skip, we only need hello for now.

  1 2 3 4 5 6 7 8 9 10 11 12  zend_module_entry hello_module_entry = { STANDARD_MODULE_HEADER, "hello", /* Extension name */ hello_functions, /* zend_function_entry */ NULL, /* PHP_MINIT - Module initialization */ NULL, /* PHP_MSHUTDOWN - Module shutdown */ PHP_RINIT(hello), /* PHP_RINIT - Request initialization */ NULL, /* PHP_RSHUTDOWN - Request shutdown */ PHP_MINFO(hello), /* PHP_MINFO - Module info */ PHP_HELLO_VERSION, /* Version */ STANDARD_MODULE_PROPERTIES }; 

Extension-related properties description:

• STANDARD_MODULE_HEADER helps us to implement the first 6 properties
• hello is the name of the extension
• hello_functions is the set of all methods contained in the extension, followed by 5 macros for each of the 5 extension-specific methods
• PHP_HELLO_VERSION is the version number of the extension, defined in the header file, so if you need to change it, just open php_hello.h and find define PHP_LZPAY_VERSION.
• STANDARD_MODULE_PROPERTIES does the rest of the properties for us

In the hello_functions[] method array there are already 2 example methods hello_test1 and hello_test2, we refer to them to write our methods, first we write a test method and put it after the function PHP_FUNCTION(hello_test2).

 1 2 3 4 5 6 7  /*新增函数*/ PHP_FUNCTION(hello) { zend_string *strg; strg = strpprintf(0, "hello word"); RETURN_STR(strg); } 

Then add our newly written functions to the hello_functions[] array.

## Compile and install

Since I have a new standalone installation of php7.4, I’m basically operating with absolute paths. If you have one environment, then just do it directly.

  1 2 3 4 5 6 7 8 9 10  cd hello/ /usr/local/Cellar/php/7.4.0/bin/phpize ./configure --with-php-config=/usr/local/Cellar/php/7.4.0/bin/php-config make && make install ---------------------------------------------------------------------------- Build complete. Don't forget to run 'make test'. Installing shared extensions: /usr/local/Cellar/php/7.4.0/pecl/20190902/ 

Once installed, let’s configure the extension.

• ext-hello.ini
 1 2  [hello] extension="/usr/local/Cellar/php/7.4.0/pecl/20190902/hello.so" 

## Testing

 1 2 3  hello git:(PHP-7.4.5) \$ /usr/local/Cellar/php/7.4.0/bin/php -m | grep hello # 输出成功说明ok hello