I'm using the glob function in PHP to browse directories and trying to also match up only the image files. This is working but when I try to count the images in each directory, it repeats the count of the first directory for the others. For example, directory 1 has 6 images and directory 2 has 4 images but when I try to display the count for each directory, it shows 6 images for directory 2 and so forth.
Here is the code I have in place:
public function viewphotoalbumsAction()
{
$identity = $this->identity();
$dirname = array();
$files = array();
foreach (glob(getcwd() . '/public/images/profile/' . $identity . '/albums/*', GLOB_ONLYDIR) as $dir) {
$dirname[] = basename($dir);
foreach (glob($dir . '/*.{jpg,png,gif}', GLOB_BRACE) as $images) {
$files[] = $images;
}
}
//var_dump($files); exit;
$data = array(
'albums' => array_values($dirname),
'files' => $files,
);
return new ViewModel(array('album' => $data['albums'], 'files' => $data['files']));
}
The results of var_dump()
array(9) { [0]=> string(96) "C:\xampp\htdocs/public/images/profile/fooboy/albums/bone mom's album_2017-07-03/massive snow.jpg"
[1]=> string(91) "C:\xampp\htdocs/public/images/profile/fooboy/albums/bone mom's album_2017-07-03/mom-jon.jpg"
[2]=> string(90) "C:\xampp\htdocs/public/images/profile/fooboy/albums/bone mom's album_2017-07-03/sunset.jpg"
[3]=> string(85) "C:\xampp\htdocs/public/images/profile/fooboy/albums/random photos_2017-07-02/cref.jpg"
[4]=> string(88) "C:\xampp\htdocs/public/images/profile/fooboy/albums/random photos_2017-07-02/diploma.jpg"
[5]=> string(86) "C:\xampp\htdocs/public/images/profile/fooboy/albums/random photos_2017-07-02/eeyor.jpg"
[6]=> string(93) "C:\xampp\htdocs/public/images/profile/fooboy/albums/random photos_2017-07-02/frother-jaws.jpg"
[7]=> string(88) "C:\xampp\htdocs/public/images/profile/fooboy/albums/random photos_2017-07-02/frother.jpg"
[8]=> string(93) "C:\xampp\htdocs/public/images/profile/fooboy/albums/random photos_2017-07-02/goat_singing.jpg" }
It is getting all the images from each directory as expected but what I really need to do is separate the images so I can have a accurate count for each directory and not just have it show the whole count (9)
The view code:
<div class="w3-col m7">
<div class="w3-row-padding">
<div class="w3-col m12">
<div class="w3-card-2 w3-round w3-white">
<div class="w3-container w3-padding" id="view-photo-albums">
<p class="w3-center">Current Albums</p>
<br>
<?php
foreach ($this->album as $albums):
?>
<p>
<?php echo $albums; ?> - Number of images: <?php echo $this->files; ?>
</p>
<?php endforeach; ?>
</div>
</div>
</div>
</div>
</div>
Any help would be appreciated.
Update:
I cannot use array_values
for $data['files']
as I did for $data['albums']
as it is giving a warning of array to string conversion.
There is a problem in this fragment of code:
foreach (glob($dir . '/*.{jpg,png,gif}', GLOB_BRACE) as $images) {
$files[] = $images;
}
The variable $dir
was used to iterate the array returned by the first invocation of glob()
:
foreach (glob(...) as $dir) {
...
}
Its value after the first foreach
loop ends is the last value that was assigned to it into the foreach
loop.
In the end, $data['albums']
contains all the directory names and $data['files']
contains the names of the files inside the last directory listed in $data['albums']
.
I cannot use array_values for $data['files'] as I did for $data['albums'] as it is giving a warning of array to string conversion.
array_values()
doesn't produce anything new for the $dirname
and $files
. If they are created (!) these two variables contain values indexed by sequential numbers starting with 0
; this is exactly what array_values()
returns.
The intention of the code you posted is not very clear for me. I assume you want to display the list of albums and how many images contain each album.
This is how I would do it:
public function viewphotoalbumsAction()
{
$identity = $this->identity();
// Always initialize the arrays before putting values into them.
// Without this, if the first glob() returns an empty array, the outer
// foreach loop never runs and both $dirname and $files end up being undefined
// and this produces trouble in the code that uses these variables later.
$dirname = array();
// This will be a two dimensional array. It is indexed by directory
// names and contains the lists of files for each directory.
$files = array();
// The outer loop enumerates the albums
foreach (glob(getcwd() . '/public/images/profile/' . $identity . '/albums/*', GLOB_ONLYDIR) as $dir) {
// The directory name is the album name
$albumName = basename($dir);
// Put the album name in $dirname[]
// This is not really needed as we also have the album name
// as key in $files but can be useful if you want to keep more
// information about each album
$dirname[] = $albumName;
// Initialize the list of images of this album
$files[$albumName] = array();
// The inner loop enumerates the images of this directory
foreach (glob($dir . '/*.{jpg,png,gif}', GLOB_BRACE) as $images) {
$files[] = $images;
}
}
// Prepare the data for display
$data = array(
'albums' => $dirname,
'files' => $files,
);
return new ViewModel($data);
}
The view (ignored the HTML wrapper, it is ok as it is):
<?php foreach ($this->files as $albumName => $listFiles): ?>
<p>
<?php echo $albumName; ?> - Number of images: <?php echo count($listFiles); ?>
</p>
<?php endforeach; ?>
As a remark, the inner foreach
loop is not even needed because all it does is to copy one by one the values from the array returned by glob()
into a new array.
It is faster and easier to read and understand to just store the value returned by glob()
into $files[$albumName]
. Since the values stored in $dirname
are never used, this variable can be omitted completely and the function becomes shorter (comments omitted):
public function viewphotoalbumsAction()
{
$identity = $this->identity();
$files = array();
foreach (glob(getcwd().'/public/images/profile/'.$identity.'/albums/*', GLOB_ONLYDIR) as $dir) {
$albumName = basename($dir);
$files[$albumName] = glob($dir . '/*.{jpg,png,gif}', GLOB_BRACE);
}
return new ViewModel(array('files' => $files));
}
I think you need to use foreach for files array also :
//its a demo
foreach(array_combine($a,$b) as $key=>$value) {
echo $key."<br/>".$value;
}//its a demo
Try this:
<div class="w3-col m7">
<div class="w3-row-padding">
<div class="w3-col m12">
<div class="w3-card-2 w3-round w3-white">
<div class="w3-container w3-padding" id="view-photo-albums">
<p class="w3-center">Current Albums</p>
<br>
<?php
foreach(array_combine($this->album,$this->files) as $albums=>$files) :
?>
<p>
<?php echo $albums; ?> - Number of images: <?php echo files; ?>
</p>
<?php endforeach; ?>
</div>
</div>
</div>
</div>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With