Foreach loop depending on files in directory - php

Is there a way to create a foreach loop, that will run for however many instances of a filename with a sequential number exists in a directory?
For example I have one directory with images. The images will have filenames such as these:
firstname-lastname_before1.jpg
firstname-lastname_after1.jpg
firstname-lastname_before2.jpg
firstname-lastname_after2.jpg
firstname2-lastname2_before1.jpg
firstname2-lastname2_after1.jpg
firstname2-lastname2_before2.jpg
firstname2-lastname2_after2.jpg
This essentially shows photos belonging to two people. Each person has four photos, two sets of two photos, a before and after.
I can already handle the individual names when echoing out, but I'm trying to find a way to set a foreach loop that will find all sequential instances of the condition that's currently applied.
i.e. If I'm viewing a page for one person, the foreach loop should run through all files relating to that person.
At the moment I just have one hard-coded instance of the block I want to loop.
<div class="photo-set col-md-4">
<figure class="cd-image-container">
<?php $procedure = get_post_custom_values('Procedure'); ?>
<img src="<?php echo get_template_directory_uri()."/img/before-after/".preg_replace("/[\s_]/", "-", strtolower($procedure[0]))."_".preg_replace("/[\s_]/", "-", strtolower($post->post_title))."_after1.jpg";?>" alt="Original Image">
<span class="cd-image-label" data-type="original">After</span>
<div class="cd-resize-img">
<img src="<?php echo get_template_directory_uri()."/img/before-after/".preg_replace("/[\s_]/", "-", strtolower($procedure[0]))."_".preg_replace("/[\s_]/", "-", strtolower($post->post_title))."_before1.jpg";?>" alt="Modified Image">
<span class="cd-image-label" data-type="modified">Before</span>
</div>
<span class="cd-handle"></span>
</figure>
</div>
This is just using before1 and after1, as I wanted to style it up first.
So to summarise, my question is: Can I have a foreach loop that will find all files that match the condition below, that are sequentially named, and sort them into a set of 2 (for before and after)?
UPDATE:
I've tried using the glob function, but I'm really not sure this is what I'm looking. After using this code:
$procedures = get_post_custom_values('Procedure');
$procedure = preg_replace("/[\s_]/", "-", strtolower($procedures[0]));
$patientName = preg_replace("/[\s_]/", "-", strtolower($post->post_title));
foreach(glob('img/before-after/*$patientName*/*.jpg') as $filename) {
Nothing is being returned on the page. I'm not sure on how the glob expression should be. As it needs to firstly find a directory that matches $patientName, and then inside there are loads of files with different procedures in the title. Like this for an example:
tummy-tuck_john-smith_before1.jpg
tummy-tuck_john-smith_after1.jpg
tummy-tuck_john-smith_before2.jpg
tummy-tuck_john-smith_after2.jpg
nose-reshaping_john-smith_before1.jpg
nose-reshaping_john-smith_after1.jpg
etc. So how can I code it so that it will pull the correct files (in sets of two, as I have a before and after for each), for the patient name, and the procedure?
UPDATE:
This code also returns nothing, and I don't know why? The $files array is returning as 0.
$procedures = get_post_custom_values('Procedure');
$procedure = preg_replace("/[\s_]/", "-", strtolower($procedures[0]));
$patientName = preg_replace("/[\s_]/", "-", strtolower($post->post_title));
$directory = get_template_directory_uri()."/img/before-after/".$patientName."/";
$files = glob($directory.'*', GLOB_BRACE);
foreach($files as $filename) {
Can someone please help?

You can use glob() function. You can pass first param as pattern and loop through the results of the function.
Example
foreach(glob('[a-zA-Z0-9]+-[a-zA-Z_0-9]+.jpg') as $filename)
{
echo $filename;
}
You can also use \w but it depends on your conditions.

Related

Finding a filename match in two directories and writing the matched filename to an array

I have looked on Stackover for a simular issue but can't find a solution.
I am trying to write a script that looks at the content of two directories to findout if a filename match can be found in both
directories. If a match is found write the name of the matched filename to an array.
The first thing I am doing is using""scandir" to create an array of data from the first directory.
In the "foreeach"loop through the array from the "scandir" result and perform a "file_exists" using the variable "$image1"
to fing a match in the seconds directory "allimages/boardsclean". If a match is found write the filename to the "$found_images" array.
Testing the result of the "$found_images" array I am not seeing the result I was expecting.
Can anyone see where I am going wrong?
$c1 = 0;
$c2 = 0;
$scan = scandir('allimages/temp1');
$found_images = array();
foreach ($scan as $image1) {
if (file_exists('allimages/temp1/'.$image1) && ('allimages/temp2/'.$image1)) {
echo "file match in Scan $image1</br>";
$found_images[] = 'allimages/adminclean/'. $image1;
$c1++;
}
}
echo $c1."</br>";
foreach ($found_images as $image3) {
echo "file match $image3 </br>";
$c2++;
}
echo $c2."</br>";
First, you don't need to test for the file from the scandir because, well... it's already there and was returned. Second, you don't test for the one in the second directory. You need:
if(file_exists('allimages/temp2/'.$image1)) {
However, just scan both directories and compute the intersection of the returned arrays which will give you files common to both directories. It's as simple as:
$found = array_intersect(scandir('allimages/temp1'), scandir('allimages/temp2'));
Then you can filter out directories if you want and add allimages/adminclean/ in the array or when needed.

PHP If-Else does not work for comparing filecontents

I am trying to make a PHP application which searches through the files of your current directory and looks for a file in every subdirectory called email.txt, then it gets the contents of the file and compares the contents from email.txt with the given query and echoes all the matching directories with the given query. But it does not work and it looks like the problem is in the if-else part of the script at the end because it doesn't give any output.
<?php
// pulling query from link
$query = $_GET["q"];
echo($query);
echo("<br>");
// listing all files in doc directory
$files = scandir(".");
// searching trough array for unwanted files
$downloader = array_search("downloader.php", $files);
$viewer = array_search("viewer.php", $files);
$search = array_search("search.php", $files);
$editor = array_search("editor.php", $files);
$index = array_search("index.php", $files);
$error_log = array_search("error_log", $files);
$images = array_search("images", $files);
$parsedown = array_search("Parsedown.php", $files);
// deleting unwanted files from array
unset($files[$downloader]);
unset($files[$viewer]);
unset($files[$search]);
unset($files[$editor]);
unset($files[$index]);
unset($files[$error_log]);
unset($files[$images]);
unset($files[$parsedown]);
// counting folders
$folderamount = count($files);
// defining loop variables
$loopnum = 0;
// loop
while ($loopnum <= $folderamount + 10) {
$loopnum = $loopnum + 1;
// gets the emails from every folder
$dirname = $files[$loopnum];
$email = file_get_contents("$dirname/email.txt");
//checks if the email matches
if ($stremail == $query) {
echo($dirname);
}
}
//print_r($files);
//echo("<br><br>");
?>
Can someone explain / fix this for me? I literally have no clue what it is and I debugged soo much already. It would be heavily gracious and appreciated.
Kind regards,
Bluppie05
There's a few problems with this code that would be preventing you from getting the correct output.
The main reason you don't get any output from the if test is the condition is (presumably) using the wrong variable name.
// variable with the file data is called $email
$email = file_get_contents("$dirname/email.txt");
// test is checking $stremail which is never given a value
if ($stremail == $query) {
echo($dirname);
}
There is also an issue with your scandir() and unset() combination. As you've discovered scandir() basically gives you everything that a dir or ls would on the command line. Using unset() to remove specific files is problematic because you have to maintain a hardcoded list of files. However, unset() also leaves holes in your array, the count changes but the original indices do not. This may be why you are using $folderamount + 10 in your loop. Take a look at this Stack Overflow question for more discussion of the problem.
Rebase array keys after unsetting elements
I recommend you read the PHP manual page on the glob() function as it will greatly simplify getting the contents of a directory. In particular take a look at the GLOB_ONLYDIR flag.
https://www.php.net/manual/en/function.glob.php
Lastly, don't increment your loop counter at the beginning of the loop when using the counter to read elements from an array. Take a look at the PHP manual page for foreach loops for a neater way to iterate over an array.
https://www.php.net/manual/en/control-structures.foreach.php

Getting File Name Details from Image File

I am looking for a way to grab details from a file name to insert it into my database. My issue is that the file name is always a bit different, even if it has a pattern.
Examples:
arizona-911545_1920.jpg
bass-guitar-913092_1280.jpg
eiffel-tower-905039_1280.jpg
new-york-city-78181_1920.jpg
The first part is always what the image is about, for example arizona, bass guitar, eiffel tower, new york city followed by a unique id and the width of the image.
What I am after would be extracting:
name id and width
So if I run for example getInfo('arizona-911545_1920.jpg');
it would return something like
$extractedname
$extractedid
$extractedwidth
so I could easily save this in my mysql database like
INSERT into images VALUES ('$extractedname','$extractedid','$extractedwidth')
What bothers me most is that image names can be longer, for example new-york-city-bank or even new-york-city-bank-window so I need a safe method to get the name, no matter how long it would be.
I do know how to replace the - between the name, that's not an issue. I am really just searching for a way to extract the details I mentioned above.
I would appreciate it if someone could enlighten me on how to solve this.
Thanks :)
One of the simplest way in this case is to use regexp, for example:
preg_match('/^(\D+)-(\d+)_(\d+)/', $filename, $matches);
// $matches[1] - name
// $matches[2] - id
// $matches[3] - width
This is the main Idea.
Let's pick a file first.
Filename will be "bass-guitar-913092_1280.jpg"
First of all we will Split this with explode, to dot( . ) in variable $Temp
This will give us an Array of bass-guitar-913092_1280 and jpg
We will choose to have the first Item of the array to continue since is the name we are interested in so we will get it with $Temp[0]
After this we will Split it Again this time to ( _ ).
Now we will have an array of bass-guitar-913092 and 1280
The Second value of the Array is what We need so we will pick it with $Temp[1]
The Last part is simple as the others, We will now Split the file name $Temp[0] with ( - ) We will get the Last value of it which is the id $Temp[count($Temp)-1] and we will remove this from the array list, and Connect everything else with implode and the delimeter we want
Now we can use also the Function ucwords to Capitalize every first letter of each word on the main name.
In the following code, there are 2 ways of getting the name, one with lowercase letters, and one with uppercase first letters of each word, uncomment what you want.
Edited Code as a Function
<?php
function ExtractFileInfo($fileName) {
$Temp = explode(".",$fileName);
$Temp = explode("_",$Temp[0]);
$width = $Temp[1];
$Temp = explode("-",$Temp[0]);
$id = $Temp[count($Temp)-1];
unset($Temp[count($Temp-1)]);
// If you want to have the name with lowercase letters Uncomment the Following:
//$name = implode(" ",$Temp);
// If you Want to Capitalize every first letter of the name Uncomment the Following:
//$name = ucwords(implode(" ",$Temp));
return array($name,$id,$width);
}
?>
This will return an Array of 3 Elements Name, Id and Width
Extracting the data you are looking for would be best via a regex pattern like the following:
(.+)-(\d+_(\d+))
Example here: https://regex101.com/r/oM5bS8/2
preg_match('(.+)-(\d+_(\d+))',"<filename>", $matches);
$extractedname = $matches[1];
$extractedid = $matches[2];
$extractedwidth = $matches[3];
EDIT - Just reread the question and you are looking for extraction techniques not how to post the image from a page to your backend. I will leave this here for reference.
When you post files via a form in html to a PHP backend there are few items that are needed.
1) You need to ensure that your form type is multi-part so that it knows to pass the files along.
<form enctype="multipart/form-data">
2) Your php backend needs to iterate over the files and save them accordingly.
Here is a sample of how to iterate over the files that are being submitted.
foreach($_FILES as $file) {
$n = $file['name'];
$s = $file['size'];
if (!$n) continue;
echo "File: $n ($s bytes)";
}

