侯体宗的博客
  • 首页
  • Hyperf版
  • beego仿版
  • 人生(杂谈)
  • 技术
  • 关于我
  • 更多分类
    • 文件下载
    • 文字修仙
    • 中国象棋ai
    • 群聊
    • 九宫格抽奖
    • 拼图
    • 消消乐
    • 相册

在PHP中使用OS进程

php  /  管理员 发布于 2年前   642

有时您需要使用 PHP 应用程序中的操作系统级命令。

让我们看看我们如何做到这一点,看看我们是否可以让开发者体验更好。


在过去的几年里,我一直专注于我如何编写代码以及如何改进它的各个方面。

我首先研究如何使与 HTTP 的集成更好、更面向对象。

我相信我找到了实现这一目标的方法,现在我将注意力集中在其他地方。


在某些情况下,您希望在应用程序中使用 OS CLI。在 Web 应用程序或另一个 CLI 应用程序中。

过去,我们使用过类似execorpassthru或shell_execand的方法system。然后出现了 Symfony Process 组件,我们得救了。


Symfony 进程组件使得与操作系统进程集成并获得输出变得非常容易。但是我们如何与这个库集成仍然有点令人沮丧。我们创建一个新进程,传入一个参数数组,使我们希望运行的命令。让我们来看看:

$command = new Process(
command: ['git', 'push', 'origin', 'main'],
);
 
$command->run();

这种方法有什么问题?

好吧,老实说,什么都没有。但是有没有办法改善开发人员的体验?

假设我们从 git 切换到 svn(我不太可能知道)。

为了改善开发人员的体验,首先,我们需要了解逻辑上用于创建 OS 命令的组件。

我们可以将它们分解为:

可执行
参数


我们的可执行文件是我们直接与之交互的东西,例如 php、git、brew 或我们系统上任何其他已安装的二进制文件。然后争论是我们如何互动;这些可以是子命令、选项、标志或参数。

因此,如果我们稍微抽象一下,我们将得到一个带参数的 aprocess和 a command。

我们将使用接口/契约来定义我们的组件来控制我们的工作流程应该如何工作。

让我们从流程契约开始:

declare(strict_types=1);
 
namespace JustSteveKing\OS\Contracts;
use Symfony\Component\Process\Process;
 
interface ProcessContract
{
   public function build(): Process;
}

我们这里是说每个进程都必须能够被构建,并且创建的进程的结果应该是一个 Symfony 进程。

我们的流程应该构建一个命令供我们运行,所以现在让我们看看我们的命令契约:

declare(strict_types=1);
 
namespace JustSteveKing\OS\Contracts;
 
interface CommandContract
{
   public function toArgs(): array;
}

我们希望从命令中得到的主要内容是能够作为参数返回,我们可以将这些参数作为命令传递给 Symfony 进程。想法已经够多了,让我们来看一个真实的例子。

我们将使用 git 作为示例,因为我们大多数人应该能够与 git 命令相关联。

首先,让我们创建一个 Git 进程来实现我们刚刚描述的 Process Contract:

class Git implements ProcessContract
{
   use HandlesGitCommands;
   private CommandContract $command;
}

我们的流程实现了合约,并有一个命令属性,我们将使用它允许我们的流程被流畅地构建和执行。

我们有一个特点,可以让我们集中精力为我们的 Git 流程构建和制造事物的方式。

让我们看一下:

trait HandlesGitCommands
{
   public function build(): Process
   {
       return new Process(
           command: $this->command->toArgs(),
       );
   }
 
   protected function buildCommand(Git $type, array $args = []): void
   {
       $this->command = new GitCommand(
           type: $type,
           args: $args,
       );
   }
}

因此,我们的 trait 展示了流程契约本身的实现,并提供了有关如何构建流程的说明。

它还包含一个允许我们抽象构建命令的方法。


到目前为止,我们可以创建一个流程并建立一个潜在的命令。

但是,我们还没有下达命令。我们在 trait 中创建一个新的 Git 命令,它使用 Git 类作为类型。

让我们看看另一个 Git 类,它是一个枚举。不过,我将展示一个精简版本 - 实际上,您希望它映射到您希望支持的所有 git 子命令:

enum Git: string
{
   case PUSH = 'push';
   case COMMIT = 'commit';
}

然后我们将它传递给 Git 命令:

final class GitCommand implements CommandContract
{
   public function __construct(
       public readonly Git $type,
       public readonly array $args = [],
       public readonly null|string $executable = null,
   )
   {
   }
 
   public function toArgs(): array
   {
       $executable = (new ExecutableFinder())->find(
           name: $this->executable ?? 'git',
       );
        
       if (null === $executable) {
           throw new InvalidArgumentException(
           message: "Cannot find executable for [$this->executable].",
       );
   }
 
       return array_merge(
           [$executable],
           [$this->type->value],
           $this->args,
       );
   }
}

在这个类中,我们接受来自我们的 Process 的参数,目前由我们的HandledGitCommandstrait 处理。

然后我们可以把它变成 Symfony 进程可以理解的参数。

我们使用ExecutableFinderSymfony 包中的包来最大程度地减少路径中的错误。

但是,如果找不到可执行文件,我们也想抛出异常。


当我们把它们放在我们的 Git 进程中时,它看起来有点像这样:

use JustSteveKing\OS\Commands\Types\Git as SubCommand;
 
