ホームページ バックエンド開発 PHPチュートリアル php_PHP チュートリアルでの foreach の問題の詳細な分析

php_PHP チュートリアルでの foreach の問題の詳細な分析

Jul 21, 2016 pm 03:01 PM
foreach php 序文 導入 深く行く 構造 解析する トラバース 質問

前書き:
foreach 構造は php4 で導入され、配列を走査する簡単な方法です。従来の for ループと比較して、foreach はキーと値のペアをより簡単に取得できます。 php5 より前は、foreach は配列にのみ使用できましたが、php5 以降は、オブジェクトの走査にも使用できるようになりました (詳細については、「オブジェクトの走査」を参照)。この記事では、配列のトラバーサルについてのみ説明します。

foreach は単純ですが、特にコードに参照が含まれる場合、予期しない動作が発生する可能性があります。
foreach の本質をさらに理解するために、いくつかのケースを以下に示します。
質問 1:

コードをコピーします コードは次のとおりです:

$arr = array(1,2,3);
foreach($arr as $k => &$v ) {
v = $v * 2;
}
// 現在 $arr は array(2, 4, 6)
foreach($arr as $k => $v) {
echo "$k", " => ", "$v";
}

簡単に始めましょう。上記のコードを実行してみると、最終的な出力は 0=>2 1=>4 2=> であることがわかります。 4.
なぜ 0=>2 1=>4 2=>6 ではないのでしょうか?
実際、foreach($arr as $k => $v) 構造は、配列の現在の 'key' と現在の 'value' をそれぞれ変数 $k と $v に割り当てる次の操作を暗示していると考えることができます。具体的な展開は次のとおりです:
コードをコピーします コードは次のとおりです:

foreach($arr as $k => $v){
// 前に暗黙的に 2 つの代入演算があります。ユーザーコードが実行される
$ v = currentVal();
$k = currentKey();
//ユーザーコードを実行し続ける
……
}

上記の理論に従って、最初のコードを再分析しますforeach:
最初のループ、$v は参照なので、$v = &$arr[0]、$v=$v*2 は $arr[0]*2 と同等なので、$arr は 2,2 になります。 3
2 番目のループ、$v = &$arr[1]、$arr は 2,4,3 になります
3 番目のループ、$v = &$arr[2]、$arr は 2,4,6 になります
その後、コードが入力されます 2 番目の foreach:
最初のループ、暗黙的な操作 $v=$arr[0] がトリガーされます。これは、この時点では $v がまだ $arr[2] への参照であるためであり、これは $arr[ と同等です。 2] =$arr[0]、$arr は 2,4,2 になります
2 番目のループ、$v=$arr[1]、つまり、$arr[2]=$arr[1]、$arr は 2 になります, 4,4
3回目のループ、$v=$arr[2]、つまり$arr[2]=$arr[2]、$arrが2,4,4
となりOK、解析は完了です。
同様の問題を解決するにはどうすればよいですか? PHP マニュアルには注意事項があります:
警告: 配列の最後の要素の $value 参照は、foreach ループの後も保持されます。 unset() を使用して破棄することをお勧めします。
コードをコピーします コードは次のとおりです:

$arr = array(1,2,3);
foreach($arr as $k => &$v) {
$v = $v * 2;
}
unset($v);
foreach($arr as $k => $v) {
echo "$k", " => ", "$v";
}
// Output 0=>2 1=>4 2=>6

この質問から、参照には副作用が伴う可能性が高いことがわかります。意図しない変更によって配列の内容が変更されることを避ける場合は、時間内にこれらの参照の設定を解除することをお勧めします。
質問 2:
コードをコピーします コードは次のとおりです:

$arr = array('a','b','c');
foreach($arr as $k => $ v) {
echo key($arr), "=>", current($arr);
}
// print 1=>b 1=>b 1=>b

この問題はもっと奇妙です。マニュアルによると、keyとcurrentは配列内の現在の要素のキーの値です。
それでは、なぜ key($arr) が常に 1 で、current($arr) が常に b なのか?
まず vld を使用して、コンパイルされたオペコードを表示します。

配列 (' を表す 3 行目の ASSIGN 命令から開始します) a','b','c') は $arr に割り当てられます。
$arr は CV、array('a','b','c') は TMP であるため、見つかった ASSIGN 命令によって実際に実行される関数は ZEND_ASSIGN_SPEC_CV_TMP_HANDLER になります。ここで注意しなければならないのは、CV は PHP5.1 以降に追加された変数キャッシュであり、zval** を保存するために配列を使用します。キャッシュされた変数を再度使用する場合は、アクティブなシンボル テーブルを検索する必要はありません。配列からCVを取得するため、配列のアクセス速度がハッシュテーブルよりもはるかに速いため効率が向上します。
コードをコピーします コードは次のとおりです:

static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
zend_op *opline = EX(opline);
zend_free_op free_op2;
zval *value = _get_zval_ptr_tmp(& opline->op2 、EX(Ts)、&free_op2 TSRMLS_CC);

/ / CV 配列に $arr** ポインターを作成します
zval **variable_ptr_ptr = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_W TSRMLS_CC);
if (IS_CV == IS_VAR && !variable_ptr_ptr) {

}
else {
--'Assign-array------- value = zend_assign_to_variable(variable_ptr_ptr, value, 1 TSRMLS_CC); AI_SET_PTR(EX_T(opline->result .u.var).var, value);
PZVAL_LOCK(value);
}
}
ZEND_VM_NEXT_OPCODE();
}ASSIGN 命令が完了すると、zval** ポインタが CV 配列に追加され、ポインタは実際の配列を指します。これは、$arr がCVによってキャッシュされます。


次に、配列のループ操作を実行します。それに対応する実行関数は

です。コードをコピーします。

static int ZEND_ファストコールZEND_FE_RESET_SPEC _CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
… RMLS_CC);
… … } ... / // 配列へのポインタを ZEND_EXEC に保存UTE_DATA- & GT; (TSはコードの実行期間のTEMP_VARIABLEで使用されます) AI_SET_PTR (ex_t (OPLINE- & GT; Result.u.var) .var .end_hash_internal_pointer_reset(fe_ht) ; ..var).fe.fe_pos は、配列の内部ポインターを保存するために使用されます
zend_hash_get_pointer(fe_ht, &EX_T(opline- >result.u.var).fe.fe_pos);
zend_execute_data->Ts:

•EX_T(opline->result.u.var).var ---- 配列へのポインタ
•に格納されているポインタEX_T(opline->result.u.var).fe. fe_pos ---- 配列の内部要素へのポインタ

FE_RESET 命令の実行後のメモリ内の実際の状況は次のとおりです。



次に、引き続き FE_FETCH を見ていきます。対応する実行関数は ZEND_FE_FETCH_SPEC_VAR_HANDLER です:



コードをコピーします

コードは次のとおりです:

Tataticint zend_fastcall zend_fe_fetch_spec_var_handler(zend_opcode_handler_args)
{
zend_op *opline = ex(opline); * array = EX_T(opline->op1.u.var).var.ptr; ……

switch (zend_iterator_unwrap(array, &iter TSRMLS_CC)) {
デフォルト:
case ZEND_ITER_INVALID:
……
case ZEND_ITER_PLAIN_OBJECT: { // FE_RESET 命令では、配列の内部要素へのポインタが EX_T(opline->op1.u.var) に保存されます
ここでポインターを取得します
zend_hash_set_pointer(fe_ht, &EX_T( opline->op1.u.var).fe.fe_pos); If (zend_hash_get_current_data(fe_ht, (void **) &value)==FAILURE) {
key_type = zend_hash_get_current_key_ex(fe_ht, &str_key, &str_key_len, &int_key, 1, NULL );
移動されたポインタは EX_T(opline->op1.u .var).fe.fe_pos
zend_hash_get_pointer(fe_ht, &EX_T(opline->op1.u.var).fe.fe_pos に保存されます); ……
}

……
}


FE_FETCH の実装に基づいて、foreach($arr as $k => $v) が何をするのかを大まかに理解しました。 zend_execute_data->Ts のポインタに基づいて配列要素を取得します。取得が成功すると、ポインタを次の位置に移動して再度保存します。




簡単に言えば、最初のループで配列の内部ポインタが FE_FETCH の 2 番目の要素に移動されているため、foreach 内で key($arr) と current($arr) が呼び出されるとき、実際に取得されるのは 1 と ' b'.

では、なぜ1=>bが3回出力されるのでしょうか?

引き続き、9 行目と 13 行目の SEND_REF 命令を見てみましょう。これは、$arr パラメーターをスタックにプッシュすることを意味します。次に、通常は DO_FCALL 命令を使用してキー関数と現在の関数を呼び出します。 PHP はネイティブ マシン コードにコンパイルされないため、PHP はそのようなオペコード命令を使用して、実際の CPU とメモリがどのように動作するかをシミュレートします。

PHP ソース コードの SEND_REF を確認します:




コードをコピーします

コードは次のとおりです:

static int ZEND_FASTCALL ZEND_SEND_REF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
……
// CV から $arr ポインタのポインタを取得
varptr_ptr = _get_zval_ptr_ptr_cv(&opline->op1, EX (Ts)、BP_VAR_W TSRMLS_CC);


// 変数の分離。これはキー関数専用の配列の新しいコピーです
SEPARATE_ZVAL_TO_MAKE_IS_REF(varptr_ptr);
varptr = *varptr_ptr;
Z_ADDREF_P(varptr);

// スタックをプッシュします
zend_ vm_stack_push(varptr) ;
ZEND_VM_NEXT_OPCODE();
}

SEPARATE_ZVAL_TO_MAKE_IS_REF はマクロです:
コードをコピーしますコードは次のとおりです:

#define SEPARATE_ZVAL_TO_MAKE_IS _REF(ppzv)
if (!PZVAL_IS_REF( *ppzv)) {
{ SEPARATE_ZVAL(ppzv);主な機能は、変数が参照でない場合にメモリ内に新しいコピーをコピーすることです。この例では、array('a','b','c') をコピーします。したがって、変数分離後のメモリは次のようになります:

変数分離が完了した後、CV 配列内のポインターは新しくコピーされたデータを指し、古いデータは引き続き zend_execute_data->Ts 内のポインターを通じて取得できることに注意してください。
以下のループについては、上の図と組み合わせて個別に説明しません:

•foreach 構造は、以下の青い配列を使用し、a、b、c を順番に走査します
•キーと現在の用途は黄色です。上記の配列では、その内部ポインタは常に b を指します
これで、key と current が常に配列の 2 番目の要素を返す理由がわかりました。コピーされた配列には外部コードが作用しないため、その内部ポインタは決して移動しません。
質問 3:


コードをコピーします
コードは次のとおりです:
$arr = array('a','b','c');foreach($arr as $k => & $v) { echo key($arr), '=>', current($arr);
}// print 1=>b 2=>c =>



この質問と質問 2 の違いは 1 つだけです。この質問の foreach では参照が使用されています。
VLD を使用してこの質問を確認し、質問 2 のコードからコンパイルされたオペコードが同じであることを確認します。したがって、質問 2 の追跡方法を使用して、対応するオペコードの実装を徐々にチェックします。
最初に foreach は FE_RESET を呼び出します:

コードをコピーします
コードは次のとおりです:

static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
……
if (opline->extended_value & ZEND_FE_RESET_VARIABLE) {
_get_z = val_ptr_ptr_cv(&opline->op1, EX(Ts), TSRMLS_CC);
R _ptr ) == IS_OBJECT) {
/ 配列を走査する場合
使用する 使用する 使用する 使用する 使用する 使用する 使用する 使用する 使用する を通じて を通じて を通じて を通じて を通じて を通じて を通じて を通じて ‐ ‐ ‐ ‐ ‐ に) array_ptr_ptr );

FE_RESET
この例では、foreach が参照を使用して値を取得するため、実行中に FE_RESET は前の質問とは別の分岐に入ります。
最後に、FE_RESET は配列の is_ref を true に設定します。この時点では、メモリ内には配列データのコピーが 1 つだけあります。

次に SEND_REF を分析します:




コードをコピーします

コードは次のとおりです:


static int ZEND_FASTCALL ZEND_SEND_REF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{

// CVから$arrポインタのポインタを取得する
varptr_ptr = _get_zval_ptr_ptr_cv (&opline->op1, EX(Ts), BP_VAR_W TSRMLS_CC);
……
// 変数の分離、この時点では CV 自体の変数が参照であるため、ここには新しい配列はコピーされません
SEPARATE_ZVAL_TO_MAKE_IS_REF (varptr_ptr); varptr = *varptr_ptr; Z_ADDREF_P(varptr);

// スタックをプッシュします zend_vm_stack_push(varptr TSRMLS_CC);
ZEND_VM_NEXT_OPCODE();
}
マクロ SEPARATE_ZVAL_TO_MAKE_IS_REF は is_ref で変数を区切るだけです=偽。配列は以前に is_ref=true に設定されているため、コピーされません。つまり、この時点ではまだメモリ内に配列データのコピーが 1 つだけ存在します。

上の図は、最初の 2 つのループが 1=>b 2=>C を出力する理由を説明しています。 FE_FETCH の 3 番目のサイクル中に、ポインタを前進させ続けます。



コードをコピーします

コードは次のとおりです:


ZEND_API int zend_hash_move_forward_ex(HashTable *ht, HashPosition *pos)
{
HashPosition *current = pos ? : &ht->pInternalPointer;
IS_CONSISTENT( ht);
if (*現在) {

この時点で内部ポインタはすでに配列の最後の要素を指しているため、先に進むと NULL を指すことになります。内部ポインタを NULL に指定した後、配列の key と current を呼び出すと、それぞれ NULL と false が返され、この時点では文字はエコーされません。
質問 4:
コードをコピーします コードは次のとおりです:

$arr = array(1, 2, 3);
$tmp = $arr;
foreach($tmp as $ k => &$v){
$v *= 2;
}
var_dump($arr, $tmp); // 何を出力するか?

この質問は foreach とはあまり関係ありませんが、foreach に関係するので一緒に議論しましょう:)
コードでは、最初に配列 $arr が作成され、次にその配列が $tmp に割り当てられます。 foreach ループ内で $v を変更すると、配列 $tmp に影響しますが、$arr には影響しません。
なぜですか?
これは、PHP では代入操作によって 1 つの変数の値が別の変数にコピーされるため、一方を変更しても他方には影響しないからです。
余談: これはオブジェクト型には当てはまりません。PHP5 以降、オブジェクトはデフォルトで常に参照によって割り当てられます。 例:
コードをコピーします コードは次のとおりです:

class A{
public $foo = 1;
}
$a1 = $a2 = new A;
$a1->foo=100;
echo $a2->foo; // 出力 100、$a1 および $a2 は実際には同じオブジェクト参照

質問のコードに戻ると、$tmp=$arr が実際には値のコピーであり、$arr 配列全体が $tmp にコピーされることが確認できます。理論的には、代入ステートメントが実行された後、メモリ内に同じ配列のコピーが 2 つ存在します。
配列が大きい場合、この操作は非常に遅くなるのではないかと疑問に思う生徒もいるかもしれません。
幸いなことに、php にはこれを処理するより賢い方法があります。実際、$tmp=$arr が実行された後も、メモリには配列が 1 つだけ存在します。 PHP ソース コード (php5.3.26 か​​ら抽出) の zend_assign_to_variable 実装を表示します:
コードをコピーします コードは次のとおりです:

static inline zval* zend_assign_to_variable(zval **variable_ptr_ptr, zval *value, int is_tmp_var TSRMLS_DC)
{
zval *variable_ptr = *variable_ptr_ptr;
zval Garage;

// 左の値はオブジェクト型
if (Z_TYPE_P (variable_ptr)== is_object && z_obj_handler_p(variable_ptr、set)){

}} else {
// refcount__gc = 1
)&& z_refcount_p(value)>
/ / $ TMP = $ ARR がここで実行されます。
// value は、$ Arr を指す実際の Array データへのポインタです。 Variable_ptr_ptr は、$ TMP のデータ ポインタを指すポインタです
// ポインタをコピーするだけです。配列
* variable_ptr_ptr = 値; variable_ptr_ptr);
}
return *variable_ptr_ptr;
}


