我认为我们大多数使用 Laravel 一段时间的人都很熟悉包安装流程:通过 Composer 添加包,注册服务提供者,发布配置文件,更新环境文件,希望你能记得更新 .env.example,并且在完成所有操作后,你希望自己没有遗漏任何步骤。这通常涉及从 README 中复制粘贴,并在编辑器和浏览器之间来回切换。随着 Laravel 5.5 的发布,我们对这个流程有了很大的改进,引入了 包发现,但这并没有改变这个流程本身。
当我开始构建 Laravel 的 Honeybadger 集成时,我几乎从未见过 PHP 包的安装命令。我能想到的唯一一个命令是 Laravel Spark。当我们开始为集成概述功能时,Josh 建议构建一个类似于 Ruby gem 中的安装命令。我认为这是一个非常棒的想法,它将使安装流程更加顺畅。
我对添加此功能有一些非常具体的目标
- 显示所有执行的任务(成功和失败)
- 尽可能避免手动操作
- 使用命令提示符获取任何所需的信息
- 兼容 Laravel 和 Lumen
可见性
我真的不希望这个安装程序只是在后台运行,修改你的许多文件,然后只是返回一个消息说一切都很成功。我也不会希望输出过于冗长。
我偶然发现了 Nuno Maduro 的一个很棒的包 nunomaduro/laravel-console-task。我真的很喜欢它简单的 API 和漂亮的输出。然而,它在 Lumen 中运行时遇到了一些问题,所以我编写了一个简单的类来收集任务名称和结果状态。
<?php namespace Honeybadger\HoneybadgerLaravel; use Illuminate\Console\OutputStyle; class CommandTasks{    /**     * @var \Illuminate\Console\OutputStyle     */    protected $output;     /**     * @var array     */    protected $results = [];     /**     * Set command output.     *     * @param  \Illuminate\Console\OutputStyle  $output     * @return self     */    public function setOutput(OutputStyle $output) : self    {        $this->output = $output;         return $this;    }     /**     * Add task with result to the stack.     *     * @param  string  $name     * @param  bool  $result     * @return self     */    public function addTask(string $name, bool $result) : self    {        $this->results[$name] = $result;         return $this;    }     /**     * Send results to the command output.     *     * @return void     */    public function outputResults() : void    {        collect($this->results)->each(function ($result, $description) {            $this->output->writeLn(vsprintf('%s: %s', [                $description,                $result ? '<fg=green>✔</>' : '<fg=red>✘</>',            ]));        });    }     /**     * Get the results of all tasks.     *     * @return array     */    public function getResults() : array    {        return $this->results;    }}它保持了简单的 API 和漂亮的输出
$this->tasks->addTask(    'Write HONEYBADGER_API_KEY to .env',    $this->installer->writeConfig(        ['HONEYBADGER_API_KEY' => $this->config['api_key']],        base_path('.env')    ));
避免手动操作
使用安装程序的目的是使安装流程快速、简单且愉快。我发现安装新包最大的痛点之一是更新 .env 文件和 .env.example 文件。
我最终编写了一个非常轻量级的包来完成这项工作,即 sixlive/dotenv-editor。
public function writeConfig(array $config, string $filePath) : bool{    try {        $env = new DotenvEditor;        $env->load($filePath);    } catch (InvalidArgumentException $e) {        return false;    }     collect($config)->each(function ($value, $key) use ($env) {        $env->set($key, $value);    });     return $env->save();}然后我们可以使用该方法写入这两个环境文件。我们将在 .env.example 文件中写入一个空值,并将通过命令输入收集的 API 写入 .env 文件
private function writeEnv() : void{    $this->tasks->addTask(        'Write HONEYBADGER_API_KEY to .env',        $this->installer->writeConfig(            ['HONEYBADGER_API_KEY' => $this->config['api_key']],            base_path('.env')        )    );     $this->tasks->addTask(        'Write HONEYBADGER_API_KEY placeholder to .env.example',        $this->installer->writeConfig(            ['HONEYBADGER_API_KEY' => ''],            base_path('.env.example')        )    );}我还想为 Laravel 和 Lumen 发布配置文件。使用 Laravel 非常简单,你可以调用 vendor:publish 命令。
public function publishLaravelConfig() : bool{    return Artisan::call('vendor:publish', [        '--provider' => HoneybadgerServiceProvider::class,    ]) === 0;}Lumen 则有点棘手,因为它缺少 Laravel 附带的许多命令。
public function publishLumenConfig(string $stubPath = null): bool{    if (! is_dir(base_path('config'))) {        mkdir(base_path('config'));    }     return copy(        $stubPath ?? __DIR__.'/../config/honeybadger.php',        base_path('config/honeybadger.php')    );}在所有配置就位之后,我们需要向 Honeybadger 发送一个测试异常。这样做是为了确保所有配置和安装步骤都正确完成。

提示配置值
在执行任何安装任务之前,我们首先要收集所有配置值,以便我们可以一步完成所有安装操作。
public function handle(){    $this->config = $this->gatherConfig();} private function gatherConfig() : array{    return [        'api_key' => $this->argument('apiKey') ?? $this->promptForApiKey(),        'send_test' => $this->confirm('Would you like to send a test exception now?', true),    ];} private function promptForApiKey() : string{    return $this->requiredSecret('Your API key', 'The API key is required');}Laravel 使我们能够非常轻松地直接将所有配置值提示到一个关联数组中。这使得在整个命令中引用这些值变得超级简单。
我需要确保 API 密钥是必需的。我编写了一个非常简单的函数,它会持续提示输入 API,直到输入为止。
trait RequiredInput{    public function requiredSecret($question, $failedMessage)    {        $input = $this->secret($question);         if (is_null($input)) {            $this->error($failedMessage);             return $this->requiredSecret($question, $failedMessage);        }         return $input;    }总结
Honeybadger 团队非常努力地提供流畅、精致、愉快的端到端体验,我认为这与 Laravel 的一些核心原则完美契合。我认为,通过为包使用安装程序,它将这种体验从他们的应用程序带到了你的终端。我们正在对安装程序进行最后的润色,它将很快加入到 honeybadger-io/honeybadger-laravel 库中。你可以关注此处的 pull 请求 honeybadger-io/honeybadger-laravel/#11。同时,Honeybadger 仍然非常容易上手。
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
