検索
ホームページバックエンド開発PHPチュートリアルPHP 拡張機能と埋め込み -- PHP 拡張機能の配列とハッシュ テーブル 2_PHP チュートリアル

上記のセクションに続いて、PHP 拡張機能の配列とハッシュ テーブル API について説明します。このセクションでは主に について説明します。 コールバック走査関数、通常走査関数、デストラクタ、ソート、比較、極値関数

ハッシュによる反復適用: 配列を走査する最も簡単な方法は、PHP 言語の foreach ステートメントに似た関数 zend_hash_apply を使用することです。この関数はコールバック関数を受け取り、ハッシュテーブルの各要素をそれに渡します。

typedef int (*apply_func_t)(void *pDest TSRMLS_DC);
void zend_hash_apply(HashTable *ht,
        apply_func_t apply_func TSRMLS_DC);
typedef int (*apply_func_arg_t)(void *pDest,
                            void *argument TSRMLS_DC);
void <strong>zend_hash_apply_with_argument</strong>(HashTable *ht,
        apply_func_arg_t apply_func, void *data TSRMLS_DC);
1 つはパラメータを渡すことができ、もう 1 つはパラメータを渡さず、ハッシュ テーブル内の値のみを渡します。引数を渡すことができる関数の場合、拡張機能で適用できる可能性が高くなります。 コールバック関数は異なる戻り値を持つ場合があります。
コールバック関数のテーブル戻り値
一定の意味
ZEND_HASH_APPLY_KEEP は現在のリクエストを終了し、次のサイクルに入ります。これは、PHP 言語の forech ステートメントのループが実行された場合、または continue キーワードが検出された場合と同じ効果があります。
ZEND_HASH_APPLY_STOP が飛び出します。これは、PHP 言語の forech ステートメントの Break キーワードと同じ効果があります。
ZEND_HASH_APPLY_REMOVE は現在の要素を削除し、次の要素の処理を続行します。 PHP 言語の場合と同等: unset($foo[$key]);Continue;

単純なPHPトラバーサルコードの場合
<?php foreach($arr as $val) {     echo "The value is: $val\n"; }
?>
の拡張形式は次のとおりです。 まずコールバック関数を定義します 次に、
int php_sample_print_zval(zval **val TSRMLS_DC)
{
    //重新copy一个zval,防止破坏原数据
    zval tmpcopy = **val;
    zval_copy_ctor(&tmpcopy);
     
    //转换为字符串
    INIT_PZVAL(&tmpcopy);
    convert_to_string(&tmpcopy);
    
    //开始输出
    php_printf("The value is: ");
    PHPWRITE(Z_STRVAL(tmpcopy), Z_STRLEN(tmpcopy));
    php_printf("\n");
     
    //毁尸灭迹
    zval_dtor(&tmpcopy);
     
    //返回,继续遍历下一个~
    return ZEND_HASH_APPLY_KEEP;
}
はループ関数を定義します: zend_hash_apply(arrht, php_sample_print_zval TSRMLS_CC);
要素タイプが zval* である arrht という名前のハッシュ テーブルが走査されます。
ハッシュ テーブルに格納されるのは要素ではなく、ポインタ (zval**) であることに注意してください。コピーすると、ポインタもコピーされ、ハッシュ テーブル自体の内容は変更されません。

ループ中に値とキーの両方を受け取るために、zend_hash_apply() の 3 番目の形式: zend_hash_apply_with_arguments() この PHP コードに対する
<?php
foreach($arr as $key => $val) {     echo "The value of $key is: $val\n"; }
?>
の C コード: れーれー
トラバーサルを実行します。 zend_hash_apply_with_arguments(arrht, php_sample_print_zval_and_key, 0); hash_key が文字列型であるか数値型であるかを確認する場合、arKey 属性ではなく、nKeyLength 属性を通じて検出されます。これは、カーネルが arKey 属性にダーティ データを残すことがありますが、nKeyLength 属性は安全であり、安全に使用できるためです。空の文字列インデックスも処理できます。例: $foo[''] = "Bar"; インデックス値は NULL 文字ですが、その長さには最後の NULL 文字が含まれるため、1 になります。

前進による反復 ハッシュ テーブルのトラバーサルはコールバックなしで実装できます。このとき、ハッシュテーブルの内部ポインタが使用される。
ユーザー空間では多くの機能が利用可能です:
int php_sample_print_zval_and_key(zval **val,         int num_args, va_list args, zend_hash_key *hash_key) {
    /* 复制zval从而使得原来的内容被保存下来 */     
    zval tmpcopy = **val;     
    /* tsrm_ls is needed by output functions */     
    TSRMLS_FETCH();     
    zval_copy_ctor(&tmpcopy);     
    /* Reset refcount & Convert */
    INIT_PZVAL(&tmpcopy);
    convert_to_string(&tmpcopy);     
    /* 输出 */
    php_printf("The value of ");
    if (hash_key->nKeyLength) {  
        /* 如果是字符串类型的key */    
        PHPWRITE(hash_key->arKey, hash_key->nKeyLength);     
    } else {
        /* 如果是数字类型的key */ 
        php_printf("%ld", hash_key->h);     
    }
    php_printf(" is: ");
    PHPWRITE(Z_STRVAL(tmpcopy), Z_STRLEN(tmpcopy));     php_printf("\n");
    /* Toss out old copy */
    zval_dtor(&tmpcopy);
    /* continue; */
    return ZEND_HASH_APPLY_KEEP;
}
対応する各関数には zend バージョンがあります。
<?php
    $arr = array('a'=>1, 'b'=>2, 'c'=>3);
    reset($arr);
    while (list($key, $val) = each($arr)) {
        /* Do something with $key and $val */
    }
    reset($arr);
    $firstkey = key($arr);
    $firstval = current($arr);
    $bval = next($arr);
    $cval = next($arr);
?>
next() prev() end() は実際に対応するインデックス値を検索し、zend_hash_get_current_data() を使用して要素値を返します
each() は次のステップと同じですが、zend_hash_get_current_key() を呼び出して返します

したがって、コールバック関数を使用しないハッシュ テーブル トラバーサル メソッドを次に示します。
	* /* reset() */
void zend_hash_internal_pointer_reset(HashTable *ht);
        /* key() */
int zend_hash_get_current_key(HashTable *ht,
        char **strIdx, unit *strIdxLen,
        ulong *numIdx, zend_bool duplicate);
	* /* current() */
int zend_hash_get_current_data(HashTable *ht, void **pData);
	* /* next()/each() */
int zend_hash_move_forward(HashTable *ht);
	* /* prev() */
int zend_hash_move_backwards(HashTable *ht);
	* /* end() */
void zend_hash_internal_pointer_end(HashTable *ht);
	* /* Other... */
int zend_hash_get_current_key_type(HashTable *ht);
int zend_hash_has_more_elements(HashTable *ht);
zend_hash_get_current_key_ex 戻り値の可能性を見てみましょう。 一定の意味

HASH_KEY_IS_STRING 現在の要素のインデックスは文字列型です。したがって、要素のキー名へのポインタが strIdx に設定され、その長さが stdIdxLen に設定されます。重複フラグがゼロ以外の値に設定されている場合、キーは前に estrndup() されます。 呼び出し元のアプリケーションは、この重複した文字列を解放する必要があります。

HASH_KEY_IS_LONG 現在の要素のインデックスは数値です。
HASH_KEY_NON_EXISTANT HashTable の内部ポインターが末尾に移動され、どの要素も指していません。


破壊 デストラクターは 4 つだけであることに注意してください。 最初の 2 つは、ハッシュ テーブルから個々の要素を削除するために使用されます。
void php_sample_print_var_hash(HashTable *arrht)
{
    for(zend_hash_internal_pointer_reset(arrht);
    zend_hash_has_more_elements(arrht) == SUCCESS;
    zend_hash_move_forward(arrht)) {
        char *key;
        uint keylen;
        ulong idx;
        int type;
        zval **ppzval, tmpcopy;
        type = zend_hash_get_current_key_ex(arrht, &key, &keylen,
                                                  &idx, 0, NULL);//获得返回的key的类型。这个类型可能有三种
        if (zend_hash_get_current_data(arrht, (void**)&ppzval) == FAILURE) {//获得当前索引所指的数据值
            /* Should never actually fail
             * since the key is known to exist. */
            continue;
        }
        /* 复制zval的值,从而原来的值不会被破坏掉 */
        tmpcopy = **ppzval;
        zval_copy_ctor(&tmpcopy);
        /* 重新设定refcount 并且转换 */
        INIT_PZVAL(&tmpcopy);
        convert_to_string(&tmpcopy);
        /* 输出 */
        php_printf("The value of ");
        if (type == HASH_KEY_IS_STRING) {
            /* String Key / Associative */
            PHPWRITE(key, keylen);
        } else {
            /* Numeric Key */
            php_printf("%ld", idx);
        }
        php_printf(" is: ");
        PHPWRITE(Z_STRVAL(tmpcopy), Z_STRLEN(tmpcopy));
        php_printf("\n");
        /* 销毁原来的副本 */
        zval_dtor(&tmpcopy);
    }
}
は成功または失敗を返します
それぞれ文字列インデックスと数値インデックスに対応するバージョン。
要素がハッシュ テーブルから削除されると、要素へのポインタを使用してハッシュ テーブルのデストラクタが呼び出されます。

