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

# パッケージビューの上書きと更新

> Laravel 13の実装から、名前空間付きビューの検索順序、公開済みBladeテンプレートの保守、ビューキャッシュと検索結果のキャッシュの違いを解説します。

利用者が画面やメールのテンプレートをカスタマイズできるパッケージでは、ビューを公開するだけでなく、公開済みファイルを残したまま更新できる契約が必要です。パッケージ側のBladeファイルを修正しても、利用アプリケーションがそのファイルを描画しているとは限りません。

このページでは[パッケージ開発の基礎](/jp/advanced/package-development)を前提に、ビューの選択とファイルの公開、キャッシュを分けて考えます。公式ドキュメントはLaravel 13、フレームワークの実装は最新リリースの `v13.34.0` を参照しています。

## 登録と公開は別の処理

`loadViewsFrom()` は名前空間に検索パスを登録します。`publishes()` はコピー元とコピー先を登録し、実際のコピーは `vendor:publish` が行います。次の例では、公開しなくても `courier::deliveries.show` を利用できます。

```php src/CourierServiceProvider.php theme={null}
<?php

namespace Acme\Courier;

use Illuminate\Support\ServiceProvider;

class CourierServiceProvider extends ServiceProvider
{
    public function boot(): void
    {
        $this->loadViewsFrom(__DIR__.'/../resources/views', 'courier');

        $this->publishes([
            __DIR__.'/../resources/views' => resource_path('views/vendor/courier'),
        ], 'courier-views');
    }
}
```

パッケージ側のファイルは `resources/views/deliveries/show.blade.php` に置きます。ビュー名のドットは、検索時にディレクトリ区切りへ変換されます。

```php theme={null}
return view('courier::deliveries.show', [
    'trackingCode' => 'TRACK-001',
]);
```

```blade resources/views/deliveries/show.blade.php theme={null}
<p>追跡番号: {{ $trackingCode }}</p>
```

ビューの名前空間はComposerのパッケージ名やPHPの名前空間とは別です。ここでは `loadViewsFrom()` の第2引数に指定した `courier` が、ビュー参照と上書き先ディレクトリの契約になります。

## ファイル単位で上書き先を探す

`ServiceProvider::loadViewsFrom()` は `view` が解決されたときに、設定の `view.paths` を順番に確認します。各パスに `vendor/courier` ディレクトリが存在する場合は、そのディレクトリを名前空間へ追加し、最後にパッケージ側のパスを追加します。

`FileViewFinder` は、その名前空間のパスを順番に検索し、最初に見つかったファイルを返します。標準の `resources/views` を使う構成では、次の順序です。

```mermaid theme={null}
flowchart TD
    A["courier::deliveries.show"] --> B["resources/views/vendor/courier/<br>deliveries/show.blade.phpを検索"]
    B --> C{"ファイルがある?"}
    C -->|はい| D["利用アプリケーションのビューを使用"]
    C -->|いいえ| E["パッケージのresources/views/<br>deliveries/show.blade.phpを検索"]
    E --> F{"ファイルがある?"}
    F -->|はい| G["パッケージのビューを使用"]
    F -->|いいえ| H["ビューが見つからない例外"]
```

これはディレクトリ全体の切り替えではありません。利用者が `deliveries/show.blade.php` だけを上書きしても、上書きしていない他のビューはパッケージ側から読み込まれます。

| 利用アプリケーションの状態 | 選ばれるビュー |
| - | - |
| 上書きファイルがない | パッケージのファイル |
| 同じ相対パスの上書きファイルがある | 利用アプリケーションのファイル |
| 上書きファイルだけを除去した | 新しい起動ではパッケージのファイルへ戻る |
| 両方に対象ファイルがない | `View [...] not found.` の例外 |

<Info>
  `view.paths` が複数ある構成では、上書き先も複数になり得ます。`resource_path('views/vendor/courier')` はこの例の公開先であり、検索対象をそこだけに固定する処理ではありません。名前空間はパッケージ固有のものにし、複数のプロバイダーで同じ名前へパスを追加する設計を避けてください。
