Php-x is a new project I created in early 2017. The goal of this project is to make PHP applications with some experience scalable.

0 x00 purpose

Swoole is now five years old, having started writing it in 2012. I found writing a PHP extension very difficult. There is not one PHP programmer in the PHP community, or even one in 100, who can write PHP extensions. PHP officials are very unfriendly to extension developers, and the Zend API provided in the source code is extremely difficult to use. The API is complex and cluttered, full of macros. The Zend API is so full of potholes that the average developer can easily step into them. All kinds of inexplicable core dump problems. The Zend API is barely documented, and it takes a lot of learning time for developers to really master this skill.

So this year I came up with an idea. Based on my experience writing swoole extensions for over five years, I tried to create a wrapper between the Zend API and C++ to make PHP extensions easy to develop. PHPer with some C++ background can easily develop a PHP extension.

The phP-X project was born, and it took only a month to develop. It is so efficient that even a PHP programmer in my company who has only been working for 3 years can make an extension. Subsequently, several projects in the company were quickly validated. Fixed a lot of crashes and memory leaks in 3 days. At present, the stability, performance and robustness have reached the industrial level.

0 x01 start

Php-x itself is based on C++11 and is compiled and configured using cmake. First, you need to make sure that all dependencies are installed. Include:

  • Gcc-4.8 or later
  • Php-7.0 or later, requiredphp7-devpackage
  • Cmake -2.8 or later

Then install PHP-x.



git clone https://github.com/swoole/PHP-X.git
cd PHP-X
cmake .
make -j 4
sudo make installCopy the code

Without any compile errors, libphx. so will be successfully compiled and installed in the system’s lib directory. The header file is copied to the include directory on the system. Run sudo ldconfig to refresh the so file cache.

0x02 Creating a Project

Using any development tool, create a new test.cc source file. First we need to import the phpx.h header file. We then use using to introduce the PHPX namespace. PHP officially doesn’t use C++, so PHPX uses PHP as its namespace directly.



#include <phpx.h>
using namespace std;
using namespace php;Copy the code

The extension is created using the PHPX_EXTENSION macro. In this macro, you just need new Extension to create the Extension. The constructor takes two arguments, the first the name of the extension and the second the version number of the extension. Return the pointer to the extension object in the PHPX_EXTENSION macro.



PHPX_EXTENSION() {Extension *ext = new Extension("test", "0.0.1"); return ext; }Copy the code

You must use New Extension instead of creating objects directly on the stack

0x03 Add function

The main purpose of a PHP extension is to provide extension functions that, because they are implemented in C/C++ code, can perform tens or even hundreds of times better than PHP user functions. Implementing functions in PHPX is very simple. Use PHPX_FUNCTION to realize the Extension function, and then call the Extension: : registerFunction to register the Extension function.

PHPX_FN is a helper macro that is actually expanded as “cpp_hello_world”. When expanded, PHPX_FUNCTION contains two variables, the first being the args parameter, The second is the return value retval. The input and output of the function can be realized by manipulating the two variables args and retval

Our code here is very simple, cpp_test($STR, $n). Calling this function returns an array of $n $STR.



#include <phpx.h> using namespace std; using namespace php; // Declare the function PHPX_FUNCTION(cpp_test); PHPX_EXTENSION() {Extension *ext = new Extension("test", "0.0.1"); ext->registerFunction(PHPX_FN(cpp_test)); return ext; } // implement the function PHPX_FUNCTION(cpp_test) {//args[1] is the second argument to the extension function long n = args[1].toint (); // initialize the return value retval to Array array_array (retval); for(int i = 0; i < n; Append (args[0]) {//args[0] is the first argument to this extension function. // Append (args[0]); }}Copy the code

0x04 Compile the extension

Write a Makefile. As follows:



PHP_INCLUDE = `php-config --includes`
PHP_LIBS = `php-config --libs`
PHP_LDFLAGS = `php-config --ldflags`
PHP_INCLUDE_DIR = `php-config --include-dir`
PHP_EXTENSION_DIR = `php-config --extension-dir`

test.so: test.cc
    c++ -DHAVE_CONFIG_H -g -o test.so -O0 -fPIC -shared test.cc -std=c++11 ${PHP_INCLUDE} -I${PHP_INCLUDE_DIR} -lphpx
    
install: test.so
    cp test.so ${PHP_EXTENSION_DIR}/
clean:
    rm *.soCopy the code

Php-config is a tool that comes with PHP. You can use php-config to get PHP installation paths, header directories, extension directories, other extra build parameters, and so on.

This Makefile supports three instructions: make compile, make clean clean, and make install to the extension directory.

Sudo make install is used to copy the installation directly from the web page. Tabs may be replaced with Spaces. Edit the Makefile manually using TAB indentation. MacOS needs to add -undefined dynamic_lookup to the c++ compilation parameter

Once you’ve written it, execute make Install to compile the extension and install the test.so extension into your PHP extension directory. Add extension=test.so to load the extension.

Use phP-m to see if your extension loads properly.



php -m
[PHP Modules]
Core
ctype
curl
date
dom
fileinfo
filter
gd
hash
iconv
inotify
json
libxml
mbstring
mcrypt
memcached
mongodb
mysqli
mysqlnd
openssl
pcntl
pcre
PDO
pdo_mysql
pdo_sqlite
Phar
posix
redis
Reflection
session
SimpleXML
sockets
SPL
sqlite3
standard
swoole
test
tokenizer
xml
xmlreader
xmlwriter
yac
zlib
zmq

[Zend Modules]Copy the code

Seeing test here indicates that your extension has loaded successfully, and you can now call the cpp_test extension function.

0 x05 perform

Write a test.php file with the following contents:



<? php var_dump(cpp_test("hello", 3));Copy the code

Perform the test. The PHP:



php test.php
array(3) {
  [0]=>
  string(5) "hello"
  [1]=>
  string(5) "hello"
  [2]=>
  string(5) "hello"
}Copy the code

You can see that the execution results are as expected. Congratulations, you have now successfully developed a PHP extension. Isn’t that easy?

0 x06 more

The above example is relatively simple, just writing an extension function. You still have a lot of work to do before you can actually use PHP-X in a real project.

  • Need to beC++The foundation of basic skills
  • To learn morePHP-XtheAPI

In addition, with the use of Eclipse and other IDE tools, can achieve API automatic prompts and complement, the development will be more convenient.

Php-x is much easier to use than the Zend API, so it won’t take you too long to get the hang of it. I’ll write more tutorials in the coming days on how to use PHP-X to implement more complex functions such as extension classes, resources, callback functions, and more.