8

I am a PHP developer who just started learning Node.js and I saw this video: https://www.youtube.com/watch?v=_D2w0voFlEk where it is explained that a html file can be given as response to the browser which is fine.

Now, my question:

If I am running Node.js and PHP in the same server and if the user visits my website, the request goes to nodejs script running in my server. Now, can I process the request in NodeJS and then give a PHP file as a response (after processing on server side) instead of .html file

An outline of what I mean is:

Client Request-> NodeJS server->NodeJS script->PHP server->PHP script->Client Response

Its like stacking of 2 servers.

Why I was thinking of this..

I am making a social networking website where I already made most of my code in PHP and now I am working on real time communications where I do video/audio conferencing, text chat, etc. So, I am planning to use WebRTC and Websockets for this and found many websites telling that NodeJS is the best way to go about when taking Real Time communications to consideration.

But, if I have to do it, I have to change all my code from PHP to NodeJS which is not a good option. So, I thought why not run PHP server inside NodeJS server.

Thanks in advance

I did refer this question by the way: Recommendation for integrating nodejs with php application and felt my case is a bit different.

Community
  • 1
  • 1
Vignesh T.V.
  • 1,790
  • 3
  • 27
  • 48

4 Answers4

5

PHP started it's earily life as a CGI. An HTTP Server would execute PHP script by spawning the PHP-CGI similarly to a command line application with all necessary data such as what would become $_GET, $_POST, and $_SERVER vars passed into the spawned CGI process as environmental variables. The CGI execution model had a high performance cost so later PHP implementations used either an embedded library such as Apache's HTTPD mod_php to execute PHP scripts directly in the HTTP server process or the PHP-FCGI SAPI which uses FastCGI protocol to execute PHP scripts outside of the HTTP server process as was originally required for IIS users on Windows. PHP-FCGI and the later and more preferred PHP-FPM SAPI are both standards now in high performance and high demand production HTTP/PHP services and both operate as a local daemon typically handling FCGI requests over IPC via Unix Domain Sockets (or local TCP sockets on windows). In other words, production HTTP services such as IIS, NGINX, and Apache HTTPD (if using mod_fcgi rather than mod_php) will typically execute PHP scripts using a built-in FCGI module/client to send FCGI requests into PHP-FCGI or PHP-FPM, executing the PHP script in a different process than the web server. This is also possible with Node.JS if you use a FCGI module such as node-phpfpm which allows node to make FCGI requests on PHP the same way as other modern high performance HTTP services. This approach allows node to execute PHP scripts as intended in production HTTP/PHP stacks, meaning it doesn't require the use of special daemons or secondary services (other than standard PHP-FCGI or PHP-FPM processes), doesn't require executing PHP in the same process space as the HTTP server, and it doesn't depend on executing long running PHP scripts to access requests over distributed queues or other messaging interfaces. In short it couples Node.JS with PHP on the exact level as NGINX or other "standard" HTTP/PHP services without using workarounds or custom protocols/interfaces. I would argue this to be the most proper as roughly 90% of the entire internet uses PHP over FCGI yet will still allow you to use much loved Node.JS code for other areas of your application.

Another option, such as if your looking for a more stateful PHP solution as opposed to just creating pages, is to use a queue or other messaging platform between Node.JS and a daemonized long running PHP script (examples ZMQ, Redis, AMQ, etc)

Lastly, you can always make requests from Node.JS onto a standard PHP enabled HTTP server somehow over HTTP such as Jose Mato suggested in his answer. This is option does not tie Node.JS and PHP together as the other options would, requires the additional resources and overhead of a second HTTP server on the network, and would require a custom protocol, but could be easier for some since this is how JavaScript has interfaced with PHP for well over a decade.

JSON
  • 1,819
  • 20
  • 27
4

Technically yes, you can, but, if you want to keep both applications I really recommend you create an interface (API) for you PHP app (eg: REST) and use it from NodeJS using the proper methods (eg: GET /profile)

If you just need to call to php server to centralize the authorization/authentication then you can find alternatives like sharing a Redis instance.

