views:

123

answers:

4

I am needing to create a foreach statement that will run through and create conditions for a conditional statement. I wrote this bit of code, not expecting it to work, and of course it didn't...

$filename = "whitelist.txt";
$handle = fopen($filename, 'r');
$whitelist = fread($handle, filesize($filename));
fclose($handle);
$whitelist = explode("\n", $whitelist);
if (
  foreach ($whitelist as $value) {
    strpos($ref, 'http://'.$value.'/')===0 ||
  }
)

So, should this ever be able to work? Or am I just crazy? If there is really no way to put a loop in the condition like this, could someone suggest a better way to do this? Much appreciated!

+7  A: 

Compute the value beforehand, you cannot use a loop as an expression:

$val = false;

foreach ($whitelist) {
   $val = $val || strpos($ref, 'http://'.$whitelist.'/')===0;
}

if($val) {
    // ...
}
Felix Kling
In that case you might want to simply `if(strpos(...)===0) {$val=true; break;}` to do less work in easy cases.
viraptor
This works beautifully with a bit of tweaking to fit my situation. Thanks very much for the attention Felix!
Ben
@Ben: You're welcome. As @viraptor said, you can improve the code they way he described. Because if `strpos($ref, 'http://'.$whitelist.'/')===0` is once `true`, the whole expression will stay true, so there is no point in testing further possibilties. That is just how logical `OR` works.
Felix Kling
A: 

You have to invert the two statements and put the if inside the for loop. Loop over the whitelist, and once you find a match set a flag and exit the loop using break. Then check that flag after the loop and see if it ever got set.

$allowed = false;

foreach ($whitelist as $url) {
    if (strpos($ref, "http://$url/") === 0) {
        $allowed = true;
        break;
    }
}

if ($allowed) {
    // Do what you want to do.
}

For what it's worth, there are other more expressive languages where you could write the code the way you tried to. In python, for instance, you could write this:

if any(ref.starts_with('http://'+url+'/') for url in whitelist):
    # Found a whitelisted URL.
John Kugelman
A: 

That can't be done because a foreach block returns nothing.

You want something like this:

if (for_any($whitelist,
    function ($arg) use ($ref) { return strpos($ref, 'http://'.$arg.'/')===0; } ) {
    /* ... */
}

with

function for_any(array $arr, $func) {
    return array_reduce($arr,
        function ($a, $v) use ($func) {
            return $a || call_user_func($func, $v);
        }, true);
}
Artefacto
A: 

Compute the condition inside the loop, not beforehand.

$filename = "whitelist.txt";
$handle = fopen($filename, 'r');
$whitelist = file($handle)
fclose($handle);
foreach ($whitelist as $line) {
    if(strpos($ref, 'http://'.$line.'/')) {
       //do stuff
    }
    else {
      // do not do stuff
    }
}
Levi Hackwith