ハッシュ テーブルを完全に削除する場合: void zend_hash_clean(HashTable *ht); これは、ループ内で zend_hash_del を呼び出すのと同じです。 clean の実行に加えて、次の関数を呼び出すと、zend_hash_init によって適用されたすべてのスペースも破棄されます: void zend_hash_destroy(HashTable *ht);
プロセス全体をより明確に理解するために、ハッシュ テーブルのライフ サイクルを見てみましょう。 リーリー

分類、比較、そして極限への挑戦 2 つのハッシュ テーブルのサイズを比較するには: typedef int (*compare_func_t)(void *a, void *b TSRMLS_DC); この関数は qsort とまったく同じで、独自の関数が a と b を比較して -1 0 1 を返すことを期待しています

サイズ比較を使用した例を次に示します:
int zend_hash_del(HashTable *ht, char *arKey, uint nKeyLen);
int zend_hash_index_del(HashTable *ht, ulong h);
flag が 0 の場合は最小値が返され、それ以外の場合は最大値が返されます。

下面则给出一个更为具体的例子,通过不同的flag就可以控制到底是返回最大值还是最小值:
int fname_compare(zend_function *a, zend_function *b TSRMLS_DC)
{
    return strcasecmp(a->common.function_name, b->common.function_name);
}
void php_sample_funcname_sort(TSRMLS_D)
{
    zend_function *fe;
    if (zend_hash_minmax(EG(function_table), fname_compare,
                0, (void **)&fe) == SUCCESS) {
        php_printf("Min function: %s\n", fe->common.function_name);
    }
    if (zend_hash_minmax(EG(function_table), fname_compare,
                1, (void **)&fe) == SUCCESS) {
        php_printf("Max function: %s\n", fe->common.function_name);
    }
}

还有一个进行哈希比较的函数: int zend_hash_compare(HashTable *hta, HashTable *htb,
compare_func_t compar, zend_bool ordered TSRMLS_DC); 先比较哈希表的个数,哪个多哪个大。 如果一样多的,就每个元素去比较。

另外还有一个专门的排序函数:
typedef void (*sort_func_t)(void **Buckets, size_t numBuckets,
            size_t sizBucket, compare_func_t comp TSRMLS_DC);
int zend_hash_sort(HashTable *ht, sort_func_t sort_func,
        compare_func_t compare_func, int renumber TSRMLS_DC);
一般就用zend_qsort作为sort_func就够了。renumber这个参数如果设为1的话,那么就会抛弃原有的索引键值关系,赋予新的数字键值。 zend_hash_sort(target_hash, zend_qsort,array_data_compare, 1 TSRMLS_CC); array_data_compare是一个返回compare_func_t类型数据的函数,它将按照HashTable中zval*值的大小进行排序。


www.bkjia.comtruehttp://www.bkjia.com/PHPjc/635044.htmlTechArticle接着上面一节,继续说php扩展中的数组与哈希表的api,这节主要是说回调遍历函数正常遍历函数析构函数排序、对比、极函数 Iteration by ha...
声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
どのデータをPHPセッションに保存できますか?どのデータをPHPセッションに保存できますか?May 02, 2025 am 12:17 AM

phpssionscanStorestrings、numbers、arrays、andobjects.1.strings:textdatalikeusernames.2.numbers:integersorfloatsforcounters.3.arrays:listslikeshoppingcarts.4.objects:complextructuresthataresialized。

どのようにPHPセッションを開始しますか?どのようにPHPセッションを開始しますか?May 02, 2025 am 12:16 AM

tostartaphpsession、outsession_start()atthescript'sbeginning.1)placeitbe foreanyouttosetthesscookie.2)usesionsionsionsionserdatalikelogintatussorshoppingcarts.3)再生セッションインドストップレベントフィックスアタック

セッションの再生とは何ですか?また、セキュリティをどのように改善しますか?セッションの再生とは何ですか?また、セキュリティをどのように改善しますか?May 02, 2025 am 12:15 AM

セッション再生とは、新しいセッションIDを生成し、セッション固定攻撃の場合にユーザーが機密操作を実行するときに古いIDを無効にすることを指します。実装の手順には次のものが含まれます。1。感度操作を検出、2。新しいセッションIDを生成する、3。古いセッションIDを破壊し、4。ユーザー側のセッション情報を更新します。

