user2101411
user2101411

Reputation: 1202

Adding Value Options to Select Element

I'm trying to set multiple values for a select object with Zend Framework 2's form class but it's only passing one value. Here is my code:

public function addphotosAction()
{
    $identity = $this->identity();
    $files = array();
    $album_name = array();

    foreach (glob(getcwd() . '/public/images/profile/' . $identity . '/albums/*', GLOB_ONLYDIR) as $dir) {
        $album_name = basename($dir);

        $files[$album_name] = glob($dir . '/*.{jpg,png,gif,JPG,PNG,GIF}', GLOB_BRACE);
    }

    $form = new AddPhotosForm();

    $form->get('copy-from-album')->setValueOptions(array($album_name));

    return new ViewModel(array('form' => $form, 'files' => $files));
}

I know it has to do with $album_name but am at a loss about how to use it to grab all the directories (if I try to write to $album_name via []), I get an warning of

`Warning: Illegal offset type in C:\xampp\htdocs\module\Members\src\Members\Controller\ProfileController.php on line 197`

which is the $files[$album_name] = glob($dir . '/*.{jpg,png,gif,JPG,PNG,GIF}', GLOB_BRACE); line.

As I said, I am at a loss about how to edit this to grab all the directories.

Any help would be appreciated.

Thanks!

here is a screenshot of what I am trying to describe: https://i.sstatic.net/37891.jpg (there is more than one directory that exists but only one is being listed in the select menu).

Upvotes: 0

Views: 236

Answers (1)

Marcel
Marcel

Reputation: 5119

I really recommend to do it with a factory. With a factory you 'll write this code once and can use it everywhere else in your code. For object orientated reasons, in which everything should be an object, I recommend using PHP 's own DirectoryIterator class instead of glob. The code in the controller should be kept as small as possible. Please have a look at the following example code.

The Form Factory with the Directory Iterator

The form factory intializes the form class with everything you need for the form instance for you, so this code won 't show up in the controller. You can re-use it for an inherited edit form for example.

<?php
namespace Application\Form\Factory;

use Zend\ServiceManager\FactoryInterface;
use Zend\ServiceManager\ServiceLocatorInterface;
use Application\Form\AddPhotosForm;

class AddPhotosFormFactory implements FactoryInterface
{
    public function createService(ServiceLocatorInterface $oServiceLocator)
    {
        $oParentLocator = $oServiceLocator->getServiceLocator();

        // please adjust the dir path - this is only an example
        $aDirectories = [];
        $oIterator = new \DirectoryIterator(__DIR__);
        
        // iterate and get all dirs existing in the path
        foreach ($oIterator as $oFileinfo) {
            if ($oFileinfo->isDir() && !$oFileinfo->isDot()) {
                $aDirectories[$oFileinfo->key()] = $oFileinfo->getFilename();
            }
        }

        // set option attribute for select element with key => value array of found dirs
        $oForm = new AddPhotosForm();
        $oForm->get('mySelectElement')
            ->setAttributes('options', $aDirectories);

        return $oForm;
    }
}

That 's all for the factory itself. The only thing you have to do is writing it down in your module.config.php file.

...
'form_elements' => [
    'factories' => [
        AddPhotosForm::class => AddPhotosFormFactory::class,
    ],
],
...

Using ::class not just cleans things up, it will lead to using fewer strings and this makes things easy to remember in an IDE with autocompletion for class names.

The Controller

With the factory we cleaned up the controller. In a controller code should be as small as possible. Using factories is the solution for many problems, which may happen in a later process of coding. So keep it always clean and simple.

...
public function indexAction()
{
    $oForm = $this->getServiceManager()
        ->get('FormElementManager')
        ->get(AddPhotosForm::class);

    return [
        'form' => $oForm,
    }
}

That 's all for the controller so far. Your select element was populated in the factory and your controller is easy to understand and as small as it should be.

Upvotes: 1

Related Questions