class Git implements ProcessContract
{
   use HandlesGitCommands;
   private CommandContract $command;
 
   public function push(string $branch): Process
   {
       $this->buildCommand(
       type: SubCommand:PUSH,
       args: [
           'origin',
           $branch,
           ],
       );
    
       return $this->build();
   }
}

现在剩下要做的就是运行代码本身,以便我们可以在 PHP 应用程序中很好地使用 git:

$git = new Git();
$command = $git->push(
   branch: 'main',
);
 
$result = $command->run();

push 方法的结果将允许您与 Symfony 进程进行交互——这意味着您可以使用另一端的命令进行各种操作。我们唯一改变的是围绕这个过程的创建构建一个面向对象的包装器。这使我们能够很好地开发和保持上下文,并以可测试和可扩展的方式扩展事物。


您多久在应用程序中使用操作系统命令?

你能想到任何用例吗?我已经在 GitHub 上的 repo 中发布了示例代码,以便您可以使用它并查看是否可以改进您的操作系统集成。

https://github.com/JustSteveKing/os-process

一个很好的例子应该是 SSH、MySQL,甚至是 ansible 或 terraform!

想象一下,如果您可以在 Laravel artisan 的时间表上高效地运行 MySQL 转储,而无需一直使用第三方包!


转:

https://laravel-news.com/working-with-os-process-in-php

  • 上一条:
    Laravel训练营:Laravel Bootcamp
    下一条:
    一个8岁学编程的老外,入行近40年,总结的15条程序员经验宝典
  • 昵称:

    邮箱:

    0条评论 (评论内容有缓存机制,请悉知!)
    最新最热
    • 分类目录
    • 人生(杂谈)
    • 技术
    • linux
    • Java
    • php
    • 框架(架构)
    • 前端
    • ThinkPHP
    • 数据库
    • 微信(小程序)
    • Laravel
    • Redis
    • Docker
    • Go
    • swoole
    • Windows
    • Python
    • 苹果(mac/ios)
    • 相关文章
    • Laravel从Accel获得5700万美元A轮融资(0个评论)
    • PHP 8.4 Alpha 1现已发布!(0个评论)
    • 用Time Warden监控PHP中的代码处理时间(0个评论)
    • 在PHP中使用array_pop + yield实现读取超大型目录功能示例(0个评论)
    • Property Hooks RFC在PHP 8.4中越来越接近现实(0个评论)
    • 近期文章
    • 智能合约Solidity学习CryptoZombie二课:让你的僵尸猎食(0个评论)
    • 智能合约Solidity学习CryptoZombie第一课:生成一只你的僵尸(0个评论)
    • 在go中实现一个常用的先进先出的缓存淘汰算法示例代码(0个评论)
    • 在go+gin中使用"github.com/skip2/go-qrcode"实现url转二维码功能(0个评论)
    • 在go语言中使用api.geonames.org接口实现根据国际邮政编码获取地址信息功能(1个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf分页文件功能(0个评论)
    • gmail发邮件报错:534 5.7.9 Application-specific password required...解决方案(0个评论)
    • 欧盟关于强迫劳动的规定的官方举报渠道及官方举报网站(0个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf文件功能(0个评论)
    • Laravel从Accel获得5700万美元A轮融资(0个评论)
    • 近期评论
    • 122 在

      学历:一种延缓就业设计,生活需求下的权衡之选中评论 工作几年后,报名考研了,到现在还没认真学习备考,迷茫中。作为一名北漂互联网打工人..
    • 123 在

      Clash for Windows作者删库跑路了,github已404中评论 按理说只要你在国内,所有的流量进出都在监控范围内,不管你怎么隐藏也没用,想搞你分..
    • 原梓番博客 在

      在Laravel框架中使用模型Model分表最简单的方法中评论 好久好久都没看友情链接申请了,今天刚看,已经添加。..
    • 博主 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 @1111老铁这个不行了,可以看看近期评论的其他文章..
    • 1111 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 网站不能打开,博主百忙中能否发个APP下载链接,佛跳墙或极光..
    • 2016-10
    • 2016-11
    • 2017-06
    • 2017-07
    • 2017-08
    • 2017-09
    • 2017-11
    • 2017-12
    • 2018-01
    • 2018-02
    • 2018-03
    • 2020-03
    • 2020-04
    • 2020-05
    • 2020-06
    • 2020-07
    • 2020-09
    • 2021-02
    • 2021-03
    • 2021-04
    • 2021-05
    • 2021-06
    • 2021-07
    • 2021-08
    • 2021-09
    • 2021-10
    • 2021-11
    • 2021-12
    • 2022-01
    • 2022-02
    • 2022-05
    • 2022-06
    • 2022-07
    • 2022-08
    • 2022-09
    • 2022-10
    • 2022-11
    • 2022-12
    • 2023-01
    • 2023-02
    • 2023-03
    • 2023-04
    • 2023-05
    • 2023-06
    • 2023-07
    • 2023-08
    • 2023-09
    • 2023-10
    • 2023-11
    • 2023-12
    • 2024-01
    • 2024-02
    • 2024-03
    • 2024-04
    • 2024-05
    • 2024-06
    • 2024-07
    • 2024-09
    Top

    Copyright·© 2019 侯体宗版权所有· 粤ICP备20027696号 PHP交流群

    侯体宗的博客