web-dev-qa-db-ja.com

より大きい(> =)を比較して直列化配列を照会する方法は?

メタ値をシリアル化しました。それはこのように見えます:

enter image description here 

配列では:

$kisiArray = array(
   'option1' => 7,
   'option2' => 'bar',
   'option3' => 'Apple',
   'option4' => 'orange'
);

そして、 meta_query argsを使ってカスタムクエリを作りたいこれは私のクエリ引数です:

<?php 
$args = array(
    'order'          => 'DESC',
    'meta_query'     => array(
        array(
            'key'     => 'themeOps_option1',
            'value'   => 6,
            'compare' => '>=',
        )
    )
);
?>

しかし、結果は表示されません。

2
bilimokur

問合せ用のmeta_value内のシリアル化された配列

後でその直列化配列内の任意の値で照会する予定がある場合は、直列化配列をmeta_valueに保存することはお勧めできません。そのため、最善の選択肢は、メタデータをキーと値のペアとして保存することです。

直列化配列の照会

これは良い方法ではありませんが、 正規表現 を使ってmeta_value内で直列化された配列を問い合わせることは可能です。

警告:パフォーマンスの面でこれはまったく良い考えではありません。あなたが同じことを成し遂げるための他の方法があるならばそれでそれをしなさい。それが可能であることを示すためだけに答えを出しています。それで 最後の手段としてのみ使用してください

コード例:

// this array is serialized and saved in meta_value for meta_key 'themeOps'
$serializedArray = array(
    'option1' => 7,
    'option2' => 'bar',
    'option3' => 'Apple',
    'option4' => 'orange'
);

// this is the WP_Query argument
$args = array(
    'meta_query' => array(
        array(
            'key'     => 'themeOps',
            // this compares if 'option1' >= 6 within the serialized array in meta_value
            'value'   => wpse311157_serialize_num_greater_equals_regex( 'option1', 6 ),
            'compare' => 'REGEXP',
        )
    )
);

ご覧のとおり、'compare' => 'REGEXP'を使用し、関数wpse311157_serialize_num_greater_equals_regex( 'option1', 6 )を使用して適切な正規表現を生成しました(最初のパラメーターは配列keyの名前、2番目のパラメーターは>=と比較する番号です)。

それでは、wpse311157_serialize_num_greater_equals_regex関数を実装しましょう。 meta_valueは直列化された配列なので、a:1:{s:3:"key";i:7;}のようになります。それに合わせるために、私たちのCODEは次のようになります。

function wpse311157_serialize_num_greater_equals_regex( $key, $num ) { 
    return 'a\:[1-9][0-9]*\:\{.*' . preg_quote( serialize( $key ) ) . 'i\:(' . wpse311157_num_greater_equals_regex( $num ) . ');.*\}';
}

>=の比較を正規表現に変換することによってwpse311157_num_greater_equals_regex( $num )関数を実装する必要があります。これは それほど効率的ではない ですが、これが唯一の選択肢です。

>=を比較するためのRegExアルゴリズム

アルゴリズムは簡単です:

(A)任意のn桁の番号について、(n+1)桁の番号はその番号より大きい。

(B)さらに、この数以上の他のn桁数をチェックするには、最大n個のルールが必要です。

たとえば、比較したいとします。num >= 12

したがって、RegEx:[1-9][0-9][0-9]+は、3桁以上の数字に一致するため、常にこれを満たします。

さて、>= 12である2桁の数字と一致させるには、2つの規則が必要です。

  1. 1[2-9] =>これは数字にマッチします:12から19
  2. [2-9][0-9] =>これは数字にマッチします:20から99

num >= 12の最終的な正規表現は次のようになります。 1[2-9]|[2-9][0-9]|[1-9][0-9][0-9]+

このアルゴリズムで、wpse311157_num_greater_equals_regex( $num )関数を作りましょう。

function wpse311157_num_greater_equals_regex( $num ) {
    $digits = wpse311157_num_digits( $num );
    $num_i = $num;
    $regex = '';        
    for( $i = 1; $i <= $digits; $i++ ) { 
        $digit = $num_i % 10; 
        $num_i = (int) ( $num_i / 10 );
        $regex_i = ''; 
        $need_rule = true;
        if( 1 === $i ) { 
            if( 9 === $digit ) { 
                $regex_i = '9';
            }   
            else {
                $regex_i = '[' . $digit . '-9]';
            }   
        }   
        else {
            // no rule for 9
            if( 9 === $digit ) { 
                $need_rule = false;
            }
            else if( 8 === $digit ) {
                $regex_i = '9';
            }
            else {
                $regex_i = '[' . ( $digit + 1 ) . '-9]';
            }
        }

        if( $need_rule ) {
            if( $i < $digits ) {
                $regex_i = $num_i . $regex_i;
            }

            for( $j = 1; $j < $i; $j++ ) {
                $regex_i = $regex_i . '[0-9]';
            }

            if( empty( $regex ) ) {
                $regex = $regex_i;
            }
            else {
                $regex = $regex . '|' . $regex_i;
            }
        }
    }

    $regex = $regex . '|[1-9]';
    for( $i = 1; $i < $digits; $i++ ) {
        $regex = $regex . '[0-9]';
    }
    $regex = $regex . '[0-9]+';

    return $regex;
}

function wpse311157_num_digits( $num ) { 
    // not considering 0 or negative numbers
    if( $num < 1 ) return -1; 

    return floor( log10( $num ) + 1 );
}

以上で、直列化された配列内で>=と値を比較できるようになりました。

2
Fayaz