Placing a foreach loop inside an if condition - php

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!

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) {
// ...
}

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.

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
}
}

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);
}

Related

what is the best way for search in json file in php?

hi i have many data files in json format in a folder.
now i want to search a filed in them .my search word maybe not exist in some of them and may be exist in one of them files.
i have read this function and if not exits in a file i call the function to read another file.
when i echo the result show me and works fine but return not working and no data returned.
function get_shenavari_in_files($search,$type)
{
static $counter =1 ;
$darsadi = 0;
$find = false;
$file_name = get_files_in_dir(); // make an array of file names
$file_number = count($file_name)-$counter ;
$file="files/" .$file_name[$file_number];
$file_data = read_json($file);
for($i = 0 ; $i<count($file_data) ; $i++)
{
if($file_data[$i][$type] == $search )
{
$darsadi = $file_data[$i]['darsadi'] ;
$find = true;
echo $darsadi ; //this works and show the data
return $darsadi; // this is my problem no data return.
break;
}
}
if($find == false)
{
$counter ++;
get_shenavari_in_files($search,$type);
}
}
var_dump(get_shenavari_in_files('Euro','symbol')); //return null
Once you recurse into get_shenavari_in_files, any found value is never returned back to the inital caller, i.e. instead of
if($find == false)
{
...
get_shenavari_in_files($search,$type);
}
you simply need to prepend the function call with a returnstatement
if($find == false)
{
...
return get_shenavari_in_files($search,$type);
}
Having said that, I would try a much simpler (and thereby less error-prone) approach, e.g.:
function get_shenavari_in_files($search, $type) {
$files = glob("files/*.json"); // Get names of all JSON files in a given path
$matches = [];
foreach ($files as $file) {
$data = json_decode(file_get_contents($file), true);
foreach ($data as $row) {
if (array_key_exists($type, $row) && $row[$type] == $search) {
$matches[$file] = $search;
}
}
}
return $matches;
}
This way, you would be able to eliminate the need for a recursive call to get_shenavari_in_files. Also, the function itself would become more performant because it doesn't have to scan the file system over and over again.

How to start a foreach loop with a specific value in PHP?

I need to start a for each loop at certain value, ex foreach($somedata as $data) Here I want to start doing some stuff only when the value of that data is "something"
I want to start doing something only after a specific value.
foreach($somedata as $data){
if($data == 'Something'){
//start processing, ignore all the before elements.
}
}
I tried break continue nothing seems to work as I wanted
For clarity, it's probably better to pre-process your array before looping over it. That way the logic inside your loop can purely focus on what it's supposed to do.
$arr = ['foo', 'something', 'bar'];
$toProcess = array_slice($arr, array_search('something', $arr));
foreach ($toProcess as $element) {
echo $element, PHP_EOL;
}
outputs
something
bar
How about using a indicator variable to achieve this.
$starter = 0;
foreach($somedata as $data){
if($data == 'Something'){
$starter = 1;
}
if(starter == 1){
//start processing, ignore all the before elements.
}
}
You'll need to keep a flag whether you have already encountered the desired value or not:
$skip = true;
foreach (... as $data) {
if ($data == 'something') {
$skip = false;
}
if ($skip) {
continue;
}
// do something
}
$skip = true;
foreach($somedata as $data){
if($data == 'Something'){
$skip = false;
}
if($skip) {
continue;
}
//start processing, ignore all before $skip == false.
}
If you want to process the values only from the moment you identify one value, then you can use a flag :
$flag = false;
foreach($somedata as $data){
if($flag OR $data == 'Something'){
$flag = true;
// processing some stuff
}
}
Once the flag is reset to true, whatever the current value is, the content of your if will be executed.

Remove a line from file if it exists