$tmp = $arr の本質は配列のポインタをコピーすることであることがわかります。このときのメモリを図で表現すると、配列は 1 つだけです:


配列は 1 つだけなので、foreach で $tmp が変更されると、ループに応じて $arr が変更されないのはなぜですか?
引き続き PHP ソース コードの ZEND_FE_RESET_SPEC_CV_HANDLER 関数を見てください。これは OPCODE HANDLER であり、対応する OPCODE は FE_RESET です。この関数は、foreach が開始される前に、配列の内部ポインタを最初の要素に設定する役割を果たします。



コードをコピーします

コードは次のとおりです:

static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
zend_op *opline = EX(opline);
zval *array_ptr, **array_ptr_ptr;
HashTable *fe_ht;
zend_object_iterator *iter = NULL;
zend_class_entry *ce = NULL;
zend_bool is_empty = 0;
// 对变量行FE_RESET
if (opline->extended_value & ZEND_FE_RESET_VARIABLE) {
array_ptr_ptr = _get_zval_ptr_ptr_cv(&opline->op1, EX(T) s)、BP_VAR_R TSRMLS_CC);
if (array_ptr_ptr == NULL || array_ptr_ptr == &EG(uninitialized_zval_ptr)) {
……
}
// foreach一个オブジェクト
else if (Z_TYPE_PP(array_ptr_ptr) == IS_OBJECT) {
……
}
else {
// 本例会进入该分支
if (Z_TYPE_PP(array_ptr_ptr) == IS_ARRAY) {
// 注意此处的SEPARATE_ZVAL_IF_NOT_REF
// 它会重新复制一个数组出来
// 真正分离$tmpand$arr,变成了内存中的2个数组
SEPARATE_ZVAL_IF_NOT_REF(array_ptr_ptr);
if (opline->extended_value & ZEND_FE_FETCH_BYREF) {
Z _SET_ISREF_PP(array_ptr_ptr);
}
}
array_ptr = *array_ptr_ptr;
Z_ADDREF_P(array_ptr);
}
} else {
… …
}