Jose Mato
  • 2,709
  • 1
  • 17
  • 18
2

The easiest way to achieve this is to run both Node.js and PHP on the same server, but on different ports. A node.js server can then just do a local HTTP request to the PHP server and do something with the response.

Evert
  • 93,428
  • 18
  • 118
  • 189
  • Easiest may not be the right way to put it. More familiar maybe since virtually every js developer is familiar with sending http requests and processing JSON or XML responses. but the various FCGI modules for nodejs are easy to use (typically around 10 lines for basic use) and a functional understanding of FastCGI can learned by most from around 10 min of reading. FastCGI is actually much easier to understanding OMHO than most JSON and XML based remoting options (although most couldn't be called "hard") – JSON Aug 21 '18 at 22:15
  • That's a surprising opinion – Evert Aug 21 '18 at 22:16
  • Maybe, but CGI and FastCGI are very basic where JSON/XML remoting can vary and has more of a learning curve unless using a framework that your familiar with. – JSON Aug 21 '18 at 22:20
  • Obviously this is an excellent answer in cases where an existing application already has a remoting framework/API in place on the server side (and new solutions that plan to implement such a feature). Nodejs will play very nice with existing SOAP or REST gateways on PHP services as well as similar JSON/XML RPC/RMI type gateways, and in such cases the developers are already likely familiar with calling into the service via JavaScript albiet from the browser. – JSON Aug 22 '18 at 05:30
  • I would go one step further and say that HTTP is the de facto communication protocol for multiple languages. Almost everyone has experience with it, it's almost always there. – Evert Aug 22 '18 at 08:49
1

yeah i know is 2 years older and just in case you want fire up nodejs with php in windows -i did in this way :

1.download PHP 8.1 (8.1.0alpha3) =VS16 x64 Non Thread Safe (2021-Jul-06 17:39:28) from https://windows.php.net/qa/

and unzip it in C:\x\php

2.put inside same location this php.ini more or less like this

engine = On
short_open_tag = Off
precision = 14
output_buffering = 4096
zlib.output_compression = Off
implicit_flush = Off
unserialize_callback_func =
serialize_precision = -1
disable_functions =
disable_classes =
zend.enable_gc = On
zend.exception_ignore_args = On
zend.exception_string_param_max_len = 0
expose_php = On
max_execution_time = 30
max_input_time = 60
memory_limit = 128M
error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT
display_errors = Off

display_startup_errors = Off

log_errors = On

ignore_repeated_errors = Off

ignore_repeated_source = Off

report_memleaks = On

variables_order = "GPCS"

request_order = "GP"
register_argc_argv = Off

auto_globals_jit = On

post_max_size = 8M
auto_prepend_file =
auto_append_file =
default_mimetype = "text/html"
default_charset = "UTF-8"
doc_root =
user_dir =

extension_dir = "c:\x\php\ext"
enable_dl = On

cgi.force_redirect = 1

fastcgi.impersonate = 1

cgi.rfc2616_headers = 1

file_uploads = On

upload_max_filesize = 2M

max_file_uploads = 20

allow_url_fopen = On
allow_url_include = Off
default_socket_timeout = 60

extension=bz2
extension=curl
extension=fileinfo
extension=gd
extension=mysqli
extension=openssl
extension=sqlite3


[CLI Server]
cli_server.color = On


[Pdo_mysql]
pdo_mysql.default_socket=


[mail function]

SMTP = localhost
smtp_port = 25
mail.add_x_header = Off

[ODBC]
odbc.allow_persistent = On
odbc.check_persistent = On
odbc.max_persistent = -1
odbc.max_links = -1
odbc.defaultlrl = 4096
odbc.defaultbinmode = 1

[MySQLi]
mysqli.max_persistent = -1
mysqli.allow_persistent = On
mysqli.max_links = -1
mysqli.default_port = 3306
mysqli.default_socket =
mysqli.default_host =
mysqli.default_user =
mysqli.default_pw =
mysqli.reconnect = Off
[mysqlnd]
mysqlnd.collect_statistics = On
mysqlnd.collect_memory_statistics = Off
[PostgreSQL]
pgsql.allow_persistent = On
pgsql.auto_reset_persistent = Off
pgsql.max_persistent = -1
pgsql.max_links = -1
pgsql.ignore_notice = 0
pgsql.log_notice = 0
bcmath.scale = 0
session.save_handler = files
session.use_strict_mode = 0
session.use_cookies = 1
session.use_only_cookies = 1
session.name = PHPSESSID
session.auto_start = 0
session.cookie_lifetime = 0
session.cookie_path = /
session.cookie_domain =
session.cookie_httponly =
session.cookie_samesite =
session.serialize_handler = php
session.gc_probability = 1
session.gc_divisor = 1000
session.gc_maxlifetime = 1440
session.referer_check =
session.cache_limiter = nocache
session.cache_expire = 180
session.use_trans_sid = 0
session.sid_length = 26
session.trans_sid_tags = "a=href,area=href,frame=src,form="
session.sid_bits_per_character = 5
zend.assertions = -1
tidy.clean_output = Off
soap.wsdl_cache_enabled=1
soap.wsdl_cache_dir="/tmp"
soap.wsdl_cache_ttl=86400
soap.wsdl_cache_limit = 5
ldap.max_links = -1

(i delete some stuff from it to be able to publish it here)

3.assuming on C:\n\ you have unzipped Windows Binary (.zip) got it from here https://nodejs.org/en/download/ and on your desktop you make a folder ..let say APP and inside you have runme.bat ,index.js ,favicon.ico and index.php :


runme.bat

c:\n\node.exe %CD%\index.js
pause

index.js

/*
these are codes from w3school and stackoverflow 
'cause am not even beginer in node.js (but i am fluent in JavaScript and others
,also i am programming since 1992 , almost 100 000 houres of programming in several languages)
*/
const http = require('http');
const url = require('url');
var fs = require('fs');
serialize = function(obj) {
var str = [];
for (var p in obj)
    
    str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
    return str.join("&");
}

http.createServer(function (req, res) {
    res.writeHead(200, {'Content-Type': 'text/html'});

        if (req.url === '/favicon.ico') {
        fs.readFile(__dirname + req.url, function (err,data) {
            if (err) {
                res.writeHead(404);
                res.end(JSON.stringify(err));
                return;
            }
            res.writeHead(200);
            res.end(data);
        });
        }

    const queryObject = url.parse(req.url,true).query;
    //console.log(`server 3 `  , queryObject);
    process.env.QUERY_STRING=serialize(queryObject);

    pathf=req.url.match('^[^?]*')[0].split('/').slice(1);
console.log(pathf);
const { exec } = require('child_process');
exec(`c:\\x\\php\\php-cgi.exe -c c:\\x\\php\\  %cd%\\index.php`, (err, stdout, stderr) => {
  if (err) {
    console.error(err);
    return;
  }stdout
 res.end(stdout);
});

}).listen(80); 

index.php

<?php
phpinfo();
//var_dump(get_defined_vars());
?>

so after you run runme.bat and in browser you have http://localhost/index.php?stack=overflow&its=cool&and=fun

you will be able to run php 8.1 alpha 3 from nodejs .. how you see inside index.js you have QUERY_STRING prepared for php and maybe others env vars are missing ... [IMPORTANT] THE SAME PHP.INI CONFIG I USE TO BUILD A NGINX WINDOWS SERVER TO CHECK YESTERDAY MY FASTEST PHP FRAMEWORK IN THE WORLD

YOU ARE FREE TO IMPROVE IT IF YOU KNOW JAVASCRIPT PROGRAMMING AND TO BUILD A SERVE FILES SECTION BASED ON THIS and maybe you approach to nginx features and so you no need several servers on several ports and minimum should sqlite 3 work already (just in case you can build around some stuff for localhost )

you see that pause inside runme.bat? it's only in case while you develop something in javascript and something goes wrong and it's crush ..so you will be able to hit enter to close it after you see the errors there.