Как заполнить элемент select в наборе полей из базы данных (mysql)

Я новичок в среде Zend и пытаюсь заполнить поле выбора в наборе полей в форме. Я перешел по разным ссылкам, но ни одна из них не увенчалась успехом.

У меня есть две таблицы Item & Category, идентификатор категории существует как внешний ключ в таблице элементов. Я пытаюсь загрузить доступные категории для выбора в режиме редактирования или добавления.

Я использовал их в качестве базы

Как запустить фабрику наборов полей в ZF3

ZF3 - Заполнить выбор из базы данных

Фабрика полевых наборов

class ItemFieldsetFactory implements FactoryInterface {
    public function __invoke(ContainerInterface $container, $requestedName, array $options = null) {
        $category = $container->get(CategoryRepository::class);
        $categories = $category->findAllCategoriesAsArray();

        $fieldset = $container->get('FormElementManager')->get(\Form\ItemFieldset::class);
        $fieldset->setCategories($categories);

        return $fieldset;
    }
}

Набор полей

namespace Item\Form;

use Zend\Form\Fieldset;
use Zend\Form\Element\Select;
use Item\Model\Item;
use Zend\Hydrator\ReflectionHydrator as ReflectionHydrator;

class ItemFieldset extends Fieldset
{
    private $categories = [];

    public function setCategories(array $categories) {
         $this->categories = $categories;
    }


    public function init()
    {
        $this->setHydrator(new ReflectionHydrator());
    $this->setObject(new Item('', '', '', ''));

        $this->add([
           'type' => 'hidden',
           'name' => 'itemid',
        ]);

        $this->add([
           'type' => Select::class,
           'name' => 'categoryid',
           'options' => [
                'label' => 'Category',
                'value_options' => $this->categories
           ]
        ]);

        $this->add([
            'type' => 'text',
            'name' => 'description',
            'options' => [
                'label' => 'Description',
            ],
        ]);

        $this->add([
            'type' => 'text',
            'name' => 'size',
            'options' => [
                'label' => 'Size',
            ],
        ]);

    }
}

Фабрика контроллеров

public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
    {
        $formManager = $container->get('FormElementManager');

        return new WriteController(
            $container->get(ItemCommandInterface::class),
            $formManager->get(ItemForm::class),
            $formManager->get(ItemFieldset::class),
            $container->get(ItemRepositoryInterface::class)
        );
    }
}

Контроллер

