> ## Documentation Index
> Fetch the complete documentation index at: https://kawax.biz/llms.txt
> Use this file to discover all available pages before exploring further.

# 將套件診斷資訊加入 about

> 解說如何使用 Laravel 13 的 AboutCommand，以 CLI 與 JSON 顯示套件的設定狀態，以及求值時機與長期維護時的注意事項。

在收到使用者詢問時，讓對方能以相同格式確認套件的啟用或停用狀態，以及目前選用的驅動程式。使用 `AboutCommand::add()`，不必實作專用指令，就能在 `php artisan about` 的輸出中加入套件專用的區段。

官方文件中有註冊的基本範例。本頁會深入確認 Laravel 13 的實作，探討收集資訊的時機、JSON 的型別、區段名稱的衝突，以及測試中的註冊狀態。

## 在提供者中註冊顯示內容

下列範例的前提是，`courier.enabled` 與 `courier.driver` 已註冊為套件的設定。設定的註冊方式請參閱[套件設定的合併與快取](/zh-TW/advanced/package-config-merging)。

```php theme={null}
<?php

namespace Acme\Courier;

use Illuminate\Foundation\Console\AboutCommand;
use Illuminate\Support\ServiceProvider;

class CourierServiceProvider extends ServiceProvider
{
    public function boot(): void
    {
        if (! $this->app->runningInConsole()) {
            return;
        }

        AboutCommand::add('Acme Courier', fn () => [
            'Enabled' => AboutCommand::format(
                (bool) config('courier.enabled', false),
                console: fn (bool $enabled) => $enabled ? 'ENABLED' : 'OFF',
            ),
            'Driver' => (string) config('courier.driver', 'log'),
        ]);
    }
}
```

`runningInConsole()` 是用來避免在 HTTP 請求中進行不必要註冊的條件。它並不是只在執行 `about` 時才成立的條件，其他 Artisan 指令中也會進行註冊。不過，上方閉包內的設定讀取在註冊時並不會執行。

<Warning>
  請明確選擇要顯示的項目。不要輸出 API 金鑰、存取權杖、含有認證資訊的連線 URL 或整個設定陣列。JSON 輸出同樣不會自動遮蔽機密資訊。處理詢問時，請對方只分享套件的區段，並在分享前確認內容。
</Warning>

## 將註冊時機與求值時機分開思考

Laravel `v13.35.0` 的 `add()` 不會當場收集資料，而是將註冊用的閉包加入靜態的 `$customDataResolvers`。執行 `about` 時才會組成顯示用的資料，並對已註冊的資料取得用閉包求值。

```mermaid theme={null}
flowchart TD
    A["提供者的 boot()"] --> B["透過 add() 儲存註冊"]
    B --> C["執行 about"]
    C --> D["收集標準資訊與附加區段"]
    D --> E["對資料取得用閉包求值"]
    E --> F["以 --only 篩選區段"]
    F --> G["以 CLI 或 JSON 顯示"]
```

比起在 `add()` 外部先讀取設定值並固定在陣列中，在閉包內取得更能反映指令執行時的狀態。另一方面，`--only` 篩選是在資料取得用閉包求值**之後**才進行。

```bash theme={null}
php artisan about --only=environment
```

像這樣即使只指定標準區段，上方 `Acme Courier` 的閉包仍會被求值。沒有顯示與沒有處理是兩回事。

因此，附加資訊應從設定值或輕量的本機狀態取得。若加入外部 API 的連通確認、資料庫查詢、檔案改寫等處理，連查看無關區段的指令都可能變慢或失敗。連通確認與修復請拆分到專用的 Artisan 指令中。

<Tip>
  僅憑 `runningInConsole()` 條件，無法保證延遲服務提供者的 `boot()` 會被執行。若希望一律註冊診斷資訊，請將該註冊放在立即載入的提供者中。只將服務綁定延遲化的架構請參閱[延遲服務提供者](/zh-TW/advanced/deferred-provider)。
</Tip>

## 兼顧 CLI 顯示與 JSON 型別

若只想確認套件的資訊，請指定將區段名稱轉為小寫 snake case 後的值。以 `Acme Courier` 為例即為 `acme_courier`。

```bash theme={null}
php artisan about --only=acme_courier
php artisan about --only=environment,acme_courier
php artisan about --only=acme_courier --json
```

在上方的註冊範例中，當 `courier.enabled` 為 `true`、`courier.driver` 為 `log` 時，JSON 會是下列形式。

```json theme={null}
{
  "acme_courier": {
    "enabled": true,
    "driver": "log"
  }
}
```

在 CLI 中，`Enabled` 會顯示為 `ENABLED`。`AboutCommand::format()` 是可分別指定 CLI 用的 `console` 與 JSON 用的 `json` 的輔助方法。上方範例只指定了 `console`，因此 JSON 會回傳原本的 boolean 值。不需要將 CLI 的顯示字串直接沿用到 JSON。

