Home » Php » php – Repeating image count for both directories

php – Repeating image count for both directories

Posted by: admin July 12, 2020 Leave a comment

Questions:

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.

How to&Answers:

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

Answer:

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>

Answer:

I think you need to explicitly declare variable type array i.e.

public function viewphotoalbumsAction()
{
    $identity = $this->identity();
    $dirname = array();
    $files = array();
   // continue ...
}

let me know if works. thanks.

Answer:

May be you need to end the first foreach statement after the end of the second one not before it so each $dir has its own $images

 public function viewphotoalbumsAction()
    {
        $identity = $this->identity();

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

        $data = array(
            'albums' => array_values($dirname),
            'files'  => $files,
        );

        return new ViewModel(array('album' => $data['albums'], 'files' => count($data['files'])));
    }

Answer:

In your public function de last dir will be the directory used in your second statement, which results in only the files counted in this folder.

change this:

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

into

foreach (glob(getcwd() . '/images/albums/*', GLOB_ONLYDIR) as $dir) 
{
     $dirname[] = basename($dir);

         foreach (glob($dir . '/*.{jpg,png,gif}', GLOB_BRACE) as $images) 
         {
          $files[] = $images;
         }
}