PHPセッションを使用する際のパフォーマンスの考慮事項は何ですか?PHPセッションを使用する際のパフォーマンスの考慮事項は何ですか?May 02, 2025 am 12:11 AM

PHPセッションは、アプリケーションのパフォーマンスに大きな影響を与えます。最適化方法には以下が含まれます。1。データベースを使用してセッションデータを保存して応答速度を向上させます。 2。セッションデータの使用を削減し、必要な情報のみを保存します。 3.非ブロッキングセッションプロセッサを使用して、同時実行機能を改善します。 4.セッションの有効期限を調整して、ユーザーエクスペリエンスとサーバーの負担のバランスを取ります。 5.永続的なセッションを使用して、データの読み取り時間と書き込み時間を減らします。

PHPセッションはCookieとどのように異なりますか?PHPセッションはCookieとどのように異なりますか?May 02, 2025 am 12:03 AM

phpsesionsareserver-side、whilecookiesareclient-side.1)Sessionsionsionsoredataontheserver、aremoresecure.2)cookiesstoredataontheclient、cookiestoresecure、andlimitedinsizeisize.sesionsionsionivationivationivationivationivationivationivationivate

PHPはユーザーのセッションをどのように識別しますか?PHPはユーザーのセッションをどのように識別しますか?May 01, 2025 am 12:23 AM

phpidentifiesauser'ssessionsingsinssessionCookiesIds.1)whensession_start()iscalled、phpgeneratesauniquesidstoredsored incoookienadphpsessidontheuser'sbrowser.2)thisidallowsphptortorieSessiondatadata fromthata

PHPセッションを保護するためのベストプラクティスは何ですか?PHPセッションを保護するためのベストプラクティスは何ですか?May 01, 2025 am 12:22 AM

PHPセッションのセキュリティは、次の測定を通じて達成できます。1。session_regenerate_id()を使用して、ユーザーがログインまたは重要な操作である場合にセッションIDを再生します。 2. HTTPSプロトコルを介して送信セッションIDを暗号化します。 3。Session_Save_Path()を使用して、セッションデータを保存し、権限を正しく設定するためのSecure Directoryを指定します。

PHPセッションファイルはデフォルトで保存されていますか?PHPセッションファイルはデフォルトで保存されていますか?May 01, 2025 am 12:15 AM

phpsessionFilesToredInthededirectoryspecifiedBysession.save_path、通常/tmponunix-likesystemsorc:\ windows \ temponwindows.tocustomizethis:1)uesession_save_path()tosetaCustomdirectory、ensuringit'swritadistradistradistradistradistra

See all articles

ホット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衣類リムーバー

Video Face Swap

Video Face Swap

完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

ホットツール

DVWA

DVWA

Damn Vulnerable Web App (DVWA) は、非常に脆弱な PHP/MySQL Web アプリケーションです。その主な目的は、セキュリティ専門家が法的環境でスキルとツールをテストするのに役立ち、Web 開発者が Web アプリケーションを保護するプロセスをより深く理解できるようにし、教師/生徒が教室環境で Web アプリケーションを教え/学習できるようにすることです。安全。 DVWA の目標は、シンプルでわかりやすいインターフェイスを通じて、さまざまな難易度で最も一般的な Web 脆弱性のいくつかを実践することです。このソフトウェアは、

Safe Exam Browser

Safe Exam Browser

Safe Exam Browser は、オンライン試験を安全に受験するための安全なブラウザ環境です。このソフトウェアは、あらゆるコンピュータを安全なワークステーションに変えます。あらゆるユーティリティへのアクセスを制御し、学生が無許可のリソースを使用するのを防ぎます。

mPDF

mPDF

mPDF は、UTF-8 でエンコードされた HTML から PDF ファイルを生成できる PHP ライブラリです。オリジナルの作者である Ian Back は、Web サイトから「オンザフライ」で PDF ファイルを出力し、さまざまな言語を処理するために mPDF を作成しました。 HTML2FPDF などのオリジナルのスクリプトよりも遅く、Unicode フォントを使用すると生成されるファイルが大きくなりますが、CSS スタイルなどをサポートし、多くの機能強化が施されています。 RTL (アラビア語とヘブライ語) や CJK (中国語、日本語、韓国語) を含むほぼすべての言語をサポートします。ネストされたブロックレベル要素 (P、DIV など) をサポートします。

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SAP NetWeaver Server Adapter for Eclipse

SAP NetWeaver Server Adapter for Eclipse

Eclipse を SAP NetWeaver アプリケーション サーバーと統合します。