| 對象 | 實作上的轉換與處理 |
| - | - |
| `--only` 的值與區段名稱 | 轉為小寫後再轉換為 snake case 進行比較 |
| JSON 的區段鍵 | 將區段名稱轉換為 snake case |
| JSON 的項目鍵 | 將項目名稱轉為小寫後再轉換為 snake case |
| `format()` 的值 | CLI 使用 `console`，JSON 使用 `json`。未指定時為原本的值 |

如範例般使用以空白分隔的一般英文單字作為名稱，篩選與 JSON 鍵會更容易處理。自動化處理所參照的鍵可能因顯示名稱的變更而改變，因此請在發布時確認相容性。

## 區段請使用套件專用的名稱

`add()` 會將項目附加到同一個區段。指定同名的區段並不會取代先前註冊的全部內容。

請選擇像 `Acme Courier` 這樣能與其他套件區分的名稱，並僅在必要時才加入 Laravel 標準的 `Environment`、`Cache`、`Drivers`、`Storage`。

若在同一區段中重複註冊同名項目，CLI 中可能會留下多行，但 JSON 中會彙整到同一個鍵並保留後者的值。此外，即使寫法不同，也請避免轉換為 snake case 後會成為相同鍵的名稱。請將註冊位置集中在一處，設計成在 CLI 與 JSON 中項目都是唯一的。

## 在測試中處理靜態的註冊狀態

`about` 開始執行時，顯示用的 `$data` 會被初始化，但附加資訊的註冊清單 `$customDataResolvers` 會被保留。這樣每次都能從相同的註冊重新收集資訊，但若在同一個 PHP 行程中重複執行提供者的 `boot()`，註冊可能會累積。

`AboutCommand::flushState()` 是清除**所有套件的註冊**與顯示用資料的方法。請不要為了避免自身區段重複而在正式環境的提供者中呼叫它，否則連其他套件的診斷資訊也會遺失。

若在自有的測試基礎架構中重建應用程式，請決定由誰負責在測試之間初始化狀態。若要初始化，請在啟動目標提供者之前進行，之後再完成所有必要的註冊。也請確認既有的測試基礎架構是否已初始化狀態。

### 發布前的確認項目

請在[以 Orchestra Testbench 測試 Laravel 套件](/zh-TW/advanced/package-testing)與實際使用的應用程式中確認下列組合。

| 要確認的操作 | 預期結果 |
| - | - |
| `about --only=acme_courier` | 只顯示套件的區段，項目不重複 |
| `about --only=acme_courier --json` | `enabled` 以 boolean、`driver` 以 string 取得 |
| `about --only=environment` | 套件的資訊收集沒有外部通訊或副作用，並正常結束 |
| 變更啟用或停用、驅動程式 | 顯示值與 JSON 值對應指令執行時的設定 |
| 在同一應用程式中執行 2 次 | 項目不會累積，每次執行都重新收集資訊 |
| 在同一 PHP 行程中重建應用程式 | 註冊狀態不會在測試之間外洩，其他套件的資訊也不會缺漏 |
| 存在設定快取的狀態 | 顯示應用程式實際使用的設定值，而非已發布設定檔的內容 |

## 相關頁面

<Columns cols={2}>
  <Card title="Laravel 套件開發" icon="box" href="/zh-TW/advanced/package-development">
    確認提供者與資源註冊的基礎。
  </Card>

  <Card title="套件設定的合併與快取" icon="sliders" href="/zh-TW/advanced/package-config-merging">
    確認預設值、使用者覆寫與設定快取之間的關係。
  </Card>
</Columns>

## 參考的第一手資料

* [Laravel 官方文件：從套件將資訊加入 about](https://github.com/laravel/docs/blob/13.x/packages.md#about-artisan-command)
* [Laravel 官方文件：about 與 --only](https://github.com/laravel/docs/blob/13.x/configuration.md#the-about-command)
* [Laravel Framework v13.35.0: AboutCommand](https://github.com/laravel/framework/blob/v13.35.0/src/Illuminate/Foundation/Console/AboutCommand.php)：註冊、求值順序、鍵轉換、`format()`、`flushState()`。
* [Laravel Framework v13.35.0: format 的測試](https://github.com/laravel/framework/blob/v13.35.0/tests/Foundation/Console/AboutCommandTest.php)
* [Laravel Framework v13.35.0: JSON 輸出的整合測試](https://github.com/laravel/framework/blob/v13.35.0/tests/Integration/Foundation/Console/AboutCommandTest.php)


## Related topics

- [Laravel 套件開發](/zh-TW/advanced/package-development.md)
- [核心套件與自訂驅動 - Feedable](/zh-TW/packages/feedable/core.md)
- [Laravel Doctor — 應用診斷工具](/zh-TW/blog/laravel-doctor-introduction.md)
- [Socialite for Discord](/zh-TW/packages/socialite-discord.md)
- [通知 Channel - LINE SDK for Laravel](/zh-TW/packages/laravel-line-sdk/notification.md)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.