user1130272
user1130272

Reputation:

PHP - foreach duplicates values through iterations

I am currently building a Laravel theme manager and im stuck a bit.

So i have a themes folder containing other folders for the actual theme files , these folders contain a template.phpas well, what contain basic data, name, title, description, version, and author

Made a function what checks for a match if the actual theme exsits in the database, if yes ignor reading the template.php, if not read the folder for that actual theme and store the file content in the database, after cliking install.

All works fine, if there is only one theme details stored in the database, if i install a second it turns back all themes located in the theme folder, checked and fround if there are more than data stored in the database, it duplicates the results.

Code

protected $theme_path = 'app/themes';

protected $manifest = 'template.php';

public function notInstalledThemes()
{
    $themes = $this->all();

    // get all directories form theme folder 
    $directories = File::directories($this->theme_path);

    // replace back slash to forward slash
    $directories = str_replace('\\', '/', $directories);

    foreach ($themes as $theme) 
    {
        
        foreach ($directories as $directory) 
        {
            // we dont need the admin
            // and ignor the themes already installed
            if ($directory != $this->theme_path.'/admin' && $directory != $this->theme_path.'/'.$theme->name)
            {
                $notINstalled = File::getRequire($directory.'/'.$this->manifest);

                $data[] = $notINstalled;
            } 
            
        }

    }

    if (!empty($data)) return $data;
}

So if i only have one theme stored in the database i and var_dump the results in my second foreach all fine

for one data

 foreach ($directories as $directory) 
    {
        var_dump($directory);
        // we dont need the admin
        // and ignor the themes already installed
        if ($directory != $this->theme_path.'/admin' && $directory != $this->theme_path.'/'.$theme->name)
        {
            $notINstalled = File::getRequire($directory.'/'.$this->manifest);
    
            $data[] = $notINstalled;
        } 
    
}

out puts

string(16) "app/themes/admin"
string(17) "app/themes/cosmos"
string(18) "app/themes/default"

i get back the directories fine,

But if another theme data is stored in the database the iteration duplicates the results

second out puts

string(16) "app/themes/admin"
string(17) "app/themes/cosmos"
string(18) "app/themes/default"
string(16) "app/themes/admin"
string(17) "app/themes/cosmos"
string(18) "app/themes/default"

Searched the net, found array_unique

but did not really work, could anybody please give me a hint on how to avoid this?

Upvotes: 0

Views: 739

Answers (1)

mpj
mpj

Reputation: 5367

When you have two themes in your database, your code is doing the following:

$themes = $this->all();
// Assuming you have admin and cosmos in your db:
// $themes = ['admin', 'cosmos']

$directories = File::directories($this->theme_path);
// $directories = ['admin', 'cosmos', 'default']

So, the loops are running like this:

foreach ($themes as $theme) 
{
    // 2 iterations: 'admin' and 'cosmos'
    foreach ($directories as $directory) 
    {
        // 3 iterations: 'admin', 'cosmos', and 'default'

Which is why you are having the output that you described (2x3 iterations).

The piece remaining, in order to have unique entries in your $data array, is something like the following, which uses PHP in_array function.

if ($directory != $this->theme_path.'/admin' && $directory != $this->theme_path.'/'.$theme->name)
{
    $notINstalled = File::getRequire($directory.'/'.$this->manifest);
        
    if ( ! in_array($notInstalled, $data))
    {
        $data[] = $notINstalled;
    }
} 

Upvotes: 1

Related Questions