// 重置数組内部指针
……
}

从代码中可以見出,真正行变量分离并不赋值语句行時候,而是了了使用推量時の、天気これも PHP での Copy On Write 機構の実現です。
FE_RESET 後の内部格納の変更は次のようになります。興味深い同学は、ZEND_FE_RESET_SPEC_CV_HANDLER と ZEND_SWITCH_FREE_SPEC_VAR_HANDLER の具体的な動作 (両方とも php-src/zend/zend_vm_execute.h にあります)、本文では説明しません:)



http://www.bkjia.com/PHPjc/327985.html

www.bkjia.com

http://www.bkjia.com/PHPjc/327985.html技術記事前文: php4 では、foreach 構造が導入されており、これは遍歴数の唯一の方法です。foreach の転送と比較して、foreach はより便利な取得値を追加できます。php5 より前では、foreach のみ...
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

Ubuntu および Debian 用の PHP 8.4 インストールおよびアップグレード ガイド Ubuntu および Debian 用の PHP 8.4 インストールおよびアップグレード ガイド Dec 24, 2024 pm 04:42 PM

PHP 8.4 では、いくつかの新機能、セキュリティの改善、パフォーマンスの改善が行われ、かなりの量の機能の非推奨と削除が行われています。 このガイドでは、Ubuntu、Debian、またはその派生版に PHP 8.4 をインストールする方法、または PHP 8.4 にアップグレードする方法について説明します。

PHP 開発用に Visual Studio Code (VS Code) をセットアップする方法 PHP 開発用に Visual Studio Code (VS Code) をセットアップする方法 Dec 20, 2024 am 11:31 AM

Visual Studio Code (VS Code とも呼ばれる) は、すべての主要なオペレーティング システムで利用できる無料のソース コード エディター (統合開発環境 (IDE)) です。 多くのプログラミング言語の拡張機能の大規模なコレクションを備えた VS Code は、

PHPでHTML/XMLを解析および処理するにはどうすればよいですか? PHPでHTML/XMLを解析および処理するにはどうすればよいですか? Feb 07, 2025 am 11:57 AM

