web-dev-qa-db-fra.com

Comment interroger un tableau sérialisé en comparant supérieur à (> =)?

J'ai sérialisé les méta-valeurs post. Cela ressemble à ceci:

 enter image description here 

Dans le tableau:

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

Et je veux faire une requête personnalisée avec meta_query args. Voici mes arguments de requête:

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

Mais cela n’affiche aucun résultat.

2
bilimokur

tableau sérialisé dans une meta_value pour la requête

Ce n'est pas une bonne idée de sauvegarder un tableau sérialisé dans un meta_value si vous envisagez d'interroger ultérieurement une valeur quelconque dans ce tableau sérialisé. La meilleure option consiste donc à enregistrer les métadonnées sous forme de paire clé/valeur.

Interroger un tableau sérialisé

Bien que ce ne soit pas une bonne approche, il est toujours possible d'interroger un tableau sérialisé dans meta_value à l'aide de expression régulière .

Attention: _ Performance sage ce n'est pas une bonne idée du tout. Donc, si vous avez un autre moyen de réaliser la même chose, mieux le faire. Je ne réponds que pour montrer que c'est possible. Alors utilisez-le seulement en dernier recours .

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

Comme vous pouvez le constater, j’ai utilisé 'compare' => 'REGEXP' et la fonction wpse311157_serialize_num_greater_equals_regex( 'option1', 6 ) pour générer l’expression régulière appropriée (le premier paramètre est le nom du tableau keyet le deuxième paramètre est le nombre à comparer avec >=).

Maintenant, implémentons la fonction wpse311157_serialize_num_greater_equals_regex. Étant donné que meta_value est un tableau sérialisé, il se présentera comme suit: a:1:{s:3:"key";i:7;}. Pour correspondre à cela, notre CODE ressemblera à:

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

Nous devons maintenant implémenter la fonction wpse311157_num_greater_equals_regex( $num ) en convertissant la comparaison >= en expression régulière. Ceci est pas très efficace , mais c'est la seule option que nous avons.

Algorithme RegEx pour comparer >=

L'algorithme est simple:

(A) Pour tout numéro de chiffre n__, tout nombre comportant (n+1) chiffres est supérieur à ce nombre.

(B) De plus, nous avons besoin du nombre maximal de n(nombre de règles) pour vérifier les autres nombres de nname (chiffres) supérieurs ou égaux à ce nombre.

Par exemple, supposons que nous voulions comparer: num >= 12

Donc, RegEx: [1-9][0-9][0-9]+ le satisfera toujours, car il correspondra à 3 chiffres ou plus.

Maintenant, pour faire correspondre les nombres à 2 chiffres qui sont >= 12, nous avons besoin de 2 règles:

  1. 1[2-9] => cela correspondra aux nombres: 12 à 19
  2. [2-9][0-9] => cela correspondra aux numéros: 20 à 99

Donc, le RegEx final pour num >= 12 est: 1[2-9]|[2-9][0-9]|[1-9][0-9][0-9]+

Avec cet algorithme, créons notre fonction 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 );
}

C'est tout, vous pourrez maintenant comparer une valeur avec >= dans un tableau sérialisé.

2
Fayaz