如何返回条件中评估的变量的名称

时间:2018-09-14 14:57:30

标签: php

我想找出在条件中检查时第一个具有假值的变量的名称。例如:

regex_pattern = re.compile(r"\d(\D+)(?=\d)")

PHP评估括号中的条件,如果变量之一为false,则执行代码。诀窍是如何使PHP告诉我哪个变量是假的,而不用一次又一次地手动检查它们。有任何想法吗?

到目前为止,我有一个主意,但是效率很低。

if (!$value1 || !$value2 || !$value3){

    // return the name of the first false variable - but how?
}

4 个答案:

答案 0 :(得分:1)

您应该能够使用简单的FOR循环遍历您的值。

$values = array($value1, $value2, $value3);
for($i = 0; $i < count($values); $i++){
if($values[$i] == false){echo "Value number $i is false.";}
}

这将为您提供开发人员友好的代码读数(如从0开始的按数组排列)。如果您希望更多的读数与您的值同名,例如$ value1,$ value2,$ value3-您可以对以下内容进行小的更改:

$values = array($value1, $value2, $value3);
for($i = 0; $i < count($values); $i++){
if($values[$i] == false){echo "Value number " . ($i + 1) . "is false.";}
}

我在这里提供了一个有效的ideone示例: https://ideone.com/cdiatK

答案 1 :(得分:1)

因为您要求输入变量名...

function varName( $v ) {
    $trace = debug_backtrace();
    $vLine = file( __FILE__ );
    $fLine = $vLine[ $trace[0]['line'] - 1 ];
    preg_match( "#\\$(\w+)#", $fLine, $match );
    print_r( $match );
}

$value1 = true;
$value2 = true;
$value3 = false;

$values = array($value1, $value2, $value3);
for($i = 0; $i < count($values); $i++)
{

    if($values[$i] == false)
    {
        varName($values[$i]);
    }

}

答案 2 :(得分:1)

由于对变量的重复迭代(在if语句和checkFalseVars函数中),听起来您不喜欢当前的实现。您的实现是正确的,因为如果您想找出哪个变量为假,则需要对它们进行迭代,并且没有办法解决。

因此,由于您不想重复任何操作,因此此时您需要退后一步并评估您的代码。由于无论如何都必须遍历变量,因此您最好让if语句查看该循环的结果,而不要让if语句评估每个变量本身。由于checkFalseVars函数在所有变量都不为假的情况下返回假值,因此您可以简单地让if语句检查该函数的输出。

这是您代码的一个小重构-我将您的checkFalseVars函数保持原样。这具有将变量检查保留在单个函数中的附加好处,因此,如果您添加更多要检查的变量,则只需将它们添加到要传递给函数的数组中即可...您不需要还要担心还要使if语句中的变量检查保持最新。

function checkFalseVars($vars){

    foreach($vars as $var){

        $v = $GLOBALS[$var];
        if (!$v){
            return $var;
       }    
    }
    return false;
}  

$value1 = true;
$value2 = false;
$value3 = false;

$vars = array('value1','value2','value3');


/*
// This was the old technique
if (!$value1 || !$value2 ||!$value3){

    return  checkFalseVars($vars);
    // returns 'value2'
}
*/

// This is the new technique:
$falseVar = checkFalseVars($vars);
if ($falseVar !== false) {
    return $falseVar
}

编辑:在您的评论之一中提到:

  

我想从PHP获得它已经知道的信息-哪个变量被评估为false并导致条件被触发。

我想澄清的是,PHP不保留有关if中哪个比较被评估为true或false的信息。即使PHP的if语句正在执行评估以确定if语句的评估结果为true还是false,它也不会将这些评估的结果存储在内存中以供以后在代码中使用。

如果PHP保留了这些信息,那么除了可能会消耗大量内存外,使用它也可能很困难。 if语句可以评估的不仅仅是一个简单的is this variable true or false,而且可以评估很多不同的表达式。

