MVC with one to many relationship

Don’t do that, just ask here.

Yes, I have exactly this when the form is rendered in browser.
A select with no options.

However, I have this code in AlbumForm.php:

      $this->add([
           'name' => 'genre_id',
           'type' => GenreSelectElement::class,
      ]);

And the customized control itself must be populated in it’s init() method:
.

<?php

namespace Album\Form;
use Laminas\Db\Adapter\AdapterAwareTrait;
use Laminas\Db\Adapter\AdapterAwareInterface; 
use Laminas\Form\Element;

class GenreSelectElement extends Element\Select implements AdapterAwareInterface
{
    use AdapterAwareTrait;

    public function init(): void
    {
        if (! $this->adapter) {
            return;
        }

        /** @var Laminas\Db\Adapter\Driver\StatementInterface $statement */
        $statement = $this->adapter->query('SELECT `id`, `genre_name` FROM `genre`');
        $result    = $statement->execute();

        $options = [];
        /** @var array{id: int, name: string} $row */
        foreach ($result as $row) {
            $options[$row['id']] = $row['genre_name'];
        }

        $this->setValueOptions($options);
    }
}

Unfortunately, I am unable to debug the code step by step, in order to see if the Select Control is populated from the database.

I have checked this again, the adapter can be set and I can debug it with Xdebug.

Add a simple var_dump() to check if the adapter is set in your custom element:

public function init(): void
{
    var_dump($this->adapter);

    if (! $this->adapter) {
        return;
    }
}

If the adapter is not set, the element will not be created correctly via the form element manager. Which means the chain is broken somewhere.

Thank you,
The following line, put in the code above, for my GenreSelectElement

var_dump($this->adapter);

Returns NULL.

It means that the adapter is not set.

From the examples I saw in the documentation, when we init the adapter, we provide the db driver and the db path to it.
As here it is not done, I assume that this directive: use AdapterAwareTrait;
does it automatically?

This means the chain is broken somewhere:

  • the element is not fetched from the form element manager
  • the form is not fetched from the form element manager
  • the form element manager is not fetched from the application service container
  • the delegator is not set for the element
  • the interface Laminas\Db\Adapter\AdapterAwareInterface is not set for the element with the trait

You have already configured the database adapter in the tutorial. See in your global configuration, in the file config/autoload/global.php. laminas-db is registered as module in your application and uses this configuration to create the database adapter when it is requested from application service container.

The extra delegator which is set for your custom element will fetch this adapter and set it via the setAdapter method of the related trait.

You have a problem again with classnames and the namespace:

namespace Album;

use Laminas\Router\Http\Segment;
use Laminas\ServiceManager\Factory\InvokableFactory;

return [
    'form_elements' => [
        'delegators' => [
            Album\Form\GenreSelectElement::class => [
                Laminas\Db\Adapter\AdapterServiceDelegator::class
            ],
        ],
    ],
    'controllers' => [
        'factories' => [
            Album\Controller\AlbumController::class =>
            Laminas\ServiceManager\AbstractFactory\ReflectionBasedAbstractFactory::class,
        ],
    ],
];

Your current configuration file produces wrong classnames which not exists:

  • Album\Album\Form\GenreSelectElement
  • Album\Laminas\Db\Adapter\AdapterServiceDelegator
  • Album\Album\Controller\AlbumController
  • Album\Laminas\ServiceManager\AbstractFactory\ReflectionBasedAbstractFactory

I think the best option for you is to import everything:

namespace Album;

use Album\Controller\AlbumController;
use Album\Form\GenreSelectElement;
use Laminas\Db\Adapter\AdapterServiceDelegator;
use Laminas\Router\Http\Segment;
use Laminas\ServiceManager\AbstractFactory\ReflectionBasedAbstractFactory;
use Laminas\ServiceManager\Factory\InvokableFactory;

return [
    // …
    'form_elements' => [
        'delegators' => [
            GenreSelectElement::class => [
                AdapterServiceDelegator::class,
            ],
        ],
    ],
    'controllers'   => [
        'factories' => [
            AlbumController::class => ReflectionBasedAbstractFactory::class,
        ],
    ],
];

And because of the wrong class names, the delegator does not work, so the adapter for the element is not set.

In the documentation of PHP you will find a page that describes the rules for name resolution:

https://www.php.net/manual/en/language.namespaces.rules.php


So, please recheck the classnames in your configuration file of your Album module.