溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

PHP應(yīng)用程序中如何正確調(diào)用系統(tǒng)命令

發(fā)布時(shí)間:2022-12-27 14:17:24 來源:億速云 閱讀:116 作者:iii 欄目:編程語(yǔ)言

這篇文章主要介紹了PHP應(yīng)用程序中如何正確調(diào)用系統(tǒng)命令的相關(guān)知識(shí),內(nèi)容詳細(xì)易懂,操作簡(jiǎn)單快捷,具有一定借鑒價(jià)值,相信大家閱讀完這篇PHP應(yīng)用程序中如何正確調(diào)用系統(tǒng)命令文章都會(huì)有所收獲,下面我們一起來看看吧。

有時(shí)你需要使用 PHP 應(yīng)用程序中的操作系統(tǒng)級(jí)命令。讓我們看看我們?nèi)绾巫龅竭@一點(diǎn),看看我們是否可以讓開發(fā)者體驗(yàn)更好。

在過去的幾年里,我一直專注于我如何編寫代碼以及如何改進(jìn)它的各個(gè)方面。我首先研究如何使與 HTTP 的集成更好、更面向?qū)ο?。我相信我找到了?shí)現(xiàn)這一目標(biāo)的方法,現(xiàn)在我將注意力集中在其他地方。

在某些情況下,你希望在應(yīng)用程序中使用 OS CLI。在 Web 應(yīng)用程序或另一個(gè) CLI 應(yīng)用程序中。過去,我們使用過類似 execpassthrushell_execsystem 的方法。然后出現(xiàn)了 Symfony Process 組件,我們得救了。

Symfony 進(jìn)程組件使得與操作系統(tǒng)進(jìn)程集成并獲得輸出變得非常容易。但是我們?nèi)绾闻c這個(gè)庫(kù)集成仍然有點(diǎn)令人沮喪。我們創(chuàng)建一個(gè)新進(jìn)程,傳入一個(gè)參數(shù)數(shù)組,使我們希望運(yùn)行的命令。讓我們來看看:

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

$command->run();

這種方法有什么問題?好吧,老實(shí)說,什么都沒有。但是有沒有辦法改善開發(fā)人員的體驗(yàn)?假設(shè)我們從 git 切換到 svn(我不太可能知道)。

為了改善開發(fā)人員的體驗(yàn),首先,我們需要了解邏輯上用于創(chuàng)建 OS 命令的組件。我們可以將它們分解為:

  • 可執(zhí)行的

  • 參數(shù)

我們的可執(zhí)行文件是我們直接與之交互的東西,例如 php、git、brew 或我們系統(tǒng)上任何其他已安裝的二進(jìn)制文件。然后爭(zhēng)論是我們?nèi)绾位?dòng);這些可以是子命令、選項(xiàng)、標(biāo)志或參數(shù)。

因此,如果我們稍微抽象一下,我們就會(huì)有一個(gè)process 和一個(gè)command , 它接受參數(shù)。我們將使用接口/契約來定義我們的組件來控制我們的工作流程應(yīng)該如何工作。讓我們從流程契約開始:

declare(strict_types=1);

namespace JustSteveKing\OS\Contracts;

use Symfony\Component\Process\Process;

interface ProcessContract
{
    public function build(): Process;
}

我們這里是說每個(gè)進(jìn)程都必須能夠被構(gòu)建,并且創(chuàng)建的進(jìn)程的結(jié)果應(yīng)該是一個(gè) Symfony 進(jìn)程。我們的流程應(yīng)該構(gòu)建一個(gè)命令供我們運(yùn)行,所以現(xiàn)在讓我們看看我們的命令契約:

declare(strict_types=1);

namespace JustSteveKing\OS\Contracts;

interface CommandContract
{
    public function toArgs(): array;
}

我們希望從命令中得到的主要內(nèi)容是能夠作為參數(shù)返回,我們可以將這些參數(shù)作為命令傳遞給 Symfony 進(jìn)程。

想法已經(jīng)夠多了,讓我們來看一個(gè)真實(shí)的例子。我們將使用 git 作為示例,因?yàn)槲覀兇蠖鄶?shù)人應(yīng)該能夠與 git 命令相關(guān)聯(lián)。

首先,讓我們創(chuàng)建一個(gè) Git 進(jìn)程來實(shí)現(xiàn)我們剛剛描述的 Process Contract:

class Git implements ProcessContract
{
    use HandlesGitCommands;

    private CommandContract $command;
}

我們的流程實(shí)現(xiàn)了合約,并有一個(gè)命令屬性,我們將使用它允許我們的流程被流暢地構(gòu)建和執(zhí)行。我們有一個(gè)特點(diǎn),可以讓我們集中精力為我們的 Git 流程構(gòu)建和制造事物的方式。讓我們看一下:

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 展示了流程契約本身的實(shí)現(xiàn),并提供了有關(guān)如何構(gòu)建流程的說明。它還包含一個(gè)允許我們抽象構(gòu)建命令的方法。

到目前為止,我們可以創(chuàng)建一個(gè)流程并建立一個(gè)潛在的命令。但是,我們還沒有下達(dá)命令。我們?cè)?trait 中創(chuàng)建一個(gè)新的 Git 命令,它使用 Git 類作為類型。讓我們看看另一個(gè) Git 類,它是一個(gè)枚舉。不過,我將展示一個(gè)精簡(jiǎn)版本 - 實(shí)際上,你希望它映射到你希望支持的所有 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,
        );
    }
}

在這個(gè)類中,我們接受來自 Process 的參數(shù),當(dāng)前由我們的 HandledGitCommands trait 處理。然后我們可以把它變成 Symfony 進(jìn)程可以理解的參數(shù)。我們使用 Symfony 包中的 ExecutableFinder 來最大程度地減少路徑中的錯(cuò)誤。但是,如果找不到可執(zhí)行文件,我們也想拋出異常。

當(dāng)我們把它們放在我們的 Git 進(jìn)程中時(shí),它看起來有點(diǎn)像這樣:

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

現(xiàn)在剩下要做的就是運(yùn)行代碼本身,以便我們可以在 PHP 應(yīng)用程序中很好地使用 git:

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

$result = $command->run();

Push方法的結(jié)果將允許你與symfony進(jìn)程交互-這意味著你可以在另一端使用命令執(zhí)行所有排序。我們唯一改變的是圍繞這個(gè)過程的創(chuàng)建構(gòu)建了一個(gè)面向?qū)ο蟮陌b器。這使我們能夠很好地開發(fā)和維護(hù)上下文,并以可測(cè)試和可擴(kuò)展的方式擴(kuò)展事物。

你多久在應(yīng)用程序中使用操作系統(tǒng)命令?你能想到任何用例嗎?我已經(jīng) 在 GitHub 上的存儲(chǔ)庫(kù)中發(fā)布了示例代碼,以便你可以使用它并查看是否可以改進(jìn)你的操作系統(tǒng)集成。

一個(gè)很好的例子應(yīng)該是SSH、MySQL,甚至Anable或Terraform!想象一下,如果你可以按計(jì)劃高效地運(yùn)行來自Laravel Artisan的MySQL轉(zhuǎn)儲(chǔ),而無需始終使用第三方程序包!

關(guān)于“PHP應(yīng)用程序中如何正確調(diào)用系統(tǒng)命令”這篇文章的內(nèi)容就介紹到這里,感謝各位的閱讀!相信大家對(duì)“PHP應(yīng)用程序中如何正確調(diào)用系統(tǒng)命令”知識(shí)都有一定的了解,大家如果還想學(xué)習(xí)更多知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

php
AI