</Info>

## 必要なビューだけをカスタマイズする

利用者は次のコマンドでテンプレートをコピーできます。プロバイダーとタグを指定し、他のリソースを巻き込まないようにします。

```bash theme={null}
php artisan vendor:publish --provider="Acme\Courier\CourierServiceProvider" --tag=courier-views
```

この登録ではビューディレクトリ全体が公開されます。すべてを上書きする必要がなければ、内容を確認してカスタマイズするファイルだけを残す、または必要なファイルだけを同じ相対パスへ手動でコピーする方法もあります。編集していないコピーも存在する限り上書きとして扱われるためです。

<Warning>
  公開済みテンプレートはパッケージの更新と自動同期されません。古いコピーが優先される状態でパッケージ側だけを修正しても、そのビューの変更は反映されません。表示の不具合修正やフォーム変更なども、上書きファイルとの比較が必要です。
</Warning>

### 再公開では差分のマージをしない

`VendorPublishCommand` は通常、同名の公開先ファイルが存在する場合にコピーをスキップします。`--force` は既存ファイルを上書きします。また、`--existing` も「公開済みのファイルを上書きする」オプションであり、利用者の編集を保持するモードではありません。

| 操作 | ビューファイルへの影響 |
| - | - |
| 通常の再公開 | 既存ファイルは保持し、存在しない対象ファイルはコピーする |
| `--force` を付けて公開 | 既存のカスタマイズも上書きする |
| `--existing` を付けて公開 | 公開先に存在する対象ファイルだけを上書きする |

どの方法も、旧版・新版・利用者の編集を比較したマージではありません。パッケージから削除されたビューを公開先から自動で取り除く処理でもありません。更新手順を「同じタグを再公開するだけ」にしないでください。

## ビューも公開APIとして保守する

ビュー名だけでなく、受け取るデータや参照する部品も利用者のカスタマイズに影響します。たとえば、新版で `trackingCode` を別の変数名へ変更すると、旧テンプレートを残している利用者は新しいコードから必要な値を受け取れなくなります。

リリース前に、次の契約を確認します。

* 名前空間と `deliveries.show` などのビュー名を不用意に変更しない。
* 渡す変数、型、必須・任意の区別を記録する。
* `@include` や `@extends` の参照先、Bladeコンポーネントのpropsも変更点に含める。
* 修正したビューと、公開済みの旧版へ適用すべき変更をリリースノートに記載する。

利用者向けには、旧版のパッケージビューと新版を比較し、カスタマイズ済みファイルへ必要な変更を手動で取り込む手順を用意します。上書きが不要になったファイルは、バックアップやバージョン管理で変更を保全してから取り除くと、パッケージ側のビューへ戻せます。

## Bladeキャッシュは上書きファイルを更新しない

`view:cache` はBladeテンプレートをPHPへ事前コンパイルします。`ViewCacheCommand` は最初に `view:clear` を実行し、通常のビューパスと名前空間に登録されたパスを集めてコンパイル対象を探します。

```bash theme={null}
php artisan view:cache
```

この処理は公開済みのBladeファイルを書き換えず、ビューの検索優先順位も変えません。古い上書きファイルが存在すれば、キャッシュを再構築してもそのファイルが引き続き選ばれます。デプロイでは、コードと上書きファイルの更新を済ませてからコンパイルします。

開発中にコンパイル済みファイルを消して再描画したい場合は、次のコマンドを使います。

```bash theme={null}
php artisan view:clear
```

通常のタイムスタンプ確認が有効なら、Bladeコンパイラーは元ファイルとコンパイル済みファイルの更新時刻を比較します。ただし、タイムスタンプ確認を無効にする構成もあるため、デプロイ時の再構築を自動判定だけに任せないでください。

### 検索結果のキャッシュとは区別する

`FileViewFinder::find()` は、見つけたパスをそのFinderインスタンスの `$views` 配列へ保存します。また、上書きディレクトリの存在確認は `loadViewsFrom()` のコールバックで行われます。起動後に新しいディレクトリを追加しても、すでに登録済みの検索パスへ自動追加されるわけではありません。

| 管理対象 | 役割 | 更新時の考え方 |
| - | - | - |
| 公開済みBladeファイル | 利用者のカスタマイズ | 差分を取り込むか、上書きをやめる |
| コンパイル済みPHP | Bladeのコンパイル結果 | `view:cache` / `view:clear` で管理する |
| Finderの登録パス・検索結果 | 実行中インスタンスのビュー選択 | 長時間動くプロセスを新しいコード・構成で再起動する |

`view:clear` は、別の実行中プロセスが保持するFinderの状態を一括で消すコマンドではありません。Octaneなどの長時間動くプロセスでは、通常のデプロイ手順に従い再読み込みしてください。Finderの `flush()` は検索結果を消しますが、新しい上書きディレクトリの登録まで行う処理ではありません。

## リリース前に確認すること

パッケージのテストに加え、利用アプリケーションで次の組み合わせを確認します。最新テンプレートだけを描画するテストでは、旧版を公開済みの利用者への互換性は検証できません。

* 未公開の状態で、パッケージのビューが描画される。
* 1つだけ上書きすると、そのファイルだけが優先され、他はパッケージへフォールバックする。
* 旧版の公開済みテンプレートを残した状態でも、新版が渡すデータで描画できる。
* 通常の再公開でカスタマイズが保持され、未公開ファイルの追加も意図どおりである。
* 上書きファイルの変更後に `view:cache` が成功し、新しい起動で変更後の表示になる。

## 関連ページ

<Columns cols={2}>
  <Card title="ビュー" icon="eye" href="/jp/views">
    ビューの作成、データの受け渡し、事前コンパイルの基本を確認します。
  </Card>

  <Card title="Bladeテンプレート" icon="code" href="/jp/blade">
    レイアウト、include、コンポーネントの使い方を確認します。
  </Card>

  <Card title="バージョン互換性管理" icon="code-branch" href="/jp/advanced/package-versioning">
    テンプレートの契約変更をリリース方針に結び付けます。
  </Card>

  <Card title="Octane" icon="bolt" href="/jp/octane">
    長時間動くアプリケーションのライフサイクルと再読み込みを確認します。
  </Card>
</Columns>

## 参照した一次情報

* [Laravel公式ドキュメント: パッケージのビュー](https://github.com/laravel/docs/blob/156fc7fde114548640e13c39aa79b991291c3f91/packages.md#views)
* [ServiceProvider: ビューパスの登録](https://github.com/laravel/framework/blob/v13.34.0/src/Illuminate/Support/ServiceProvider.php)
* [FileViewFinder: 検索順序と検索結果の保持](https://github.com/laravel/framework/blob/v13.34.0/src/Illuminate/View/FileViewFinder.php)
* [VendorPublishCommand: ファイルの公開条件](https://github.com/laravel/framework/blob/v13.34.0/src/Illuminate/Foundation/Console/VendorPublishCommand.php)
* [ViewCacheCommand: ビューパスの収集とコンパイル](https://github.com/laravel/framework/blob/v13.34.0/src/Illuminate/Foundation/Console/ViewCacheCommand.php)
* [ViewClearCommand: コンパイル済みファイルの削除](https://github.com/laravel/framework/blob/v13.34.0/src/Illuminate/Foundation/Console/ViewClearCommand.php)
* [Compiler: 更新時刻の確認](https://github.com/laravel/framework/blob/v13.34.0/src/Illuminate/View/Compilers/Compiler.php)


## Related topics

- [Laravelパッケージ開発](/jp/advanced/package-development.md)
- [応用トピック](/jp/advanced/index.md)
- [パッケージのマイグレーション公開と更新](/jp/advanced/package-migrations.md)
- [パッケージ設定のマージとキャッシュ](/jp/advanced/package-config-merging.md)
- [Laravel Pennant 実践ユースケース](/jp/blog/laravel-pennant.md)


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