ホームページ >バックエンド開発 >PHPチュートリアル >Laravelのセッションに深く飛び込みます

Laravelのセッションに深く飛び込みます

Karen Carpenter
Karen Carpenterオリジナル
2025-03-06 02:32:13364ブラウズ

A Deep Dive into Sessions in Laravel

Laravelアプリケーションを構築する場合、ある時点でセッションを処理する必要があることをほぼ確実にします。それらはWeb開発の基本的な部分です。

この記事では、セッションが何であるか、Laravelでどのように機能するか、Laravelアプリケーションでどのように使用するかをすばやく説明します。

その後、さらに一歩進んで、「セッションクラス」を使用してセッションと対話する方法に飛び込み、Laravelアプリケーションを扱うときによく遭遇する一般的な落とし穴を避けます。

最後に、Laravelでセッションデータをテストする方法を学びます。

会話とは何ですか?


デフォルトでは、Webアプリケーションはステートレスです。つまり、リクエストは通常​​お互いを認識していません。したがって、リクエスト間でデータを保存する方法が必要です。たとえば、ユーザーがWebサイトにログインする場合、訪問中にログインしていることを覚えておく必要があります。これは会話が始まるところです。

要するに、セッションは複数のリクエスト間でデータを維持するための安全な方法です。

セッションデータを使用して、次のコンテンツを保存できます。

ユーザー認証ステータス。

    別のページでアクセス可能な一時的なデータ。
  • ユーザーに表示されるフラッシュメッセージ。
  • セッションデータは、次のようなさまざまな場所に保存できます。
  • cookie

データベース

    キャッシュストレージ(例:redis)
  • セッションはLaravelでどのように機能しますか?
  • セッションが何であるかを理解するために、それらがLaravelでどのように機能するかを見てみましょう。

以下は、Laravelアプリケーションのセッションで見つけるかもしれないいくつかのサンプルデータです。


各キーが表すものを分解しましょう。

次のキーは、Laravelフレームワーク自体によって追加されています:

CSRF攻撃を防ぐために、
<code>[
  '_token' => 'bKmSfoegonZLeIe8B6TWvSm1dKwftKsvcT40xaaW'
  '_previous' => [
    'url' => 'https://my-app.com/users'
  ]
  '_flash' => [
    'old' => [
        'success',
    ],
    'new' => []
  ]
  'success' => 'User created successfully.'
  'current_team_id' => 123
]</code>

値を使用します。

値は、以前に要求されたURLを保存するために使用されます。
  • _token値は、Flashセッションデータのキーを前のリクエストに保存するために使用されます。この場合、それは前のリクエストで
  • 値がフラッシュされたことを意味します。
  • _previous.url
  • 値は、現在のリクエストにフラッシュセッションデータのキーを保存するために使用されます。
  • _flash.old success次のキーが私によって追加されています:
  • _flash.new
  • 値は、ユーザーに表示される可能性のある成功メッセージを保存するために使用されます。

値は、ユーザーが表示している現在のチームのIDを保存するために使用されます。
  • successデフォルトでは、Laravelは次のセッションドライバーをサポートしています:
    • cookie - セッションデータは、安全で暗号化されたCookieに保存されます。
    • database - セッションはデータベースに保存されます(たとえば、mysql、postgresql、sqlite)。
    • memcached / redis - セッションデータは、これらの高速キャッシュストレージに保存されます。
    • dynamodb - セッションデータはAWS dynamodbに保存されます。
    • file - セッションデータはstorage/framework/sessionsに保存されます。
    • array - セッションデータはメモリのPHPアレイに保存され、持続しません。

    これらのドライバーの一部には、セットアップ要件があります。したがって、それらを使用する前に、Laravelドキュメントを確認して、それらをセットアップする方法を学習してください。

    Laravelのセッションを使用


    Laravelはセッションを使用して非常にシンプルにします。ドキュメントでは、セッションとうまくやり取りする方法を説明しています。しかし、基本を簡単に見てみましょう。

    この例では、複数のページにまたがるステップバイステップのウィザードを構築していると仮定します。現在のステップと各ステップに入力されたデータをセッションに保存します。このようにして、ユーザーがすべての手順を完了すると、ウィザードの最後に提出されたすべてのデータを読み取ることができます。

    例をシンプルにするには、session()ヘルパー関数も使用します。ただし、後でSessionファサードまたはリクエストクラスを使用してセッションデータにアクセスします。

    #セッション

    のデータを読み取ります メソッドを使用できます。 get 上記のコードを実行すると、セッションに保存されている値がキーとして返されます。キーがセッションに保存された値を持っていない場合、
    <code>[
      '_token' => 'bKmSfoegonZLeIe8B6TWvSm1dKwftKsvcT40xaaW'
      '_previous' => [
        'url' => 'https://my-app.com/users'
      ]
      '_flash' => [
        'old' => [
            'success',
        ],
        'new' => []
      ]
      'success' => 'User created successfully.'
      'current_team_id' => 123
    ]</code>
    を返します。

    wizard:current_stepこのメソッドでは、デフォルト値を定義することもできます。これは、キーが存在しない場合はnull

    上記のコードを実行すると、セッションに保存されている値が

    キーとして返されます。キーがセッションに保存された値を持っていない場合、

    を返します。
    <code>$currentStep = session()->get(key: 'wizard:current_step');</code>

    セッションのデータを読み取って同時に削除する場合もあります(したがって、再度アクセスできません)。これにはwizard:current_step関数を使用できます 1 上記のコードを実行すると、セッションに保存されている値が

    キーとして返され、セッションから削除されます。

    pull#セッションにデータを書き込みます

    <code>$currentStep = session()->get(key: 'wizard:current_step', default: 1);</code>
    セッションにデータを記述するには、以下に示すように

    関数を使用できます。 wizard:current_step 上記のコードを実行すると、

    キーの値として配列(2番目のパラメーターに渡されます)が保存されます。

    #セッションの配列にデータを押します

    put同様に、

    メソッドを使用して、セッションの配列にデータをプッシュすることもできます。
    <code>$currentStep = session()->pull(key: 'wizard:current_step');</code>

    wizard:step_one:form_dataキーに次のデータがあると仮定します。

    上記のコード(呼び出し

    メソッド)はセッション値を更新します:push

    <code>[
      '_token' => 'bKmSfoegonZLeIe8B6TWvSm1dKwftKsvcT40xaaW'
      '_previous' => [
        'url' => 'https://my-app.com/users'
      ]
      '_flash' => [
        'old' => [
            'success',
        ],
        'new' => []
      ]
      'success' => 'User created successfully.'
      'current_team_id' => 123
    ]</code>
    セッションにwizard:step_one:form_data:languages値がまだ存在しない場合は、pushを使用してセッションキーを作成し、渡された値を含む配列に値を設定します。

    #セッションでデータを増やして減少させます

    Laravelは、セッションで値を増やして減らすことができる便利なヘルパーメソッドも提供します。

    このようなセッションの値を増やすことができます:

    <code>$currentStep = session()->get(key: 'wizard:current_step');</code>
    上記のコードを実行すると、

    セッション値が3の場合、4に増加します。 wizard:current_step

    このようなセッションの値を減らすこともできます:

    <code>$currentStep = session()->get(key: 'wizard:current_step', default: 1);</code>
    セッションに値がまだ存在しない場合、それらは0として扱われます。したがって、空のセッション値で

    を呼び出すと、値が1に設定されます。空のセッション値でincrementを呼び出してください。値を-1に設定します。 decrement

    両方の方法で、数を増やすか減少させるかを指定できます。

    #セッション
    <code>$currentStep = session()->pull(key: 'wizard:current_step');</code>
    からデータを削除します

    メソッドを使用してセッションからデータを削除することもできます。

    上記のコードを実行すると、セッションからforgetキーに属するデータが削除されます。

    <code>session()->put(
        key: 'wizard:step_one:form_data',
        value: [
            'name' => 'Ash Allen',
            'email' => 'ash@example.com',
        ],
    );</code>
    複数のキーを一度に削除する場合は、キー配列を

    関数に渡すことができます:wizard:current_step

    または、セッションからすべてのデータを削除する場合は、forget関数を使用できます。

    <code>session()->push(
        key: 'wizard:step_one:form_data:languages',
        value: 'javascript',
    );</code>
    #セッションにデータがあるかどうかを確認

    また、Laravelは、セッションにデータが存在するかどうかを確認するための便利なヘルパー関数を提供します。 flush

    <code>[
        `php`,
    ]</code>
    メソッドを使用して、セッションにキーがあるかどうか、およびその値が

    にないかどうかを確認できます。

    値が存在していて

    ではない場合、上記のコードはhasに戻ります。値がnullまたはキーが存在しない場合、

    に戻ります。
    <code>[
        `php`,
        `javascript`,
    ]</code>

    同様に、nullメソッドを使用して、キーがセッションに存在するかどうかを確認することもできます(値がnullであることに関係なく)true null falseセッションがまったく存在しないかどうかを確認することもできます:

    exists#session

    へのフラッシュデータ
    <code>session()->increment(key: 'wizard:current_step');</code>
    セッションでいくつかのデータを保持することがありますが、次のリクエストのためにのみです。たとえば、ユーザーがフォームを提出した後、ユーザーに成功通知を表示することをお勧めします。

    これを行うには、

    メソッド:
    <code>session()->decrement(key: 'wizard:current_step');</code>
    を使用できます

    上記のコードを実行する場合は、次のリクエストで、セッションの値(

    のようなものを使用)の値を表示できます。次に、次のリクエストで利用できないように削除します。

    フラッシュデータ(前のリクエストに追加)がある場合があり、次のリクエストに保持したい場合があります。 flash

    <code>session()->increment(key: 'wizard:current_step', amount: 2);
    session()->decrement(key: 'wizard:current_step', amount: 2);</code>
    メソッドを使用してすべてのフラッシュデータを更新できます:

    session()->get('success')

    または、フラッシュデータを保持するだけの場合は、

    メソッドを使用できます:

    <code>[
      '_token' => 'bKmSfoegonZLeIe8B6TWvSm1dKwftKsvcT40xaaW'
      '_previous' => [
        'url' => 'https://my-app.com/users'
      ]
      '_flash' => [
        'old' => [
            'success',
        ],
        'new' => []
      ]
      'success' => 'User created successfully.'
      'current_team_id' => 123
    ]</code>
    上記のコードを実行すると、

    およびsuccessフラッシュセッション値が保持されますが、次のリクエストのために他のフラッシュデータを削除します。 error

    機能、ファサード、またはリクエストクラスをヘルプしますか?


    これまでのところ、例では

    ヘルパー関数のみを使用しています。 session()

    ただし、

    ファサードまたはIlluminateSupportFacadesSessionクラスを使用してセッションと対話することもできます。 IlluminateHttpRequest

    どの方法を使用しても、この記事で前述したのと同じ方法を使用できます。これらの方法は、セッションデータと対話するさまざまな方法です。

    ファサードを使用するには、次のような方法を呼び出すことができます。 Session 代わりに、コントローラーメソッドに注入された

    メソッドを呼び出すことで、セッションにアクセスできます。次のコントローラー方法があるとします:
    <code>$currentStep = session()->get(key: 'wizard:current_step');</code>

    IlluminateHttpRequest各方法は完全に効果的であるため、あなたとあなたのチームがどちらを好むかを決定できます。 session

    さらに一歩進んでください
    <code>$currentStep = session()->get(key: 'wizard:current_step', default: 1);</code>

    小規模なプロジェクトでは、前述の方法を使用してセッションと対話してもまったく問題ありません。ただし、Laravelプロジェクトが成長するにつれて、エラーを引き起こし、コードの維持をより困難にする可能性のある問題に遭遇する可能性があります。

    それで、潜在的な落とし穴とそれらを回避する方法をカバーします。
    私が見る共通のtrap(私は自分で何度もそれを経験しました)は、セッションキーのタイプミスです。

    セッションの現在のステップを保存したいと仮定して、ウィザードの例に固執します。したがって、私たちのコードは次のようになるかもしれません:

    その後、コードベースのさまざまな部分で、セッションの現在のステップを読みたいと思うかもしれません。

    私が今した間違いを見ましたか?私は誤って

    キーの代わりに
    <code>$currentStep = session()->pull(key: 'wizard:current_step');</code>
    キーを読んでみました。

    これは簡単な例ですが、大規模なコードベースでは、そのような間違いを犯すのは簡単です。これらの明らかな間違いは、見つけるのが最も難しいかもしれません。
    <code>session()->put(
        key: 'wizard:step_one:form_data',
        value: [
            'name' => 'Ash Allen',
            'email' => 'ash@example.com',
        ],
    );</code>
    したがって、これらのタイプミスを回避する便利な方法は、定数または方法を使用してセッションキーを生成することです。

    たとえば、セッションキーが静的である場合、次のように定数(おそらくセッションクラスで説明します)を定義できます。 wizard:step これは、コードベースで使用される生文字列の数を減らすことを意味し、タイプミスの数を減らすのに役立ちます。 wizard:current_step

    ただし、セッションキーを動的に生成する必要がある場合があります。たとえば、チームIDフィールドを含める

    キーが必要だとします。次のようにキーを生成する方法を作成できます。

    上記のコードで見ることができるように、

    セッションキーを動的に生成して、異なる方法で使用できるようにしています。たとえば、ID 1のチームの現在のステップを見つけようとすると、キーは

    になります。

    #セッションキー競合

    しばらくの間存在していたプロジェクトを扱うときに見られる別のtrapは、セッションの重要な競合です。

    たとえば、数年前に新しいユーザーアカウントを作成するためのウィザードを作成したと想像してください。したがって、このようなセッションデータを保存することができます:

    <code>[
      '_token' => 'bKmSfoegonZLeIe8B6TWvSm1dKwftKsvcT40xaaW'
      '_previous' => [
        'url' => 'https://my-app.com/users'
      ]
      '_flash' => [
        'old' => [
            'success',
        ],
        'new' => []
      ]
      'success' => 'User created successfully.'
      'current_team_id' => 123
    ]</code>
    あなたは今、魔法使いを備えた新しい機能を構築するために割り当てられており、あなたが使用した古いウィザードと命名規則を完全に忘れてしまいました。新しいウィザードに誤って同じキーを使用して、データの競合を引き起こし、潜在的なエラーを導入することができます。

    これを避けるために、セッションキーのプレフィックスとして関数名を使用するのが好きです。したがって、新しいユーザーを作成するためにウィザードデータを保存するために、次のキーがある場合があります。

    • new_user_wizard:current_step
    • new_user_wizard:step_one:form_data
    • 待って... new_user_wizard:step_two:form_data
    • その後、新しいチームを作成するための新しいウィザードで、次のキーがあるかもしれません。

    • new_team_wizard:current_step
    • new_team_wizard:step_one:form_data
    • 待って...
    • new_team_wizard:step_two:form_data この記事の後半で、これらのプレフィックスをセッションクラスに追加する方法について説明します。
    • #不明なデータ型
    このセッション値にデータ型が保存されているものを教えてもらえますか?

    それが

    のインスタンスだと推測した場合、あなたは正しいです。

    話して話しているだけで、セッションからデータを読んだときに、使用しているデータの種類が常にすぐにクリアされるとは限らないことを明確にしたいと思います。最終的には、セッションにデータを書き込むコードを見て、それが何であるかを把握する必要があります。これは気を散らし、時間がかかる可能性があり、エラーにつながる可能性があります。
    <code>$currentStep = session()->get(key: 'wizard:current_step');</code>

    セッションデータを読み取るコードにコメントまたはドキュメントブロックを追加できます。しかし、これは単なるヒントです。コメントが最新の状態に保たれない場合(セッションデータ型が変更された場合)、それは役に立たず、エラーの可能性を高めます。 AppDataTransferObjectsWizardsFormData

    私が使用したいもう1つの方法は、メソッド内のセッションデータを読み取り、メソッドに戻るタイプを追加することです。これにより、使用しているデータ型が正しいことを確認できます。また、IDEとコードを読む人々にも役立ちます。

    たとえば、

    このコードを見てみましょう

    メソッドが

    インスタンスを返すことがわかります。これは、使用しているデータの種類を明確に示しています。次に、このようにコントローラーでこのメソッドを呼び出すことができます:

    <code>$currentStep = session()->get(key: 'wizard:current_step', default: 1);</code>
    #セッションクラスのプロセスセッションデータ

    前のセクションで見たように、Laravelでセッションを使用する場合、いくつかの簡単な(しかし一般的な)落とし穴があります。 stepOneFormData 「セッションクラス」を使用することにより、これらのトラップはそれぞれ回避できます(または少なくとも削減されます)。セッションクラスを使用して、1つの場所で単一の関数に関連するセッションデータ処理ロジックをカプセル化するのが好きです。 AppDataTransferObjectsWizardsFormDataたとえば、

    ユーザーを作成するためのウィザードがあり、チームを作成するための別のウィザードがあるとします。これらの魔法使いのそれぞれのセッションクラスを作成します:

    • AppSessionsUsersNewUserWizardSession
    • AppSessionsTeamsNewTeamWizardSession

    セッションクラスを使用することで、

    を使用できます
    • すべてのキーのプレフィックスとして関数名を自動的に使用します。
    • タイププロンプトとメソッドに戻るタイプを追加します。
    • コードベースで使用される元の文字列の数を減らします。
    • リファクタリングセッションデータ構造を簡単にします。
    • テストセッションデータを簡単にします。
    • 特定の関数のセッションデータを作成するために変更が必要な場合は、どこに行くかを正確に把握します。
    • セッションデータを処理するときにこのクラスベースのアプローチを使用すると、大規模なLaravelプロジェクトを操作するときに無数の時間を節約できます。これは大きな影響を与える可能性のある簡単な方法です。

    前の例では、セッションクラスの使用を既に提案しています。しかし、私がこれらのクラスをどのように構築するのが好きかをもっとよく見てみましょう。

    新しいユーザーウィザードの次のセッションクラスがあるとします。一見、それは少し圧倒されるかもしれませんが、コードを見てそれを分解しましょう:

    上記のクラスでは、最初に

    インスタンスを受け入れるコンストラクターを定義します。これを行うことにより、Laravelは、サービスコンテナから
    <code>[
      '_token' => 'bKmSfoegonZLeIe8B6TWvSm1dKwftKsvcT40xaaW'
      '_previous' => [
        'url' => 'https://my-app.com/users'
      ]
      '_flash' => [
        'old' => [
            'success',
        ],
        'new' => []
      ]
      'success' => 'User created successfully.'
      'current_team_id' => 123
    ]</code>
    クラスを解析するときに、セッションインスタンスを自動的に注入します。後でコントローラーでこれを行う方法をお見せします。

    AppSessionsUsersWizardSession次に、5つの基本的なパブリックメソッドを定義します:IlluminateContractsSessionSession AppSessionsUsersWizardSession

    - ウィザードの現在のステップに戻ります。セットアップステップがない場合、デフォルトは

    です。
    • getCurrentStep - セットアップウィザードの現在のステップ。 1
    • - ウィザードの指定されたステップのフォームデータを設定します。この方法では、段階番号とsetCurrentStepの例が掲載されています。
    • setFormDataForStep - ウィザードの指定されたステップのフォームデータを取得します。このメソッドはステップ番号を取得し、AppDataTransferObjectsWizardsUsersFormDataインスタンスを返します。または、データが存在しない場合。
    • getFormDataForStep - セッションからウィザードに関連するすべてのデータを削除します。ウィザードが完了またはキャンセルされた場合は、この方法を呼び出すことができます。 AppDataTransferObjectsWizardsUsersFormData null
    • すべてのキーがメソッド内で生成されていることに気付いたかもしれません。私はこれを行い、使用される生の文字列の数を減らす(そしてタイプミスの可能性を減らす)ことが好きです。これはまた、特定のキーにアクセスする別の方法を追加したい場合、これを非常に簡単に実行できることを意味します。
    • flushこれらの重要な生成方法を使用することの追加の利点は、競合を回避するためにキーを簡単に接頭することができることです。この例では、すべてのキーのプレフィックスを
    • メソッドを使用して
    に設定します。

    このクラスが設定されたので、コントローラーでどのように対話するかを見てみましょう。

    <code>[
      '_token' => 'bKmSfoegonZLeIe8B6TWvSm1dKwftKsvcT40xaaW'
      '_previous' => [
        'url' => 'https://my-app.com/users'
      ]
      '_flash' => [
        'old' => [
            'success',
        ],
        'new' => []
      ]
      'success' => 'User created successfully.'
      'current_team_id' => 123
    ]</code>
    上記の例では、コントローラーメソッドに

    クラスを挿入します。 Laravelは、セッションインスタンスを自動的に解析します。 AppSessionsUsersWizardSession

    その後、他のクラスと同じようにやり取りすることができます。

    最初は、これは過剰補償のように感じられ、より多くのコードメンテナンスが必要になる場合があります。ただし、プロジェクトが成長するにつれて、型プロンプト、リターンタイプ、主要な生成方法、さらには命名方法(操作をより説明的にする)さえ非常に便利です。

    Laravelのテストセッション


    コードベースの他の部分と同様に、正しいフィールドが読み取りおよび書き込まれていることを確認するために、セッションデータをカバーしていることを確認する必要があります。

    セッションクラスを使用することの大きな利点の1つは、クラス内の各メソッドの集中型ユニットスタイルのテストを簡単に記述できることです。

    たとえば、

    クラスの

    メソッドのテストをいくつか書くことができます。リマインダーとして、メソッドは次のとおりです AppSessionsUsersWizardSession getFormDataForStepここでは、いくつかのシナリオをテストできます:

    <code>$currentStep = session()->get(key: 'wizard:current_step');</code>

    ステップの

    オブジェクトを返します。
    • ステップにフォームデータがない場合は、AppDataTransferObjectsWizardsUsersFormDataを返します。
    • nullテストクラスは次のようになる場合があります:
    上記のテストクラスでは、前述の2つのケースをカバーする2つのテストがあります。

    これらのユニットスタイルのテストは、セッションクラスがセッションデータの読み取りと書き込みのために正しく構成されていることを確認するのに最適です。しかし、彼らは必ずしもあなたが彼らが残りのコードベースで正しく使用されていると信じさせるわけではありません。たとえば、
    <code>$currentStep = session()->get(key: 'wizard:current_step', default: 1);</code>
    を呼び出している可能性があり、

    に電話する必要があります。

    このため、機能テスト(通常はコントローラーのために書くもの)でセッションデータをアステル化することを検討することもできます。 getFormDataForStep(1) たとえば、getFormDataForStep(2)コントローラーに次の基本的な方法があり、ウィザードの次のステップに進むとします。

    上記の方法では、最初にセッションの現在のステップを読みます。次に、セッションの現在のステップのフォームデータを保存します。最後に、現在のステップを増やし、ウィザードの次のステップにリダイレクトします。

    クラスは、フォームデータの検証に責任を負い、
    <code>$currentStep = session()->pull(key: 'wizard:current_step');</code>
    メソッドを呼び出すときに

    インスタンスを返すと想定します。

    また、コントローラーメソッドには、

    ルート(名前AppHttpRequestsUsersWizardNextStepRequest)へのPOSTリクエストを介してアクセスできると仮定します。 toDto AppDataTransferObjectsWizardsUsersFormDataフォームデータがセッションに正しく保存されていることを確認するために、次のテストを作成する場合があります。

    <code>[
      '_token' => 'bKmSfoegonZLeIe8B6TWvSm1dKwftKsvcT40xaaW'
      '_previous' => [
        'url' => 'https://my-app.com/users'
      ]
      '_flash' => [
        'old' => [
            'success',
        ],
        'new' => []
      ]
      'success' => 'User created successfully.'
      'current_team_id' => 123
    ]</code>

    上記のテストでは、何らかの形のデータを使用して、/users/wizard/next-stepルートへのPOSTリクエストを発行しています。 withSessionを使用していることに気付くかもしれません。この方法により、セッションデータを設定して、正しく読み取られていると主張できるようにします。

    次に、ユーザーがウィザードの次のステップにリダイレクトされ、セッションの現在のステップが3に設定されていると主張します。また、ステップ2のフォームデータがセッションに正しく保存されていると主張します。

    テストで見たように、セッションから2つの方法で読みます。

    • メソッドを使用して、セッションデータが正しく設定されているかどうかを確認します。 assertSessionHas
    • ヘルパー関数を使用して、セッションデータを直接読み取ります。 session()
    両方の方法が機能するため、どちらを好むかを決定できます。上記のテストで両方の方法を使用して、複数のオプションがあることを示しました。

    結論


    この記事が、セッションが何であり、それらがLaravelでどのように機能するかをよく理解するのに役立つことを願っています。また、いくつかの一般的な落とし穴を避けるために、クラスベースの方法を使用してセッションデータと対話する方法についていくつかのアイデアを提供することを願っています。

以上がLaravelのセッションに深く飛び込みますの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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