it-swarm.com.de

Wie wird ein serialisiertes Array durch Vergleichen von größer als (> =) abgefragt?

Ich habe Post-Meta-Werte serialisiert. Es sieht aus wie das:

 enter image description here 

Im Array:

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

Und ich möchte eine benutzerdefinierte Abfrage mit meta_query args machen. Dies ist meine Frage Argumente:

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

Es wird jedoch kein Ergebnis angezeigt.

2
bilimokur

serialisiertes Array in einem Meta-Wert für die Abfrage

Es ist keine gute Idee, ein serialisiertes Array in einem meta_value zu speichern, wenn Sie später eine Abfrage mit einem Wert innerhalb dieses serialisierten Arrays planen. Daher ist die beste Option, Metadaten als Schlüssel/Wert-Paar zu speichern.

Serialisiertes Array abfragen

Obwohl dies kein guter Ansatz ist, ist es dennoch möglich, ein serialisiertes Array in meta_value mit regulärer Ausdruck abzufragen.

Warnung:In Bezug auf die Leistung ist dies überhaupt keine gute Idee. Wenn Sie also eine andere Möglichkeit haben, das Gleiche zu erreichen, tun Sie dies besser. Ich gebe die Antwort nur, um zu zeigen, dass es möglich ist. Also benutze es nur als letzten Ausweg .

Beispiel CODE:

// 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',
        )
    )
);

Wie Sie sehen, habe ich 'compare' => 'REGEXP' und die Funktion wpse311157_serialize_num_greater_equals_regex( 'option1', 6 ) verwendet, um den richtigen regulären Ausdruck zu generieren (der erste Parameter ist der Name des Arrays key und der zweite Parameter ist die Zahl, die mit >= verglichen werden soll).

Implementieren wir nun die Funktion wpse311157_serialize_num_greater_equals_regex. Da meta_value ein serialisiertes Array ist, sieht es ungefähr so ​​aus: a:1:{s:3:"key";i:7;}. Dazu sieht unser CODE folgendermaßen aus:

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 ) . ');.*\}';
}

Jetzt müssen wir die Funktion wpse311157_num_greater_equals_regex( $num ) implementieren, indem wir den Vergleich von >= in einen regulären Ausdruck konvertieren. Dies ist nicht sehr effizient , aber dies ist die einzige Option, die wir haben.

RegEx-Algorithmus zum Vergleichen von >=

Der Algorithmus ist einfach:

(A) Für n Ziffern ist jede Zahl mit (n+1) Ziffern größer als diese Zahl.

(B) Zusätzlich benötigen wir eine maximale Anzahl von Regeln für n, um andere Ziffern für n zu überprüfen, die größer oder gleich dieser Anzahl sind.

Angenommen, wir möchten Folgendes vergleichen: num >= 12

RegEx: [1-9][0-9][0-9]+ wird es also immer erfüllen, da es mit 3 oder mehr Ziffern übereinstimmt.

Um 2-stellige Zahlen mit >= 12 abzugleichen, benötigen wir 2 Regeln:

  1. 1[2-9] => Dies entspricht den Nummern 12 bis 19
  2. [2-9][0-9] => Dies entspricht den Zahlen von 20 bis 99

Die endgültige RegEx für num >= 12 lautet also: 1[2-9]|[2-9][0-9]|[1-9][0-9][0-9]+

Erstellen wir mit diesem Algorithmus unsere Funktion 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 );
}

Jetzt können Sie einen Wert mit >= in einem serialisierten Array vergleichen.

2
Fayaz