您好,登錄后才能下訂單哦!
這篇文章主要介紹了PHP應用程序中如何正確調用系統命令的相關知識,內容詳細易懂,操作簡單快捷,具有一定借鑒價值,相信大家閱讀完這篇PHP應用程序中如何正確調用系統命令文章都會有所收獲,下面我們一起來看看吧。
有時你需要使用 PHP 應用程序中的操作系統級命令。讓我們看看我們如何做到這一點,看看我們是否可以讓開發者體驗更好。
在過去的幾年里,我一直專注于我如何編寫代碼以及如何改進它的各個方面。我首先研究如何使與 HTTP 的集成更好、更面向對象。我相信我找到了實現這一目標的方法,現在我將注意力集中在其他地方。
在某些情況下,你希望在應用程序中使用 OS CLI。在 Web 應用程序或另一個 CLI 應用程序中。過去,我們使用過類似 exec
或 passthru
或 shell_exec
和 system
的方法。然后出現了 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轉儲,而無需始終使用第三方程序包!
關于“PHP應用程序中如何正確調用系統命令”這篇文章的內容就介紹到這里,感謝各位的閱讀!相信大家對“PHP應用程序中如何正確調用系統命令”知識都有一定的了解,大家如果還想學習更多知識,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。