Search text files and display results with PHP

I have a folder (blogfiles/posts) with various text files, numbered (1.txt, 2.txt, 3.txt...) and they each hold a post for a blog (I haven't learned SQL yet). I'm trying to make a search engine for it that will take a query from a text box (done with this part), then search the files for each word in the query, and return the results (possibly in order of the number of times the word occurs).
Each text file looks like this:
Title on Line 1
Date Posted on Line 2 (in Month Date, Year form)
Post body to search on lines 3 and up
I currently have this code:
<?php
$q = $_GET["q"];
$qArray = explode(" ", $q);
//preparing files
$post_directory = "blogfiles/posts/";
$files = scandir($post_directory, 1);
$post_count = (count($files)) - 2;
$files = array_pop($files); // there are 2 server files I want to ignore (#1)
$files = array_pop($files); // there are 2 server files I want to ignore (#2)
foreach ($files as $file) {
//getting title
$post_path = $post_directory . $file;
$post_filecontents = file($post_path);
$post_title = $post_filecontents[0];
echo "<tr><td>" . $post_title . "</td></tr>";
}
if ($post_count > 2) {
$postPlural = "s";
}
echo "<tr><td>" . $post_count . " post" . $postPlural . ".";
?>
I'll apologize now for the formatting, I was trying to separate it to troubleshoot.
Any help to get this working would be greatly appreciated.
There are many ways to search files.
use preg_match_all function to match pattern for each file.
use system() function to run external command like grep (only available under *nix).
use strpos function ( not recommended because of low performance and lack of support of pattern ).
If you will face a big traffic you'd better use pre-build indexes to accelerate the search. for example split the posts into tokens ( words ) and add position info along with the words, when user search the some words you can just split the words first and then look for the indexes. It's simpler to discribe this method than to implement it. You may need a existing full-text search engine like Apache Lucene.

PHP syntax equivalent to SQL %

I have a folder unit_images that is full of images with random names except they have a prefix that corresponds to a PRIMARY KEY in a db table.
1_4534534fw4.jpg
2_43534tw4t45.png
You get my point. I am using YoxView to view images and am doing something like this:
<?php
$query = "SELECT id FROM images WHERE unit = ".$_GET['id']."";
$result = mysqli_query($con, $query);
echo '<div class="yoxview">';
while ($row = mysqli_fetch_assoc($result))
{
echo '<img src="unit_images/01.jpg" alt="First" title="First image" />
<img src="unit_images/02.jpg" alt="Second" title="Second image" />'
}
echo '</div>';
?>
I want to list the images from my folder unit_images WHERE the unit is the one currently being shown.I just do not know how to tell PHP the filename. I want to do something similar to a 1_% in SQL. Does that make sense? Since I do not know what the rest of the filename looks like I just need to tell php it doesn't matter.
The closest equivalent to SQL's % wildcard that works for files is the shell's * wildcard, which is available in php through the glob() function. You can iterate through its results as follows:
foreach (glob("unit_images/1_*.jpg") as $filename) {
echo '<img src="unit_images/' . htmlspecialchars(basename($filename))
. '" />';
}
If I understand you correctly, you want to get a list of items in a directory with a certain prefix.
Step 1 (use sandir() to determine the items in the directory):
$files = scandir('unit_images');
Step 2 (eliminate the unwanted image names):
for ($i=0; $i<count($files); i++)
{
$file = $files[i];
$prefix = explode("_", $file)[0];
if ($prefix != $_GET['id'])
{
unset($files[i]);
}
}
$files is now an array of only the file names prefixed with $_GET['id]
My advice would be to store the whole name of the file in a column so that you can reference it directly instead of having to search in the file system for a matching name.
Having said that, you can search for a file using the glob PHP function.
Maybe you can do something like this:
glob("unit_images/<YOUR_PRIMARY_KEY>_*.{png,jpg}", GLOB_BRACE);

Categories