简体   繁体   中英

PHP: How can I apply my variables to a dynamic set of conditions?

Consider an array as a set of generic or abstract conditional statements:

$conditionSet = array(
    'condition1' => '$a > $b', 
    'condition2' => '$c != $d', 
    'condition3' => '$f < $e'
);

Is it possible to apply the variables that I have in my current scope of execution to the conditions in the array on-the-fly - without having to try and parse the statements? ie

$a = 1; 
$b = 2; 
$c = 3; 
$d = 4;
$e = 5; 
$f = 6; 

if ( $conditionSet['condition1'] && 
     $conditionSet['condition2'] && 
     $conditionSet['condition3'] )
{
    // PASS: do something    
} else {        
    // FAIL: do something else
}

you want to use array_reduce.

$conditionSet = array(true, false, true);

$conditionReduced = array_reduce
(
    $conditionSet,
    function($a,$b)
    {
        return $a && $b;
    },
    true
);

if($conditionReduced)
{
    echo 'all conditions are true';
}
else
{
    echo 'one or more conditions are false';
}

I think I see what you are getting at - the other answers here assumed that your $conditionSet is a collection of predetermined booleans which is perfectly plausible but your edit suggests that you want to be able to assert that n number of parameters match a given set of generic checks at any given time?

Instead of coupling state to particular parts of your application you could group callable "comparison" functions (assertions) . Although It may not adhere to it strictly in this example I believe this forms - in part - the basis of a functional programming approach.

function assertion(){
    $args = func_get_args();
    foreach($args[0] as $assert)
        if(!call_user_func_array($assert, array_slice($args, 1)))
            return false;
    return true;
}

$conditionSet = [
    function($a, $b){ return $a > $b; },
    function($a, $b, $c, $d){ return $c != $d; },
    function($a, $b, $c, $d, $e, $f){ return $f < $e; }
];

if( assertion($conditionSet, 2, 1, 3, 4, 6, 5) )
    echo 'All conditions true';
else 
    echo 'One or more conditions false';

demo

Variables $a through $f could be passed as a single array but I wanted to demonstrate the flexibility.


You could of course just use eval but frankly that would be Fugly (capital F) ! This method is more robust and arguably the proper way to approach your problem. I also think it's rather pretty but that's subjective :) - I'm not sure how it would affect performance.

You should check out the documentation on call_user_func and call_user_func_array as they are quite powerful tools.


The following is just for completeness and should not be used in production code...

I should have also pointed out that PHP has it's own assert function which accepts callable arguments (admittedly I wasn't even aware of this myself) but it doesn't accept a set of several. In any case here's a simple demonstration:

$a = 2; $b = 3;
if( assert(function($a, $b){ $a > $b; }) )
    echo '$a is greater than $b';

If you don't end up reading the assert documentation please be aware there's a part that reads:

"... should be used as a debugging feature only ... should not be used for normal runtime operations like input parameter checks. As a rule of thumb your code should always be able to work correctly if assertion checking is not activated."

I'm not sure if this refers to an option that applies to the the function in it's entirety or just it's ability to evaluate strings (most likely the former) - which I'm guessing works in a similar way to eval .

See this post on why eval is evil .

It's not 100% clear what your final intention would be, for simplistic comparison this is somewhat overkill but I can see a use for the first solution I posted if you are dealing with more complex logic.

Array array_filter function will filter out all false expression when used without a callback function:

if(count(array_filter($conditionSet)) == count($conditionSet)){
    //do somthing
}else{
    //do other
}

If all of the conditions are true, the count should match between prefiltered and post-filtered array.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM