我想找出在条件中检查时第一个具有假值的变量的名称。例如:
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?
}
答案 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{}
因为有时候写更多的收益多于写更少的东西好很多
为此目的编写新功能会浪费一些时间,也许会降低代码的速度,最后也可以像我的情况那样消耗更多的内存,因此也考虑一下... >