Run PHP script in Node.js (or CMD)? - node.js

Due to some reasons in need to run a small part of my NodeJS Project in PHP7.
I know I can make an internal API but that would increase network dependency.
To solve this problem I found that this can be done as
php test.php
How do I provide a JSON input to this PHP file where data is stored in a JS variable not in file and receive output in another JS variable.
function runPHP(jsonString){
....what to write here
...
return output_string;
}
Note: Please, do not suggest Query parameters as the data is too large.

I assume you want to call a php scipt from a nodejs process, send some arguments in JSON and get back some JSON and process it further.
The php script:
<?php
// test.php
$stdin = fopen('php://stdin', 'r');
$json = '';
while ($line = fgets($stdin)) {
$json .= $line;
}
$decoded = \json_decode($json);
$decoded->return_message = 'Hello from PHP';
print \json_encode($decoded);
exit(0);
The nodejs script:
// test.js
function runPHP(jsonString) {
const spawn = require('child_process').spawn;
const child = spawn('php', ['test.php']);
child.stdin.setEncoding('utf-8');
child.stdout.pipe(process.stdout);
child.stdin.write(jsonString + '\n');
child.stdin.end();
}
runPHP('{"message": "hello from js"}');
This will need some polishing and error handling...

Related

return a string from an async nodejs function called in bash

i'm calling an async nodejs function that uses prompts(https://www.npmjs.com/package/prompts)
basically, the user is presented options and after they select one, i want the selection outputted to a variable in bash. I cannot get this to work. it either hangs, or outputs everything since prompts is a user interface that uses stdout
//nodefunc.js
async run() {
await blahhhh;
return result; // text string
}
console.log(run());
// bash
x=$(node nodefunc.js)
echo $x
Unless you can ensure nothing else in the node script will print to stdout, you will need a different approach.
I'd suggest having the node script write to a temporary file, and have the bash script read the output from there.
Something like this perhaps:
const fs = require('fs');
const outputString = 'I am output';
fs.writeFileSync('/tmp/node_output.txt', outputString);
node nodefunc.js
# Assuming the node script ran succesfully, read the output file
x=$(</tmp/node_output.txt)
echo "$x"
# Optionally, cleanup the tmp file
rm /tmp/node_output.txt

Use child_process#spawn with a generic string

I have a script in the form of a string that I would like to execute in a Node.js child process.
The data looks like this:
const script = {
str: 'cd bar && fee fi fo fum',
interpreter: 'zsh'
};
Normally, I could use
const exec = [script.str,'|',script.interpreter].join(' ');
const cp = require('child_process');
cp.exec(exec, function(err,stdout,sterr){});
however, cp.exec buffers the stdout/stderr, and I would like to be able to be able to stream stdout/stderr to wherever.
does anyone know if there is a way to use cp.spawn in some way with a generic string, in the same way you can use cp.exec? I would like to avoid writing the string to a temporary file and then executing the file with cp.spawn.
cp.spawn will work with a string but only if it has a predictable format - this is for a library so it needs to be extremely generic.
...I just thought of something, I am guessing the best way to do this is:
const n = cp.spawn(script.interpreter);
n.stdin.write(script.str); // <<< key part
n.stdout.setEncoding('utf8');
n.stdout.pipe(fs.createWriteStream('./wherever'));
I will try that out, but maybe someone has a better idea.
downvoter: you are useless
Ok figured this out.
I used the answer from this question:
Nodejs Child Process: write to stdin from an already initialised process
The following allows you to feed a generic string to a child process, with different shell interpreters, the following uses zsh, but you could use bash or sh or whatever executable really.
const cp = require('child_process');
const n = cp.spawn('zsh');
n.stdin.setEncoding('utf8');
n.stdin.write('echo "bar"\n'); // <<< key part, you must use newline char
n.stdout.setEncoding('utf8');
n.stdout.on('data', function(d){
console.log('data => ', d);
});
Using Node.js, it's about the same, but seems like I need to use one extra call, that is, n.stdin.end(), like so:
const cp = require('child_process');
const n = cp.spawn('node').on('error', function(e){
console.error(e.stack || e);
});
n.stdin.setEncoding('utf-8');
n.stdin.write("\n console.log(require('util').inspect({zim:'zam'}));\n\n"); // <<< key part
n.stdin.end(); /// seems necessary to call .end()
n.stdout.setEncoding('utf8');
n.stdout.on('data', function(d){
console.log('data => ', d);
});

