简体   繁体   中英

Executing PHP script has different results when run in CLI and by node.js script

I'm completely lost with figuring out why my PHP script produces different results when run via CLI (producing the right results) vs when run within Node.js via the exec function.

Here's my PHP. Note the fopen('blah.txt', 'w') line, which is what I'm using to check if the script reaches that place.

calculator.php

class calculator{

    public static $_var = array();

    public function calculate($xml, $xsl, $frequency){
        $reader = new DOMDocument;
        if(!$reader->load($xsl)) throw new Exception('XSL Could not be loaded: ' . $xsl);

        $processor = new XSLTProcessor;
        $processor->importStyleSheet($reader);
        $processor->registerPHPFunctions();
        $processor->setParameter('', 'frequency', $frequency);

        $dictionary = new DOMDocument;
        if(!$dictionary->load($xml)) throw new Exception('XML Could not be loaded: ' . $xml);

        $processor->transformToXML($dictionary);
    }

    public static function connectNodes($name, $dataset, $processor, $destination, $frequency){
        $var = self::$_var;
        self::$_var = array();

        $test = fopen('blah.txt', 'w');
        fclose($test);

        ob_start();
        require 'templates/' . $processor . '.php';
        $xsltSheet = new DOMDocument;
        $xsltSheet->loadXML(ob_get_clean());

        $xsltProc = new XSLTProcessor;
        $xsltProc->importStyleSheet($xsltSheet);

        $dataSet = new DOMDocument;
        if(is_file('../dataFiles/xml/' . $dataset . '.xml') && calculator::makedirs('../dataFiles/json/' . $destination . '/' . $frequency)){
            //proceed only if the dataset exists and the folders are created correctly
            $dataSet->load('../dataFiles/xml/' . $dataset . '.xml');
            if(!is_file('../dataFiles/json/' . $destination . '/' . $frequency . '/' . $name . '.json')){
                $filemaker = fopen('../dataFiles/json/' . $destination . '/' . $frequency . '/' . $name . '.json', 'w');
                fclose($filemaker);
            }
            $xsltProc->transformToURI($dataSet, '../dataFiles/json/' . $destination . '/' . $frequency . '/' . $name . '.json');
        } else {
            throw new Exception('Either dataset does not exist('. $dataset .'), or directories could not be created (dataFiles/json/'. $destination . '/' . $frequency .')');
        }

    }

    public static function populateVarWithXPath($var){
        self::$_var[] = $var;
    }

    public static function makedirs($dirpath, $mode=0777) {
        return is_dir($dirpath) || mkdir($dirpath, $mode, true);
    }

}

When I run this via the CLI, blah.txt is created in the directory of where the script is ran. But when I run this via Node.js, it doesn't create blah.txt!

Here's my node script:

script runner

var ipc = require('./ipc');
var exec = require('child_process').exec;

ipc.listen(function(frequency){

    if(frequency.toString().match(/integrator /)){
        var freq = frequency.toString().replace(/integrator /, '');
        console.log('Received message: ' + freq);

        var cmd = exec('php use_calculator.php metricsDictionary.xml metricsXmlReader.xsl ' + frequency);

        cmd.on('close', function(exitCode, stdout, stderr){
            if(exitCode === 0){
                console.log('exitcode: ' + exitCode + ' ; stdout: ' + stdout + ' ; stderr: ' + stderr);

            } else {
                console.log('Try again?');
            }
        });

        cmd.on('error', function(err){
            throw err;
        });

    }

});

The funny thing here is, if I move my blah.txt to the calculate() function (which will run first), both CLI and node will create the file.


A little more context:

The use_calculator.php file will call the calculate() function and pass the three required arguments to it. Then, within calculate(), it will do an XML and XSL file merge.

Within the XSL are rules on how to handle the XML data, and what it does is call the connectNodes() function -- which will process new XML and XSL. It's like an inception of XML/XSL.

The point is there's one XML file listing all the details of what and how other XML data should be processed. That file is read in calculate(). Then as it calculates each piece of data, it calls the connectNode() function in an inception-like way.

To make things clearer (I hope), here's the metricsXmlReader.xsl which calls connectNodes()

metricsXmlReader.xsl

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:php="http://php.net/xsl">

    <xsl:output method="html" omit-xml-declaration="yes" />

    <xsl:template match="metrics">
        <xsl:for-each select="metric">
            <xsl:if test="frequency = $frequency">
                <xsl:for-each select="xpath/var">
                    <xsl:variable name="pusher" select="php:functionString('calculator::populateVarWithXPath', .)" />
                </xsl:for-each>
                <xsl:variable name="trigger" select="php:functionString('calculator::connectNodes', name, dataset, processor, destination, frequency)" />   
            </xsl:if>
        </xsl:for-each>
    </xsl:template>

</xsl:stylesheet>

My first guess is that, wherever PHP is trying to write the file to, it can't. You could try an absolute path with rights for everyone like /tmp.

Also you should make sure that you can handle parallel requests. Because this doesn't scale. As already mentioned pipeing is a solution.

HP

PS: Have you tried it?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM