ホームページ >バックエンド開発 >PHPチュートリアル >Laravelのモデルイベントのガイド

Laravelのモデルイベントのガイド

James Robert Taylor
James Robert Taylorオリジナル
2025-03-06 02:25:14857ブラウズ

A guide to Laravel's model events

Laravelのモデルイベントは、雄弁なモデルで特定の操作を実行するときにロジックを自動的に実行するのに役立つ非常に便利な機能です。ただし、不適切に使用すると、奇妙な副作用につながることがあります。

この記事では、モデルイベントとLaravelアプリケーションで使用する方法を調べます。また、モデルイベントを使用する際に注意するために、モデルイベントをテストする方法といくつかの問題を調べます。最後に、使用を検討できるモデルイベントの代替案について説明します。

イベントとリスナーとは何ですか?


「イベント」と「リスナー」を聞いたことがあるかもしれません。しかし、あなたがそれを聞いたことがないなら、それらの簡単な概要を次に示します:

#EVENT

これらは、行動するアプリで起こることです。たとえば、ユーザーはウェブサイトでサインアップしたり、ユーザーのログインなどです。

通常、Laravelでは、イベントはPHPクラスです。フレームワークまたはサードパーティパッケージによって提供されるイベントに加えて、通常、app/Eventsディレクトリに保存されます。

以下は、ユーザーがWebサイトに登録するときにスケジュールしたい単純なイベントクラスの例です。

上記の基本的な例では、コンストラクターのモデルインスタンスを受け入れる
declare(strict_types=1);

namespace App\Events;

use App\Models\User;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;

final class UserRegistered
{
    use Dispatchable;
    use InteractsWithSockets;
    use SerializesModels;

    public function __construct(public User $user)
    {
        //
    }
}
イベントクラスがあります。このイベントクラスは、登録されたユーザーインスタンスを保存するためのシンプルなコンテナです。

派遣されると、イベントはそれを聞いているリスナーをトリガーします。 AppEventsUserRegistered User以下は、ユーザーが登録したときにイベントをスケジュールする方法の簡単な例です。

上記の例では、新しいユーザーを作成してから、ユーザーインスタンスを使用して

イベントをスケジュールしています。リスナーが正しく登録されていると仮定すると、これにより、

イベントで聞いているリスナーがトリガーされます。

#listener
use App\Events\UserRegistered;
use App\Models\User;

$user = User::create([
    'name' => 'Eric Barnes',
    'email' => 'eric@example.com',
]);

UserRegistered::dispatch($user);

リスナーは、特定のイベントが発生したときに実行するコードのブロックです。 AppEventsUserRegistered AppEventsUserRegisteredたとえば、ユーザー登録の例に固執する場合、ユーザーが登録されたときにユーザーにウェルカムメールを送信することができます。リスナーのイベントを作成して、ウェルカムメールを送信できます。

laravelでは、リスナーは通常(常にではない)クラスであり、

ディレクトリにあります。

リスナーがユーザーのレジスタが次のようになる場合にウェルカムメールをユーザーに送信する例:

AppEventsUserRegistered 上記のコード例で見たように、

リスナークラスには、

イベントインスタンスを受け入れるapp/Listenersメソッドがあります。この方法は、ウェルカムメールをユーザーに送信する責任があります。

イベントやリスナーに関する詳細な手順については、公式ドキュメントをチェックしてください:

https://www.php.cn/link/d9a8c56824cfbe66f28f85edbbe83e09 モデルイベントとは何ですか?

laravelアプリケーションでは、通常、特定のアクションが発生したときにイベントを手動でスケジュールする必要があります。上記の例で見たように、次のコードを使用してイベントをスケジュールできます。

ただし、LaravelでEloquentモデルを使用する場合、一部のイベントが自動的にスケジュールされるため、手動でスケジュールする必要はありません。イベントが発生したときに操作を実行したい場合は、リスナーを定義するだけです。

declare(strict_types=1);

namespace App\Events;

use App\Models\User;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;

final class UserRegistered
{
    use Dispatchable;
    use InteractsWithSockets;
    use SerializesModels;

    public function __construct(public User $user)
    {
        //
    }
}
次のリストには、雄弁さモデルによって自動的にスケジュールされたイベントとトリガーが表示されます。

取得 - データベースから取得。

作成 - モデルの作成。
  • 作成 - モデルが作成されました。
  • 更新 - モデルの更新。
  • 更新 - モデルが更新されました。
  • 保存 - モデルの作成または更新。
  • 保存 - モデルは作成または更新されました。
  • 削除 - モデルの削除。
  • 削除 - モデルが削除されました。
  • ゴミ箱 - モデルは柔らかく削除されています。
  • 強制削除 - モデルの強制削除。
  • 強制販売 - モデルは削除されることを余儀なくされています
  • 復元 - ソフト削除からモデルを回復します。
  • 復元 - モデルはソフト削除から回収されました。
  • 複製 - モデルの複製。
  • 上記のリストでは、たとえば、
  • および
  • など、いくつかのイベント名に気付くかもしれません。操作が発生する前に
  • で終わるイベントは実行され、変更はデータベースに持続します。操作が発生した後に
で終了するイベントは実行され、変更はデータベースに持続します。

creating Laravelアプリケーションでこれらのモデルイベントを使用する方法を見てみましょう。 created ingedモデルイベントを聞いてください

モデルイベントをリッスンする1つの方法は、モデル上の

プロパティを定義することです。 dispatchesEvents

このプロパティを使用すると、イベントが発生したときにスケジュールする必要があるイベントクラスに雄弁なモデルイベントをマッピングできます。これは、他のイベントを処理するのと同じように、リスナーを定義できることを意味します。

より多くのコンテキストを提供するには、例を見てみましょう。 dispatchesEvents

2つのモデルを備えたブログアプリケーションを構築していると仮定します:

。両方のモデルがソフト削除をサポートしていると言えます。新しい

を保存するとき、コンテンツの長さに基づいて記事の読み取り時間を計算します。著者をそっと削除するとき、著者にすべての記事をそっと削除してもらいたいです。

#モデルをセットAppModelsPost AppModelsAuthor以下に示すようにAppModelsPostモデルがある場合があります:

上記のモデルには、

があります

  • dispatchesEventsモデルイベントをdeletedイベントクラスにマッピングするAppEventsAuthorDeletedプロパティを追加しました。これは、モデルが削除された場合、新しいAppEventsAuthorDeletedイベントがスケジュールされることを意味します。このイベントクラスを後で作成します。
  • posts関係を定義します。
  • IlluminateDatabaseEloquentSoftDeletes機能を使用して、モデルでソフト削除が有効になっています。

AppModelsPostモデル:

を作成しましょう
declare(strict_types=1);

namespace App\Events;

use App\Models\User;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;

final class UserRegistered
{
    use Dispatchable;
    use InteractsWithSockets;
    use SerializesModels;

    public function __construct(public User $user)
    {
        //
    }
}
上記のモデルには、

AppModelsPost

    モデルイベントを
  • イベントクラスにマッピングするdispatchesEventsプロパティを追加しました。これは、モデルが作成または更新されたときに、新しいsavingイベントがスケジュールされることを意味します。このイベントクラスを後で作成します。 AppEventsPostSaving AppEventsPostSaving
  • 関係を定義します。
  • author
  • 機能を使用して、モデルでソフト削除が有効になっています。
  • IlluminateDatabaseEloquentSoftDeletes
  • モデルの準備が整っているので、
および

イベントクラスを作成しましょう。 AppEventsAuthorDeleted AppEventsPostSaving#createイベントクラス

新しい記事を保存するときにスケジュールされるイベントクラスを作成します:

上記のコードでは、コンストラクターのモデルインスタンスを受け入れるAppEventsPostSavingイベントクラスを見ることができます。このイベントクラスは、保存されている記事インスタンスを保存するためのシンプルなコンテナです。

同様に、著者を削除するときにスケジュールされるイベントクラスを作成できます。
use App\Events\UserRegistered;
use App\Models\User;

$user = User::create([
    'name' => 'Eric Barnes',
    'email' => 'eric@example.com',
]);

UserRegistered::dispatch($user);
上記のクラスでは、コンストラクターが

モデルインスタンスを受け入れることがわかります。 AppEventsPostSaving AppModelsPost今では、リスナーを作成し続けることができます。

#createリスナーAppEventsAuthorDeleted

最初に、記事の読み取り時間の推定を計算するために使用できるリスナーを作成しましょう。
declare(strict_types=1);

namespace App\Listeners;

use App\Events\UserRegistered;
use App\Notifications\WelcomeNotification;
use Illuminate\Support\Facades\Mail;

final readonly class SendWelcomeEmail
{
    public function handle(UserRegistered $event): void
    {
        $event->user->notify(new WelcomeNotification());
    }
}

新しいAppEventsAuthorDeletedリスナークラスを作成します:AppModelsAuthor

上記のコードでわかるように、

1つのメソッドのみがあります。これは、

イベントをスケジュールするときに自動的に呼び出されるメソッドです。保存されている記事を含む

イベントクラスのインスタンスを受け入れます。

メソッドでは、簡単な式を使用して、記事の読み取り時間を計算します。この例では、平均読み取り速度は毎分265ワードであると想定しています。読み取り時間を秒単位で計算し、記事モデルに

属性を設定します。 AppListenersCalculateReadTimeこのリスナーは、

モデルイベントがトリガーされたときに呼び出されるため、これは、作成または更新する前に記事がデータベースに持続するたびにsaving属性が計算されることを意味します。 read_time_in_seconds

著者を柔らかく削除するときに、関連するすべての記事を柔らかく削除するリスナーを作成することもできます。

新しい

リスナークラスを作成できます:AppListenersSoftDeleteAuthorRelationships

上記のリスナーでは、
declare(strict_types=1);

namespace App\Events;

use App\Models\User;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;

final class UserRegistered
{
    use Dispatchable;
    use InteractsWithSockets;
    use SerializesModels;

    public function __construct(public User $user)
    {
        //
    }
}
メソッドは

イベントクラスのインスタンスを受け入れます。このイベントクラスには、削除されている著者が含まれています。次に、handle関係を使用して、著者の記事を削除します。 AppEventsAuthorDeleted したがって、postsdeleteモデルがそっと削除されると、すべての著者の記事もゆっくりと削除されます。

ちなみに

これを達成するために、より強力で再利用可能なソリューションを使用したいと思うかもしれないことは注目に値します。しかし、この記事の目的のために、私たちはそれをシンプルに保ちます。 AppModelsAuthor

閉鎖を使用してモデルイベントを聞く

使用できるもう1つの方法は、リスナーをモデル自体の閉鎖として定義することです。


著者を柔らかく削除したときに、ソフト削除記事の例を見てみましょう。モデルのモデルをリストに供給するように

モデルを更新することができます。

上記のモデルでは、モデルのAppModelsAuthorメソッドでリスナーを定義していることがわかります。 deletedモデルイベントを聴きたいので、

を使用しました。同様に、
use App\Events\UserRegistered;
use App\Models\User;

$user = User::create([
    'name' => 'Eric Barnes',
    'email' => 'eric@example.com',
]);

UserRegistered::dispatch($user);
モデルイベントのリスナーを作成したい場合は、

などを使用できます。 bootedメソッドは、削除されているdeletedを受信する閉鎖を受け入れます。この閉鎖は、モデルが削除されたときに実行されるため、すべての著者記事が削除されます。 self::deleted createdモデルクラスを開くときにオブザーバーを登録するかどうかをすぐに確認できるため、リスナーロジックを定義するこの方法が本当に好きです。したがって、ロジックはまだ別のファイルに「非表示」されていますが、モデルの少なくとも1つのイベントについてリスナーを登録していることがわかります。ただし、これらの閉鎖のコードがより複雑になると、ロジックを別のリスナークラスに抽出する価値があります。 self::created self::deleted便利なトリックは、AppModelsAuthor関数を使用してクロージャーをキューにすることもできることです。これは、リスナーのコードがキューに押し込まれ、同じリクエストライフサイクルではなく、バックグラウンドで実行されることを意味します。次のように、リスナーをqueuableに更新できます:

上記の例で見たように、

関数で閉鎖を包みます。 IlluminateEventsqueueableオブザーバーを使用してモデルイベントをリッスンします


モデルイベントを聞くために取ることができるもう1つの方法は、モデルオブザーバーを使用することです。モデルオブザーバーを使用すると、1つのクラスでモデルのすべてのリスナーを定義できます。

通常、それらは

ディレクトリに存在するクラスであり、聴きたいモデルイベントに対応するメソッドがあります。たとえば、app/Observersモデルイベントを聞きたい場合は、オブザーバークラスでdeletedメソッドを定義します。 deletedモデルイベントを聞きたい場合は、オブザーバークラスなどでcreatedメソッドを定義します。 created

モデルイベントをリスニングするモデルのモデルオブザーバーを作成する方法を見てみましょう。 AppModelsAuthor 上記のコードでわかるように、deleted

メソッドを使用してオブザーバーを作成します。このメソッドは、削除されている
declare(strict_types=1);

namespace App\Events;

use App\Models\User;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;

final class UserRegistered
{
    use Dispatchable;
    use InteractsWithSockets;
    use SerializesModels;

    public function __construct(public User $user)
    {
        //
    }
}
モデルのインスタンスを受け入れます。次に、

関係を使用して、著者の記事を削除します。 deleted たとえば、AppModelsAuthorモデルイベントのリスナーも定義する必要があるとします。このようなオブザーバーを更新することができます:posts delete

メソッドを実行するには、Laravelに使用するように指示する必要があります。これを行うには、created属性を使用できます。これにより、オブザーバーをモデルに関連付けることができます。これは、updated属性を使用してグローバルクエリスコープを登録する方法と同様に(Laravelでクエリスコープをマスターする方法を理解することに示されています)。このような

モデルを更新して、オブザーバーを使用できます。
use App\Events\UserRegistered;
use App\Models\User;

$user = User::create([
    'name' => 'Eric Barnes',
    'email' => 'eric@example.com',
]);

UserRegistered::dispatch($user);

私は、リスナーロジックを定義するこの方法が本当に好きです。モデルクラスを開くときにオブザーバーを登録するかどうかをすぐに確認できるからです。したがって、ロジックはまだ別のファイルに「非表示」されていますが、モデルの少なくとも1つのイベントについてリスナーを登録していることがわかります。 AppObserversAuthorObserver #[IlluminateDatabaseEloquentAttributesObservedBy]モデルイベントをテストします#[ScopedBy] AppModelsAuthor

使用するモデルイベント方法に関係なく、ロジックが期待どおりに機能することを確認するために、いくつかのテストを作成することができます。
declare(strict_types=1);

namespace App\Listeners;

use App\Events\UserRegistered;
use App\Notifications\WelcomeNotification;
use Illuminate\Support\Facades\Mail;

final readonly class SendWelcomeEmail
{
    public function handle(UserRegistered $event): void
    {
        $event->user->notify(new WelcomeNotification());
    }
}

上記の例で作成したモデルイベントをテストする方法を見てみましょう。

最初にテストを書き、著者が柔らかく削除されたときに著者の記事が柔らかく削除されるようにします。テストは次のようになるかもしれません:


上記のテストでは、その著者の新しい著者と記事を作成しています。その後、著者をそっと削除し、著者と記事の両方がそっと削除されていると主張しました。

これは非常にシンプルだが効果的なテストであり、ロジックが期待どおりに機能することを確認するために使用できます。このテストの利点は、この記事で説明する各方法で動作することです。したがって、この記事で説明した方法のいずれかを切り替えた場合、テストに合格するはずです。

同様に、いくつかのテストを作成して、記事の読み取り時間が作成または更新時に計算されるようにすることができます。テストは次のようになるかもしれません:

declare(strict_types=1);

namespace App\Events;

use App\Models\User;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;

final class UserRegistered
{
    use Dispatchable;
    use InteractsWithSockets;
    use SerializesModels;

    public function __construct(public User $user)
    {
        //
    }
}

2つのテストがあります:

  • 最初のテストにより、記事の読み取り時間が作成時に計算されるようにします。
  • 2番目のテストにより、記事の読み取り時間が計算されることを保証します。
モデルイベントを使用する場合の予防策 モデルイベントは非常に便利ですが、使用する際に注意すべき問題がいくつかあります。

モデルイベントは、雄弁さモデルのみからスケジュールされます。これは、

ファサードを使用してデータベース内のモデルの基礎となるデータと対話する場合、そのイベントはスケジュールされないことを意味します。

たとえば、IlluminateSupportFacadesDB簡単な例を見てみましょう。

ファサードを使用して著者を削除します。

上記のコードを実行すると、予想どおりデータベースから作成者が削除されます。ただし、IlluminateSupportFacadesDBおよび

モデルイベントはスケジュールされていません。したがって、著者を削除するときにこれらのモデルイベントのリスナーを定義する場合、それらは実行されません。
use App\Events\UserRegistered;
use App\Models\User;

$user = User::create([
    'name' => 'Eric Barnes',
    'email' => 'eric@example.com',
]);

UserRegistered::dispatch($user);
同様に、モデルの更新または削除にEloquentを使用して使用する場合、影響を受けるモデルのために

deletingdeleted、および

モデルイベントはスケジュールされていません。これは、イベントがモデル自体からスケジュールされるためです。ただし、バッチの更新と削除が更新された場合、モデルは実際にデータベースから取得されないため、イベントはスケジュールされません。

たとえば、saved次のコードを使用して著者を削除するとします。 updated deleting deletedメソッドはクエリビルダーで直接呼び出されるため、

および

モデルイベントはその著者にはスケジュールされていません。

declare(strict_types=1);

namespace App\Listeners;

use App\Events\UserRegistered;
use App\Notifications\WelcomeNotification;
use Illuminate\Support\Facades\Mail;

final readonly class SendWelcomeEmail
{
    public function handle(UserRegistered $event): void
    {
        $event->user->notify(new WelcomeNotification());
    }
}

を考慮する代替方法 delete deletingプロジェクトでモデルイベントを使用するのが好きです。モデルに影響を与えるコードをあまり制御できないときに、コードを切り離し、ロジックを自動的に実行できるようにする良い方法として機能します。たとえば、Laravel Novaで著者を削除した場合、著者を削除するときにロジックを実行できます。 deleted

ただし、異なる方法を使用するかを検討する時期を知ることが重要です。

これを説明するために、モデルイベントの使用を避けたい基本的な例を見てみましょう。新しい投稿を作成するときに以下を実行したいと仮定して、以前の簡単なブログアプリケーションの例を拡張します。


記事の読み取り時間を計算します。

API呼び出しをX/Twitterに送信して、記事を共有します。

プラットフォーム上のすべてのサブスクライバーに通知を送信します。

    したがって、新しい
  • インスタンスが作成されるたびに実行される3つの独立したリスナー(各タスクに1つ)を作成する場合があります。
  • しかし、以前のテストの1つを確認しましょう:
declare(strict_types=1);

namespace App\Events;

use App\Models\User;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;

final class UserRegistered
{
    use Dispatchable;
    use InteractsWithSockets;
    use SerializesModels;

    public function __construct(public User $user)
    {
        //
    }
}
上記のテストを実行すると、

モデルが工場を介して作成されたときに、これら3つの操作もトリガーされます。もちろん、読み取り時間の計算は二次的なタスクであるため、それほど重要ではありません。ただし、テスト中にAPI呼び出しや通知を送信しようとはしません。これらは予期しない副作用です。テストを書いている開発者がこれらの副作用を認識していない場合、これらの操作が発生する理由を追跡することは困難かもしれません。 AppModelsPost また、リスナーにテスト固有のロジックを作成することを避けたいと考えています。これにより、これらの操作がテスト中に実行されないようにします。これにより、アプリケーションコードがより複雑で維持が難しくなります。

これは、自動モデルイベントに依存するのではなく、より明確なアプローチを検討したい場合の1つです。

1つの方法は、

作成コードをサービスまたはアクションクラスに抽出することです。たとえば、単純なサービスクラスは次のようになる場合があります:

AppModelsPost 上記のクラスでは、読み取り時間を計算し、通知を送信し、Twitterに投稿するコードを手動で呼び出しています。これは、これらの操作がいつ実行されるかをより適切に制御できることを意味します。また、これらの方法をテストで簡単にock笑して、実行しないようにすることもできます。必要に応じて、これらの操作をキューすることができます(この場合、おそらくそうするでしょう)。

したがって、これらの操作のモデルイベントとリスナーを削除することができます。これは、アプリケーションコードでこの新しい
use App\Events\UserRegistered;
use App\Models\User;

$user = User::create([
    'name' => 'Eric Barnes',
    'email' => 'eric@example.com',
]);

UserRegistered::dispatch($user);
クラスを使用し、テストコードでモデルファクトリを安全に使用できることを意味します。

これを行うことの追加の利点は、コードを理解しやすくすることです。簡単に述べたように、イベントやリスナーを使用するという一般的な批判は、予期しない場所でビジネスロジックを隠す可能性があるということです。したがって、新しい開発者がチームに参加した場合、モデルイベントによってトリガーされている場合、一部の操作が発生する場所または理由がわからない場合があります。

ただし、このようなロジックにイベントやリスナーを使用したい場合は、より明確なアプローチを使用することを検討する場合があります。たとえば、サービスクラスからイベントをスケジュールして、リスナーをトリガーできます。このようにして、イベントやリスナーのデカップリングの利点を引き続き使用できますが、イベントがスケジュールされる時期をよりよく制御できます。 AppServicesPostService たとえば、

イベントをスケジュールするために上記の

メソッドを更新できます。

上記の方法を使用することにより、APIリクエストを行い、Twitterに通知を送信するために別のリスナーを使用することができます。しかし、これらの操作がいつ実行されるかをより適切に制御できるため、モデルファクトリを使用してテストするときは実行されません。

これらの方法のいずれかを使用することを決定したときに黄金律はありません。それはすべて、あなた、あなたのチーム、そしてあなたが構築している機能に依存します。しかし、私は次の親指の規則に従う傾向があります:AppServicesPostService

  • リスナーの操作がモデルにわずかな変更のみを行った場合は、モデルイベントの使用を検討してください。例:スラグを生成し、読み取り時間などを計算します。
  • 操作が別のモデルに影響を与える場合(自動的に作成、更新、削除されているかどうかにかかわらず)、より明確でモデルイベントを使用しません。
  • 操作が外部プロセス(API呼び出し、ファイル処理、トリガー通知、キュームジョブ)で動作する場合、モデルイベントを使用しないことは明らかです。
モデルイベントを使用することの長所と短所

この記事で紹介したものをすばやく要約するために、モデルイベントを使用することの利点と短所のいくつかを次に示します。
#pros

コードを切り離すことをお勧めします。

    モデルの作成/更新/削除の場所に関係なく、アクションを自動的にトリガーできます。たとえば、モデルがLaravel Novaで作成された場合、ビジネスロジックをトリガーできます。
  • モデルを作成/更新/削除するたびに、イベントをスケジュールすることを忘れないでください。
  • #disadvantages

予期しない副作用を引き起こす可能性があります。リスナーをトリガーすることなく、モデルを作成/更新/削除することもできますが、これは予期しない動作につながる可能性があります。これは、テストを書くときに特に問題があります。

    ビジネスロジックは、追跡が難しい予期しない場所に隠されている場合があります。これにより、コードの流れがより困難になります。
  • 結論

この記事が、モデルイベントが何であるか、それらを使用するさまざまな方法の概要を提供することを願っています。また、モデルイベントコードをテストする方法と、使用する際に注意するいくつかの問題を示す必要があります。


Laravelアプリケーションでモデルイベントを使用するのに十分な自信があるはずです。

以上がLaravelのモデルイベントのガイドの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。