Domanda

Ho una variabile che contiene una stringa lunga. (nello specifico contiene pochi kilobyte di codice javascript)

Voglio passare questa stringa tramite un comando esterno, in questo caso un compressore javascript, e catturare l'output del comando esterno (il javascript compresso) in php, assegnandolo a una variabile.

Sono a conoscenza del fatto che esistono classi per la compressione di javascript in php, ma questo è solo un esempio di un problema generale.

originariamente abbiamo utilizzato:

$newvar = passthru("echo $oldvar | compressor");

Funziona per stringhe piccole, ma non è sicuro. (se oldvar contiene caratteri con un significato speciale per la shell, potrebbe succedere di tutto)

L'escape con escapeshellarg risolve questo problema, ma la soluzione si interrompe per stringhe più lunghe, a causa delle limitazioni del sistema operativo sulla lunghezza massima consentita degli argomenti.

Ho provato a utilizzare popen("command" "w") e scrivere nel comando: funziona, ma l'output del comando scompare silenziosamente nel vuoto.

Concettualmente, voglio solo fare l'equivalente di:

$newvar = external_command($oldvar);
È stato utile?

Soluzione

Utilizzando la funzione proc_open puoi ottenere gli handle per entrambi gli stdoute stdin del processo e quindi scrivi i tuoi dati su di esso e leggi il risultato.

Altri suggerimenti

Usando il suggerimento di Rumpels, sono stato in grado di utilizzare la seguente soluzione che sembra funzionare bene.Pubblicalo qui a vantaggio di chiunque altro sia interessato alla domanda.

public static function extFilter($command, $content){
    $fds = array(
        0 => array("pipe", "r"),  // stdin is a pipe that the child will read from
        1 => array("pipe", "w"),  // stdout is a pipe that the child will write to
        2 => array("pipe", "w")   // stderr is a pipe that the child will write to
    );
    $process = proc_open($command, $fds, $pipes, NULL, NULL);
    if (is_resource($process)) {
        fwrite($pipes[0], $content);
        fclose($pipes[0]);
        $stdout =  stream_get_contents($pipes[1]);
        fclose($pipes[1]);
        $stderr = stream_get_contents($pipes[2]);
        fclose($pipes[2]);
        $return_value = proc_close($process);
        // Do whatever you want to do with $stderr and the commands exit-code.
    } else {
        // Do whatever you want to do if the command fails to start
    }
    return $stdout;
}

Potrebbero esserci problemi di deadlock: se i dati che invii sono più grandi delle dimensioni combinate delle pipe, il comando esterno si bloccherà, in attesa che qualcuno legga dal suo stdout, mentre php è bloccato, in attesa che stdinessere letto da per fare spazio a più input.

Forse PHP si prende cura di questo problema in qualche modo, ma vale la pena provarlo se prevedi di inviare (o ricevere) più dati di quanti ne possano contenere.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top