Como passar o conteúdo de uma variável por meio de um comando externo no php?

StackOverflow https://stackoverflow.com/questions/7331527

  •  27-10-2019
  •  | 
  •  

Pergunta

Eu tenho uma variável que contém uma longa string. (especificamente, contém alguns kilobytes de código javascript)

Quero passar esta string por meio de um comando externo, neste caso um compressor javascript, e capturar a saída do comando externo (o javascript compactado) em php, atribuindo-o a uma variável.

Estou ciente de que existem classes para compactar javascript em php, mas este é apenas um exemplo de um problema geral.

usamos originalmente:

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

Isso funciona para strings pequenas, mas não é seguro. (se oldvar contiver caracteres com significado especial para o shell, então tudo pode acontecer)

Escapar com escapeshellarg corrige isso, mas a solução falha para strings mais longas, por causa das limitações do sistema operacional no comprimento máximo permitido do argumento.

Tentei usar popen("command" "w") e escrever o comando - isso funciona, mas a saída do comando desaparece silenciosamente no vazio.

Conceitualmente, quero apenas fazer o equivalente a:

$newvar = external_command($oldvar);
Foi útil?

Solução

Usando a função proc_open , você pode obter alças para ambos stdoute stdin do processo e, assim, gravar seus dados nele e ler o resultado.

Outras dicas

Usando a sugestão do rumpels, consegui acertar a seguinte solução que parece funcionar bem.Poste aqui para o benefício de qualquer pessoa interessada na questão.

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;
}

Pode haver problemas de deadlock: se os dados que você enviar forem maiores do que os tamanhos combinados dos tubos, o comando externo irá bloquear, esperando que alguém leia de seu stdout, enquanto o php é bloqueado, esperando por stdin paraser lido para abrir espaço para mais comentários.

Possivelmente o PHP cuida desse problema de alguma forma, mas vale a pena testar se você planeja enviar (ou receber) mais dados do que cabem nos canais.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top