将Shell命令封装为类的模式

7
尽管不建议使用PHP的shell命令与非PHP系统命令交互,但在Web应用程序中快速实现某些结果仍然是一种常见方式。
是否有人将常见用例抽象成一个类库(例如Zend)并提供更合理/常见的处理方式?每次我遇到(或不得不产生)这种代码时,都是一堆过程性代码,反复复制粘贴。我想知道(希望)PHP社区是否已经找到了更好的处理Web/PHP应用程序中使用命令行应用程序的方法。

非常好的问题。用户贡献笔记中提供了各种方法,大多数都是您所描述的质量,但是......那里有各种函数的不同版本,其中一个通常会起作用。还有一些更清晰的面向对象实现,但它们只适用于非常特定的情况(例如在Linux中启动和停止进程)。拥有这个“完美”的实现将是非常好的。 - Pekka
1
什么是“常见用例”? - Artefacto
如果我能列出所有这些并且有信心我知道它们,那么我可能会自己实现它,而不是问是否已经实现了它。在任何看起来简单的编程任务中,都有大量常见条件你没有考虑到。我所说的“常见用例”只是希望解决方案已经被思考过,而不是一个包装外壳调用的单个方法类。 - Alana Storm
1个回答

3
执行命令行应用程序并不是什么肮脏的事情。实际上,这是Unix的方式。而且大多数情况下,这比试图在纯PHP代码中重新实现例如ImageMagick更加明智。(由于其cmdline args的差异,如果您正在寻找一个不错的exec()抽象,则imagemagick是一个糟糕的例子。)
你不能做太多包装。最好的方法是将内部/外部二进制文件的输入/输出总结在一个方法中:
function exec($args) {
    $args = implode(" ", array_map("escapeshellcmd", func_get_args()));
    $opts = $this->opts();
    return `{$this->bin} {$args} {$opts}`;
}

所以您只需在需要时调用 ->exec("-o", "$file")。如果特定的命令行应用程序具有固有的 --argument 命名方案,则可以使用专门的 exec 子方法进一步概括您的代码。
根据您实际的用例,您可能能够存储一些标准选项。我为 pspell 这样做了,其中选项名称与 --cmdline=args 几乎是一对一的关系:
function opts() {
    $map = array(
       "--ignore" => $this->ignore,
       "--verbose" => $this->verbose,
       "--dir={$this->dir}" => isset($this->dir),
    );
    return implode(" ", array_keys(array_intersect($map, array(1=>1))));
}

目前可能不存在一个非常通用的抽象类,适用于exec/popen(适用于各种命令行程序)。


我提到的不建议通常归结为两点:1. 生成新进程是一项昂贵的操作;2. 通常有一个本地的PHP扩展可以为您处理这些事情。 - Alana Storm

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接