node.js: Trouble using a systemcall to write a file to the /tmp directory

As an exercise, I'm trying to use a systemcall from node.js to write a small text file to the /tmp directory. Here is my code:
#!/bin/node
var child_process = require("child_process");
var send = "Hello, world!";
child_process.exec('cat - > /tmp/test1', { input: send });
The file actually gets created; but, no content is placed in it. Things just hang. Can someone please tell me what I'm missing?
Also, I'd really like to know how to do this synchronously.
Thanks for any input.
... doug
hm unless i forgot to rtm too, this code will just never work. There is no such input option for cp.exec.
But there is a stdio option, will let us open the expected stdio on the child.
child_process.exec('cat - > /tmp/test1', { stdio: 'pipe' });
see https://nodejs.org/api/child_process.html#child_process_options_stdio
stdios are not string, they are streams, which we can end / write / pipe / close / push etc
see https://nodejs.org/api/stream.html
Note that stdin is a writable, stdout / stderr are readable.
To write the stdin of cat you ll now consume the cp.stdin object and call for its end() method.
child_process.exec('cat - > /tmp/test1', { stdio: 'pipe' }).stdin.end('hello world');
Note that end method is a write followed by a termination of the stream, which is required to tell cat to quit.
To ensure this is working well, we should refactor it, to not send stdin to a file, instead pipe child.stdout to the process.stdout.
var child_process = require('child_process');
var cp = child_process.exec('cat -', { stdio: 'pipe' });
cp.stdin.end('hello world');
cp.stdout.pipe(process.stderr);
Note that process is a global.
I finally got my original approach to work. The big stumbling block is to know that the synchronous methods are only available in version 0.12 (and later) of node.js. Here is the code that I finally got to work:
#!/usr/local/n/versions/node/0.12.14/bin/node
var child_process = require('child_process');
var send = "Hello, world!"
child_process.execSync('cat - > /tmp/test1', { input : send }).toString();
Thanks to all for the help.
... doug

ReactPHP run every loop twice

I'm trying to learn now technology - reactPHP. But I'm stacked with starting script. I'd edited it little bit, but I have problem, if I call the react loop, the script is done twice.
I have this code:
<?php
require 'vendor/autoload.php';
$app = function ($request, $response) {
$date = new DateTime();
file_put_contents("data.txt", $date->getTimestamp().";", FILE_APPEND);
$response->writeHead(200, array('Content-Type' => 'text/plain'));
$response->end("Done\n");
};
$loop = React\EventLoop\Factory::create();
$socket = new React\Socket\Server($loop);
$http = new React\Http\Server($socket, $loop);
$http->on('request', $app);
echo "Server running at http://127.0.0.1:1337\n";
$socket->listen(1337);
$loop->run();
and if I call http://localhost:1337/react/index.php I get in data.txt this
1439849018;1439849018;
I'm expecting only one value.
I have tested your code and the problem is because your'e testing it in your browser. Your browser send request and then ask for favicon. That's it. On the image from Inspect it's the first and third line. Next time try to run the scripts from cmd.

How to use prawn pdf inside a node / express app

In a node.js app I want to generate pdf docs and send it back to the user. I would like to use Prawn PDF as I have used it before and am comfortable using it.
I suppose I should use node's child_process.spawn to call a ruby script (that returns a pdf) to achieve this but I do not know how to actually implement it!
Am doing this:
spawn = require('child_process').spawn;
pdf = spawn('my_ruby_script');
Now how do I get hold of the returned pdf doc?
Thanks,
mano
I ended up with this eventually:
var spawn = require('child_process').spawn;
var child = spawn('ruby', ['print_pdf.rb', doc_id]);
var pdf = '';
child.on('data', function(data){
pdf += data;
});
child.on('exit', function(code){
if(code == 0){
res.setHeader('Content-Type', 'application/pdf');
res.send(pdf);
}
});
The ruby prawn script generates the pdf and at the end just 'puts' the rendered pdf which is available to child as 'data'.

Resources