Hello everyone,
I'm very excited to test out creating my own extension. The idea is something like the Phalcon extension or Ice extension: A web framework delivered as a PHP extension.
I came across some prebuilt solutions C that offers HTTP handling, routing, and template rendering. Now, these functions by default these frameworks have their own web server, which are fragmented into different components (router has it own .h file).
But now an interesting question came into my mind: What if the PHP extension converts PHP into the actual Web Server (instead of passing through PHP-FPM). It would make PHP look more like a Ruby or Python program though . . .
But doing so seems like just programming a raw web server, with PHP as the controlling configuration language. Which it itself, personally considering PHP as a "C" languages, is not a big problem for me.
So I have the following question regarding the 2 approaches:
Option 1: PHP extension as a Web Framework
- How can I access Global Variables from a C extension (_SERVER, _GET, _POST)? I know that there is a
zend_is_auto_global(zend_string *name)function to check if a given ZSTR_VAL correspond to a given Global variable name. But, how can I retrieve it value as an array? What is the function to do so?
Option 2: PHP extension as a Web Server(Embedded C Server inside PHP)
- The simplest way to implement a MVP would be to embed the C server inside the PHP extension. There are 2 ways of doing so:
- Server initialization function would start at MINIT(), and server shutdown at MSHUTDOWN(), while router and controllers definition would be placed maybe at RINIT, or after, and their destruction at RSHUTDOWN.
- Everything at RINIT of just after, right before RSHUTDOWN.
What would be the drawbacks of each of these method (considering from a general perspective). I assume that it really depends on the framework, but what do you consider things I should take care about in the case I want to continue in that road
-
I understand that PHP lifecycle goes something like MINIT() -> RINIT() -> YOUR_CODE() -> RSHUTDOWN -> MSHUTDOWN. But reading the PHP Lifecycle from PHP Internals Book https://www.phpinternalsbook.com/php7/extensions_design/php_lifecycle.html. I got some doubts: in a PHP-CLI, do you have a single instance of the lifecycle, or a bunch of those per requests? The book says that PHP-CLI uses a process-based model for parallelism. Is it enabled by default? In the case I use an NGINX server as a reverse proxy for the PHP code, and I run PHP as continuously running through a service/task manager (i.e creating a systemd entry for PHP to run in the background), will the process-based parallelism model work by default?
-
Is there a problem that a NTS PHP invokes a C class that handles threads? Or is it recommendable to build the PHP version as ZTS (Which, based on some diagram I saw, makes more sense. But I read that it is discouraged as it is a very hard work to maintain).
Thanks for you reading and consideration,
David Maye.
- I understand that PHP lifecycle goes something like MINIT() -> RINIT() -> YOUR_CODE() -> RSHUTDOWN -> MSHUTDOWN. But reading the PHP Lifecycle from PHP Internals Book https://www.phpinternalsbook.com/php7/extensions_design/php_lifecycle.html. I got some doubts: in a PHP-CLI, do you have a single instance of the lifecycle, or a bunch of those per requests? The book says that PHP-CLI uses a process-based model for parallelism. Is it enabled by default?
I think "process-based model for parallelism" here basically means "any parallelism is somebody else's problem": if you run a PHP script on the command-line, PHP just runs that script in its own process, it doesn't know or care what other processes are running at the same time.
In the case I use an NGINX server as a reverse proxy for the PHP code, and I run PHP as continuously running through a service/task manager (i.e creating a systemd entry for PHP to run in the background), will the process-based parallelism model work by default?
"Continuously running" in this case really just means "if the process exits, run it again". PHP doesn't know that's going to happen, and is still running the same code as if you ran it manually.
You could set it up to run two copies, or 100; or run the same script through multiple copies of PHP (e.g. in a CI environment); each script will still just be doing its thing.
- Is there a problem that a NTS PHP invokes a C class that handles threads? Or is it recommendable to build the PHP version as ZTS (Which, based on some diagram I saw, makes more sense. But I read that it is discouraged as it is a very hard work to maintain).
If the aim is ultimately to run the user's PHP code in a separate thread for each request, you're going to need ZTS - otherwise code in one thread will affect or even crash code in another.
A common alternative is to use asynchronous request handling rather than parallel request handling: a single thread switches context while waiting for things like I/O. For that, you don't need any thread safety, because requests are all in one thread.
I hope that helps,
Rowan Tommins
[IMSoP]