このチュートリアルでは、PHPを使用してXMLドキュメントを効率的に処理する方法を示しています。 XML(拡張可能なマークアップ言語)は、人間の読みやすさとマシン解析の両方に合わせて設計された多用途のテキストベースのマークアップ言語です。一般的にデータストレージに使用されます

母音を文字列にカウントするPHPプログラム 母音を文字列にカウントするPHPプログラム Feb 07, 2025 pm 12:12 PM

文字列は、文字、数字、シンボルを含む一連の文字です。このチュートリアルでは、さまざまな方法を使用してPHPの特定の文字列内の母音の数を計算する方法を学びます。英語の母音は、a、e、i、o、u、そしてそれらは大文字または小文字である可能性があります。 母音とは何ですか? 母音は、特定の発音を表すアルファベットのある文字です。大文字と小文字など、英語には5つの母音があります。 a、e、i、o、u 例1 入力:string = "tutorialspoint" 出力:6 説明する 文字列「TutorialSpoint」の母音は、u、o、i、a、o、iです。合計で6元があります

トップ10グローバルデジタル仮想通貨取引プラットフォームランキング(2025権限ランキング) トップ10グローバルデジタル仮想通貨取引プラットフォームランキング(2025権限ランキング) Mar 06, 2025 pm 04:36 PM

2025年、グローバルデジタル仮想通貨取引プラットフォームは、トランザクションのボリューム、セキュリティ、ユーザーエクスペリエンスなどの指標に基づいて、2025年に世界のトップ10のデジタル通貨取引プラットフォームを激しく競争しています。 OKXは、強力な技術的強さとグローバルな運用戦略で最初にランクされており、Binanceは高流動性と低料金に密接に続きます。 Gate.io、Coinbase、Krakenなどのプラットフォームは、それぞれの利点がある最前線にいます。このリストには、Huobi、Kucoin、Bitfinex、Crypto.com、Geminiなどの取引プラットフォームがそれぞれ独自の特徴がありますが、投資は注意する必要があります。プラットフォームを選択するには、セキュリティ、流動性、料金、ユーザーエクスペリエンス、通貨選択、規制コンプライアンスなどの要因を考慮し、合理的に投資する必要があります

JSON Web Tokens(JWT)とPHP APIでのユースケースを説明してください。 JSON Web Tokens(JWT)とPHP APIでのユースケースを説明してください。 Apr 05, 2025 am 12:04 AM

JWTは、JSONに基づくオープン標準であり、主にアイデンティティ認証と情報交換のために、当事者間で情報を安全に送信するために使用されます。 1。JWTは、ヘッダー、ペイロード、署名の3つの部分で構成されています。 2。JWTの実用的な原則には、JWTの生成、JWTの検証、ペイロードの解析という3つのステップが含まれます。 3. PHPでの認証にJWTを使用する場合、JWTを生成および検証でき、ユーザーの役割と許可情報を高度な使用に含めることができます。 4.一般的なエラーには、署名検証障害、トークンの有効期限、およびペイロードが大きくなります。デバッグスキルには、デバッグツールの使用とロギングが含まれます。 5.パフォーマンスの最適化とベストプラクティスには、適切な署名アルゴリズムの使用、有効期間を合理的に設定することが含まれます。

今まで知らなかったことを後悔している 7 つの PHP 関数 今まで知らなかったことを後悔している 7 つの PHP 関数 Nov 13, 2024 am 09:42 AM

あなたが経験豊富な PHP 開発者であれば、すでにそこにいて、すでにそれを行っていると感じているかもしれません。あなたは、運用を達成するために、かなりの数のアプリケーションを開発し、数百万行のコードをデバッグし、大量のスクリプトを微調整してきました。

PHPでの後期静的結合を説明します(静的::)。 PHPでの後期静的結合を説明します(静的::)。 Apr 03, 2025 am 12:04 AM

静的結合(静的::) PHPで後期静的結合(LSB)を実装し、クラスを定義するのではなく、静的コンテキストで呼び出しクラスを参照できるようにします。 1)解析プロセスは実行時に実行されます。2)継承関係のコールクラスを検索します。3)パフォーマンスオーバーヘッドをもたらす可能性があります。

See all articles