如何通过比较大于(>=)来查询序列化数组?

时间:2018-08-11 作者:wpdev

我已经序列化了post元值。看起来是这样的:

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 个回复
最合适的回答,由SO网友:Fayaz 整理而成

将序列化数组保存在查询的meta\\u值中不是一个好主意meta_value 如果计划稍后使用该序列化数组中的任何值进行查询。因此,最好的选择是将元数据保存为键/值对。

查询序列化数组虽然不是一种好方法,但仍然可以在meta_value 使用regular expression.

Warning: 就性能而言,这根本不是一个好主意。因此,如果你有其他方法来实现同样的目标,最好这样做。我给出答案只是为了证明这是可能的。所以使用它only as a last resort.

示例代码:

// 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 第二个参数是要比较的数字>=).

现在,让我们实现wpse311157_serialize_num_greater_equals_regex 作用自从meta_value 是一个序列化数组,它将类似于:a:1:{s:3:"key";i:7;}. 为了匹配这一点,我们的代码如下所示:

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 ) 转换函数>= 比较到正则表达式。这是not very efficient, 但这是我们唯一的选择。

要比较的RegEx算法>=

算法很简单:

(A) 对于任何n 数字,任何带(n+1) 数字大于该数字。

(B) 此外,我们需要最大n 要检查其他的规则数n 大于或等于此数字的数字。

例如,假设我们要比较:num >= 12

所以,正则表达式:[1-9][0-9][0-9]+ 将始终满足它,因为它将匹配3个或更多数字。

现在,要匹配两位数>= 12,我们需要两条规则:

  1. 1[2-9] => 这将匹配数字:12到19[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 );
    }
    
    仅此而已,现在您可以将值与>= 在序列化数组中。

SO网友:Nic Bug

来自@Fayaz!的出色回答!非常感谢。我获取代码并将其更改为匹配序列化数组的大小(计数),该数组位于序列化字符串的开头,如“a:4”=数组中的4个条目。这就是我想到的:

\'meta_query\' => array(
    \'user_sets\' => array(
         \'key\' => \'user_sets\',
         \'value\'   => serialize_num_greater_equals_regex( $_GET[\'sets\'] ),
         \'compare\' => \'REGEXP\'

     )
)
以及简化的功能:

function serialize_num_greater_equals_regex( $num ) {
    return \'a\\:(\' . num_greater_equals_regex( $num ) . \')\\:\\{s.*\';
}
因此,现在您可以按数组大小过滤结果了!顺便说一下,我使用的方法是“users_list_table_query_args“使用的挂钩WP_User_Query 班使用挂钩,您可以更改用户。php输出。

结束

相关推荐

防止使用新的Query_Posts()更改

我必须在我的主题首页上显示12项我的自定义帖子类型。但是,当我这样做时,页面标题(<title>...</title>) 更改为Custom Post Type archive - Page Title.因为这是首页,我只想让它有正常的首页标题,即Page title - page tag line. 有没有办法在新的query_posts()? 或者只是为了防止在使用新的query_posts()?我不介意在子页面上发生这种情况,但在首页,当我打开筛选结果时,它不应该改变post