【问题标题】:How do I return literal values of a PHP string so it runs as code?如何返回 PHP 字符串的文字值以便它作为代码运行?
【发布时间】:2016-06-30 12:00:27
【问题描述】:

我不确定我是否在这里使用了正确的术语,但我会尝试解释。我正在使用 PHP 的 array_filter 函数来过滤产品,它会回调我在其中添加过滤器的自定义函数。我可以很容易地进行硬编码,但我显然希望它是动态的:

长话短说,自定义过滤器函数返回到 array_filter() 函数,如下所示:

return ($arr['colour']=='Red' || $arr['colour']=='White');

如果像上面那样硬编码,这可以正常工作,并按预期过滤数组以仅显示红色或白色的产品。但是,我需要它是动态的。

那么如何构造一个值的字符串,然后在 return 语句中使用它呢?

例如:

$var = "$arr['colour'] == 'Red' || $arr['colour'] == 'White'";
return ($var);

它不起作用。我试过用 eval() (反正我不想用这个!),还是不行。

我有一个循环如下从数组构造字符串:

// $value=array of filters e.g colour=Black, colour=Red

$filterparts = explode("=", $value);

$filters[] = '$arr[\'' . $filterparts[0] . '\'] == \'' . $filterparts[1] . '\'';
// Creates array e.g $arr['colour'] = 'Red'

$imploded_filter = implode(" || ", $uniquefilters);
// Creates string, e.g. $arr['colour'] = 'Red' || $arr['colour'] = 'White'

所以,如果我回显 $imploded_filter 我会得到我想要返回的提取字符串:

echo $imploded_filter;
// Outputs $arr['colour'] = 'Red' || $arr['colour'] = 'White'

如果我这样做了

return($imploded_filter);

它显然没有将字符串评估为硬代码,那我该怎么办?我需要对字符串做些什么或以不同的方式返回它,还是构建我需要以完全不同的方式返回的代码?

【问题讨论】:

    标签: php arrays string eval array-filter


    【解决方案1】:

    可以动态指定数组键。不需要eval()

    $value = $array[$key];
    

    您可以构建过滤器列表并在array_filter() 回调中匹配每个过滤器:

    $filters = array(
        array('colour', array('white', 'blue')), // Multiple accepted values (OR)
        array('material', 'Fine Bone China'), // Single accepted value
    );
    
    $filtered = array_filter($products, function ($item) use ($filters) {
        // Match all filters
        foreach ($filters as $filter) {
            // Detect multi-value filter
            $isArrayFilter = is_array($filter[1]);
    
            if (
                // Check if multi-value filter doesn't match
                $isArrayFilter && !in_array($item[$filter[0]], $filter[1])
                // Check if a single-value filter doesn't match
                || !$isArrayFilter && $item[$filter[0]] != $filter[1]
            ) {
                // Filter doesn't match - exclude the item
                return false;
            }
        }
    
        // All filters match - include the item
        return true;
    });
    

    【讨论】:

    • 谢谢,这似乎做得很好,是否超出了这个问题的范围(甚至是 array_filter 函数!)询问它是否可以工作,所以它的 OR 中的所有值一个类别(例如颜色),然后将其与其他类别结合起来?
    • 例如 colour="red" ||颜色=“蓝色”和材料=“金属”|| material="paper" ...目前它只是在检查它们是否存在,这很好,但是很高兴将这个功能添加到它。
    • 您可以支持$filterparts[1] ($filter[1]) 中的数组值。如果它是一个数组,则将其与in_array($arr[$filter[0]], $filter[1]) 匹配,而不仅仅是比较它。
    • 嗨,我真的很抱歉,但你能不能帮我把它说得通俗一点,或者给我一个例子,我的大脑今天很疲惫,哈哈。说我有一个数组 colour="red", colour="blue", material="wood" 如何将所有颜色匹配为 OR 然后说 AND material= wood,所以它需要过滤“all red OR由木头制成的蓝色产品”
    • 1) 解析过滤器,因此每个过滤器都具有以下结构:['property', 'value']['property', ['value1', 'value2']](如果提供了多个值)2) 支持array_filter() 回调中的数组过滤器值如下:if (is_array($filter[1]) && in_array($arr[$filter[0]], $filter[1]) || !is_array($filter[1]) && $arr[$filter[0]] == $filter[1]) {
    【解决方案2】:
    $colors = ['Red', 'White'];
    $products = array_filter($products, function ($product) use ($colors) {
        return in_array($product['color'], $colors);
    });
    

    几乎没有任何理由或需要“动态创建 PHP 源代码”。总有一种操作可以对任意数量的元素执行您想要的操作,而无需连接 || 运算符。这里in_array 是一个非常好的函数,可以针对多个值测试一个值。您可以使用 use ($colors) 动态传入颜色数组。

    对于古老的 PHP 版本,最合理的解决方法是使用类来近似匿名回调:

    class InArrayFilterCallback {
    
        public $data = array();
        public $key;
    
        public __construct($data, $key) {
            $this->data = $data;
            $this->key = $key;
        }
    
        public callback($item) {
            return in_array($item[$this->key], $this->data);
        }
    
    }
    
    $products = array_filter($products, array(new InArrayFilterCallback($colors, 'color'), 'callback'));
    

    当然,您也可以只使用简单的foreach 循环...

    【讨论】:

    • 嗨,谢谢@deceze,你知道这是否适用于 PHP
    • 这从 5.3 开始工作,因为引入了匿名函数。对于更旧的版本(现在肯定是古老的!),有许多可能的解决方法。需要支持什么版本?
    • 您好,我在 5.4 上,但其中任何一个都无法正常工作:/ 解决方法只是白屏,并且由于某种原因甚至没有给出错误(!)
    • 好吧,我太笨了,当我的数组中它是“颜色”时,我没有看到美国的“颜色”拼写......我认为现在一切正常,只需要解决一些问题还是!
    • 所以回到使这个动态的原始问题,我将如何转换您的解决方案以允许它传递颜色、材料等,此时您已经有了 $product 之类的东西['color'], $colors 是硬编码的,而我有一个值数组,如“material=metal”、“color”="Black" 等,我需要动态传递给过滤器?
    【解决方案3】:

    使用in_array 函数,如下所示:

    $filters = [
        'colour' => [
            'red',
            'blue',
        ]
    ];
    array_filter($list, function ($item) use ($filters) {
        foreach ($filters as $index => $filter) {
            if (!in_array($item[$index], $filter)) {
                return false;
            }
        }
        return true;
    });
    

    创建一个字符串并对其进行评估从来都不是一个好主意。

    【讨论】:

      猜你喜欢
      • 2011-11-03
      • 1970-01-01
      • 1970-01-01
      • 2018-12-21
      • 2021-09-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多