Ich habe Post-Meta-Werte serialisiert. Es sieht aus wie das:
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.
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.
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.
>=
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[2-9]
=> Dies entspricht den Nummern 12 bis 19[2-9][0-9]
=> Dies entspricht den Zahlen von 20 bis 99Die 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.