{
    private $command;
    private $form;
    private $fieldset;
    private $repository;

/**
 * @param ItemCommandInterface $command
 * @param ItemForm $form
 */
    public function __construct(
        ItemCommandInterface $command,
        ItemForm $form,
        ItemFieldset $fieldset,
        ItemRepositoryInterface $repository
    ) {
        $this->command = $command;
        $this->form = $form;
        $this->fieldset = $fieldset;
        $this->repository = $repository;
    }

    public function addAction()
{
    $req   = $this->getRequest();
    $viewModel = new ViewModel(['form' => $this->form]);

    if (! $req->isPost()) {
        return $viewModel;
    }

    $this->form->setData($req->getPost());

    if (! $this->form->isValid()) {
        return $viewModel;
    }

    $item = $this->form->getData();

    try {
        $item = $this->command->insertItem($item);
    } catch (\Exception $ex) {
        // An exception occurred; we may want to log this later and/or
        // report it to the user. For now, we'll just re-throw.
        throw $ex;
    }

    return $this->redirect()->toRoute(
        'item/detail',
        ['itemid' => $item->getItemId()]
    );
}

Конфигурация

namespace Item;

use Zend\Router\Http\Literal;
use Zend\Router\Http\Segment;
use Zend\Form;
use Zend\Fieldset;
use Zend\ServiceManager\Factory\InvokableFactory;

return [
    'service_manager' => [
..
    ],
    'controllers' => [
..
    ],
    'router' => [
..
    ],
    'form_elements' => [
        'factories' => [
            Form\ItemFieldset::class => Factory\ItemFieldsetFactory::class
        ]
    ],
    'view_manager' => [
        'template_path_stack' => [
            __DIR__ . '/../view',
        ],
    ],
];

Я надеялся, что поле выбора будет содержать все доступные категории (в режиме редактирования с выбранной текущей).

Все, что я получаю, это пустая коробка

Я думаю, что мой ItemFieldsetFactory не срабатывает, но не могу понять, почему. Моя причина этого в том, что я пытался остановиться на этом этапе, вызвав несуществующий метод, а также с помощью vardump & exit.

Любые советы / рекомендации с благодарностью.


person David334    schedule 18.07.2019    source источник
comment
also by vardump & exit ой. Если вы занимаетесь локальной разработкой, следуйте этому руководству от Jetbrains или это с Docker. - Использование xdebug сэкономит вам невероятное количество времени на размещение этих var_dump($var);exit; строк, обновление, проверку, редактирование и повторение, вместо этого предоставив вам возможность остановить выполнение, проверить во время выполнения и протестировать изменения во время выполнения.   -  person rkeet    schedule 19.07.2019
comment
Эти строки: $this->setHydrator(new ReflectionHydrator()); $this->setObject(new Item('', '', '', ''));, сделайте это на своей фабрике с помощью $fieldsetVar->setHydrator((new Hydrator())->setObject(new Category());. Если это не может измениться, вы могли бы также, поскольку это ничего не меняет для логики создания содержимого набора полей (что вы делаете в классе)   -  person rkeet    schedule 19.07.2019
comment
Кроме того, судя по именам функций, вы должны иметь возможность получать результаты (т. е. категории) в виде опций в наборе полей. То есть, если ваше свойство $categories представляет собой массив только значений, вы должны иметь значения в виде текстовых опций и числовые ключи в качестве опций значений в выводе HTML. Если вы определили пары ключ/значение, они должны присутствовать. Если findAllCategoriesAsArray возвращает массив объектов, вам необходимо преобразовать их, возможно, с помощью анонимной функции при настройке элемента Select. Вы можете подтвердить свою ситуацию по этому поводу?   -  person rkeet    schedule 19.07.2019
comment
Большое спасибо за все советы, которые я обязательно изучу в руководстве (я думал, что должен быть лучший способ добиться этого).   -  person David334    schedule 22.07.2019
comment
{ $sql = новый Sql($this-›db); $select = $sql-›select('categories'); $select-›заказ('описание'); $statement = $sql-›prepareStatementForSqlObject($select); $результат = $оператор->выполнить(); if (! $result instanceof ResultInterface || ! $result-›isQueryResult()) { return []; } $resultSet = new HydratingResultSet($this-›Hydrator, $this-›categoryPrototype); $resultSet-›инициализировать($результат); $arrayResults = $resultSet->toArray(); возврат ($массиврезультатов); }   -  person David334    schedule 22.07.2019
comment
Добавлен файл findAllCategoriesAsArray. Вы говорите, что мне нужно проанализировать результат, создав пары ключ/значение?   -  person David334    schedule 22.07.2019
comment
Да. (Кстати, разместить правку с дополнительной информацией в вопросе гораздо удобнее, чем в виде комментария). - Но да, конечный результат 'value_options' => $here, должен иметь массив ключ/значение вместо $here. Таким образом, ['foo' => 'bar', 'space' => 'astronaut''] дает 2 варианта (1 - значение «foo» с текстом «bar», 2 значение «пробел» с текстом «астронавт»).   -  person rkeet    schedule 22.07.2019
comment
Большое спасибо, понял, что как только нажал энтер. Каждый день школьный!   -  person David334    schedule 23.07.2019
comment
Все хорошо. Опубликуйте решение, когда оно у вас заработает ;-)   -  person rkeet    schedule 23.07.2019