登录  /  注册

浅析PHP应用程序中正确调用系统命令的方法

青灯夜游
发布: 2022-12-19 19:41:50
转载
4772人浏览过

浅析PHP应用程序中正确调用系统命令的方法

有时你需要使用 PHP 应用程序中的操作系统级命令。让我们看看我们如何做到这一点,看看我们是否可以让开发者体验更好。

在过去的几年里,我一直专注于我如何编写代码以及如何改进它的各个方面。我首先研究如何使与 HTTP 的集成更好、更面向对象。我相信我找到了实现这一目标的方法,现在我将注意力集中在其他地方。【相关推荐:laravel视频教程

在某些情况下,你希望在应用程序中使用 OS CLI。在 Web 应用程序或另一个 CLI 应用程序中。过去,我们使用过类似 execpassthrushell_execsystem 的方法。然后出现了 Symfony Process 组件,我们得救了。

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

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

$command->run();
登录后复制

这种方法有什么问题?好吧,老实说,什么都没有。但是有没有办法改善开发人员的体验?假设我们从 git 切换到 svn(我不太可能知道)。

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

  • 可执行的
  • 参数

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

因此,如果我们稍微抽象一下,我们就会有一个process 和一个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 的参数,当前由我们的 HandledGitCommands trait 处理。然后我们可以把它变成 Symfony 进程可以理解的参数。我们使用 Symfony 包中的 ExecutableFinder 来最大程度地减少路径中的错误。但是,如果找不到可执行文件,我们也想抛出异常。

当我们把它们放在我们的 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 上的存储库中发布了示例代码,以便你可以使用它并查看是否可以改进你的操作系统集成。

一个很好的例子应该是SSH、MySQL,甚至Anable或Terraform!想象一下,如果你可以按计划高效地运行来自Laravel Artisan的MySQL转储,而无需始终使用第三方程序包!

原文地址:https://laravel-news.com/working-with-os-process-in-php

译文地址:https://learnku.com/laravel/t/71422

更多编程相关知识,请访问:编程视频!!

以上就是浅析PHP应用程序中正确调用系统命令的方法的详细内容,更多请关注php中文网其它相关文章!

智能AI问答
PHP中文网智能助手能迅速回答你的编程问题,提供实时的代码和解决方案,帮助你解决各种难题。不仅如此,它还能提供编程资源和学习指导,帮助你快速提升编程技能。无论你是初学者还是专业人士,AI智能助手都能成为你的可靠助手,助力你在编程领域取得更大的成就。
来源:learnku网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
作者最新文章
最新问题
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习
PHP中文网抖音号
发现有趣的

Copyright 2014-2024 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号