答案 3 :(得分:1)

基于@dustytrash和@rtoyo的建议,我建议您可以通过以下方式修改代码:

function checkfalseVar(){
    //Use debug_trace() to find the line number that called this function
    $trace = debug_backtrace();
    //Get the contents of the current file.
    $vLine = file( __FILE__ );
    //Get the text of the line of code that called the function
    $fLine = $vLine[ $trace[0]['line'] - 1 ];
    //Use a regular expression to get the list of variable names that were passed as arguments
    preg_match_all( "#\\$(\w+)#", substr($fLine,stripos($fLine,'checkfalseVar')), $match );

    //Loop through each variable name in the argument, to see if that particular argument is null
    foreach($match[1] as $k=>$v){
        // Evaluate if the value of the argument is false; if it is, then return the name.
        if(!func_get_arg($k)) return $v;
    }
    return false;
}

$data=7;
$data2=false;
$data3='';

if(false!==($false=checkfalseVar($data,$data2,$data3))){
      print($false);//output data2;
}

但是,它不一定在每种情况下都有效(请在下面的评论中查看原因)。

经过深思熟虑,我发现了另一个实现,该实现比第一个版本稍微复杂一些,使用起来也不少,

function checkfalseVar2(){
    //define a static variable to track function calls in order to allow  search on same line
        static $counter=0;
     //Use debug_trace() to find the line number that called this function
    $trace = debug_backtrace();
    //Get the contents of the current file.
    $vContent = file_get_contents(__FILE__);
    //get all newlines occurrences in order to allow multiple lines search
    preg_match_all('#\n#',$vContent,$newlines,PREG_OFFSET_CAPTURE);
    $i=0;
    $newlineE=$newlines?$newlines[0][$trace[0]['line']+1][1]:0;  
    //found all matches which fit the $trace variable characteristics
    do{
        $newlineS=$newlines?$newlines[0][$trace[0]['line'] - $i][1]:0;
        $sub=substr($vContent,$newlineS,$newlineE-$newlineS);
        preg_match_all('#checkfalseVar2#i',$sub,$match,PREG_OFFSET_CAPTURE);
        $i++;
    }while(!$match[0]);
    isset($match[0][$counter])?$occurrence=$match[0][$counter][1]+$newlineS:$occurrence=$match[0][0][1]+$newlineS;
    //get the list of the functions args as a string
    $signature='';
    $r=$l=0;
    $start=false;
    for($i=$occurrence,$length=strlen($vContent);$i<$length;$i++){
        if($r===$l&&$l!==0&&($l+$r)%2===0) break;
        if($vContent[$i]==='('){
            if(!$start)
                $start=true;
            $r++;
        }

        if($vContent[$i]===')'&&$start){
            $l++;
        }
        if($start)
            $signature .=$vContent[$i];
    }
    //get only parameters as array
    preg_match_all("#\\$(\w+)#",$signature,$parameters);
    $counter++;
    //loop through the values to return the first false ,null or empty occurrence
     foreach($parameters[1] as $k=>$v){
        if(!func_get_arg($k)) return $v;
    }
    return false;//return false if every variables cast to boolean are true
}

您可以轻松地做到这一点:

$data=7;
$data2=false;
$data3='';
$data4=null;
if(($false=checkfalseVar2($data,$data2,$data3))
    &&$true=
checkfalseVar2(/**/$data4/**/,$data2,$data3)){
      print($false);// output data2 
      print($true);// output data4
}

请注意,现在该函数返回不带美元符号$的名称,以允许再次使用代码$GLOBALS[$true]$$true直接在代码中不带eval的方式使用

但是我认为您必须通过手动检查变量来保持良好做法,因为它确实消耗更少

if(!$data){...}elseif(...){}else{} 

因为有时候写更多的收益多于写更少的东西好很多

为此目的编写新功能会浪费一些时间,也许会降低代码的速度,最后也可以像我的情况那样消耗更多的内存,因此也考虑一下...