I'm getting used to PHP and trying to remove a line from a file (if it exists) and resave the file.
So if I had the file
user1
user2
user3
user4
I could use
if(existsAndRemove("user3")){
do thing
}
I've tried using code similar to the code below but it sometimes bugs out and will only remove a line if it is last in the file. I have no idea how to fix this.
$data2 = file("./ats.txt");
$out2 = array();
foreach($data2 as $line2) {
if(trim($line2) != $acc) {
$out2[] = $line2;
}
}
$fp2 = fopen("./ats.txt", "w+");
flock($fp2, LOCK_EX);
foreach($out2 as $line2) {
fwrite($fp2, $line2);
}
flock($fp2, LOCK_UN);
fclose($fp2);
}
}
Any help at all would be greatly appreciated, and i would also appreciate if you could explain the code too so I could easier learn from it!!
Thank you.
If the file size is small enough that you're not worried about reading it all into memory, you could do something more functional
// Read entire file in as array of strings
$data = file("./ats.txt");
// Some text we want to remove
$acc = 'user3';
// Filter out any lines that match $acc,
// ignoring any leading or trailing whitespace
//
$filtered_data = array_filter(
$data,
function ($line) use ($acc) {
return trim($line) !== $acc;
}
)
// If something changed, write the file back out
if ($filtered_data !== $data) {
file_put_contents('./ats.txt', implode('', $filtered_data));
}
Something like this might work:
function remove_user($user) {
$file_path = "foo.txt"
$users = preg_split("[\n\r]+", file_get_contents($file_path));
foreach ($users as $i => $existing) {
if ($user == $existing) {
$users = array_splice($users, $i, 1);
file_put_contents($file_path, implode("\n", $users));
break;
}
}
}
Should be much easier since you're already using file():
$data2 = file("./ats.txt", FILE_IGNORE_NEW_LINES);
unset($data2[array_search('user3', $data2)]);
file_put_contents("./ats.txt", implode("\n", $data2));
Or to check if it exists first:
$data2 = file("./ats.txt", FILE_IGNORE_NEW_LINES);
if( ($key = array_search('user3', $data2)) !== false ) {
unset($data2[$key]);
file_put_contents("./ats.txt", implode("\n", $data2));
}

Data Not Being Parsed Correctly

I have a simple data format that goes as follows:
stuff/stuff/stuff
An example would be:
data/test/hello/hello2
In order to retrieve a certain piece of data, one would use my parser, which tries to do the following:
In data/test/hello/hello2
You want to retrieve the data under data/test (which is hello). My parser's code is below:
function getData($data, $pattern)
{
$info = false;
$dataLineArray = explode("\n", $data);
foreach($dataLineArray as &$line)
{
if (strpos($line,$pattern) !== false) {
$lineArray = explode("/", $line);
$patternArray = explode("/", $pattern);
$iteration = 0;
foreach($lineArray as &$lineData)
{
if($patternArray[$iteration] == $lineData)
{
$iteration++;
}
else
{
$info = $lineData;
}
}
}
}
return $info;
}
However, it always seems to return the last item, which in this case is hello2:
echo getData("data/test/hello/hello2", "data/test");
Gives Me;
hello2
What am I doing wrong?
If you want the first element after the pattern, put break in the loop:
foreach($lineArray as $lineData)
{
if($patternArray[$iteration] == $lineData)
{
$iteration++;
}
elseif ($iteration == count($patternArray))
{
$info = $lineData;
break;
}
}
I also check $iteration == count($patternArray) so that it won't return intermediate elements, e.g.
/data/foo/test/hello/hello2
will return hello rather than foo.
P.S. There doesn't seem to be any reason to use references instead of ordinary variables in your loops, since you never assign to the reference variables.

read file matching lines using array using php

I want to be able to read through a plain text file and match a number of lines without the need to iterate over the text file multiple times. I am passing in an array with a list of strings I would like to match, which ideally, I would like to put into an array.
I can achieve the desired result using the code below, but it necessitates the reading of the text file multiple times.
function readFile($line){
$contents = file("test.txt");
if(preg_match("/$line*/i", $val)){
return($val);
}
}
Ideally, I would like to do the following:
// pass an array to the funciton which will parse the file once and match on the elements defined.
$v = readFile(array("test_1", "test_2", "test_2", "test_3"));
// return an array with the matched elements from the search.
print_r($v);
Any help would be much appreciated.
Thanks all!
$val = array();
foreach ($contents as $file) {
foreach ($line as $l) {
if (stristr($file, $l)) {
$val[] = $file;
break; // Don't need to check the other $line values
}
}
}
$val = array();
foreach ($contents as $file) {
foreach ($line as $l) {
if (stristr($file, $l) {
$val[] = $file;
}
}
}
Even if you want to stick with preg_match, the "*" is unnecessary.

Categories