我完全失去了弄清楚为什么我的PHP脚本在通过CLI运行时产生不同的结果(产生正确的结果)与通过exec函数在Node.js中运行时。
这是我的PHP。注意fopen('blah.txt', 'w')
行,这是我用来检查脚本是否到达该位置的。
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);
}
}
当我通过CLI运行此命令时,blah.txt将在脚本运行的目录中创建。但是当我通过Node.js运行这个时,它不会创建blah.txt!
这是我的节点脚本:
脚本跑
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;
});
}
});
有趣的是,如果我将blah.txt移动到calculate()函数中(它将首先运行),CLI和node都将创建该文件。更多的上下文:
use_calculator.php文件将调用calculate()函数并将三个必需的参数传递给它。然后,在calculate()中,它将执行XML和XSL文件合并。
在XSL中是关于如何处理XML数据的规则,它所做的是调用connectNodes()函数——该函数将处理新的XML和XSL。它就像XML/XSL的开端。
关键是有一个XML文件列出了应该处理其他XML数据的内容和方式的所有细节。该文件在calculate()中读取。然后,当它计算每个数据块时,它以类似于初始化的方式调用connectNode()函数。
为了使事情更清楚(我希望),这里是metricsXmlReader。xsl调用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>
我的第一个猜测是,无论PHP试图将文件写入何处,它都不能。您可以尝试为每个人创建一个具有权限的绝对路径,例如/tmp。
你也应该确保你可以处理并行请求。因为这个不能按比例缩放。如前所述,管道是一种解决方案。
惠普PS:你试过吗?