Как исправить "Вход не был найден в стоге сена" в ZF2?

В моем коде есть проблема, которую я не могу решить. Я использую Zend framework 2.4, и я написал форму, но как только я ее проверил, я получил сообщение об ошибке . Входные данные не были найдены в стоге сена. Это 3 входа, где я получил ошибку:

 $this->add(array(
        'name' => 'ACTIVITE1',
        'type' => 'Zend\Form\Element\Select',
        'required' => 'required',
        'options' => array(
            'value_options' => array(
                'Choisir l\'activité'
            ),
            'disable_inarray_validator' => false,
        ),
        'attributes' => array(
            'class' => 'form-control',
            'id' => 'select-session1'
        )
    ));

    $this->add(array(
        'name' => 'ACTIVITE2',
        'type' => 'Zend\Form\Element\Select',
        'required' => 'required',
        'options' => array(
            'value_options' => array(
                'Choisir l\'activité'
            )
        ),
        'disable_inarray_validator' => false,
        'attributes' => array(
            'class' => 'form-control',
            'id' => 'select-session2'
        )
    ));

    $this->add(array(
        'name' => 'ACTIVITE3',
        'type' => 'Zend\Form\Element\Select',
        'required' => 'required',
        'options' => array(
            'value_options' => array(
                'Choisir l\'activité'
            )
        ),
        'disable_inarray_validator' => false,
        'attributes' => array(
            'class' => 'form-control',
            'id' => 'select-session3'
        )
    ));

Я видел в другой форме, что я должен поставить 'disable_inarray_validator' => false но это тоже не работает.

2 ответа

Решение

Конечно не работает.

Это сообщение исходит от \Zend\Validator\InArrayи, по сути, это означает: "ваш пользователь делает что-то взломанное с вашим выбором, обратите внимание".

Примером может служить Select Preferred fruitс двумя вариантами, такими как "Банан" и "Ананас", но пользователь "взламывает" выбор и отправляет на сервер значение "Audi". ВInArray валидатор действительно важен, и его не следует отключать (ну, только за некоторыми исключениями...).

Итак, почему вы получаете эту ошибку? Ответ... Вы не сказали, какие есть варианты выбора. Вы создали Select, но не указали его параметры. Вы помещаете метку / заполнитель вместо вариантов. Правильный выбор будет:

$this->add(array(
    'name' => 'ACTIVITE1',
    'type' => 'Zend\Form\Element\Select',
    'required' => 'required',
    'options' => array(
        'value_options' => array(
            1 => 'Fitness',
            2 => 'Parcour',
            3 => 'Velo',
            4 => 'Tapis roulant',
            // ... and so on
        )
    ),
    'attributes' => array(
        'class' => 'form-control',
        'id' => 'select-session1',
        'placeholder' => "Choisir l'activité"
    )
));

Что "странно", так это то, что вы заполняете что-то в пустом выделении, и тогда мой вопрос: почему?

Выборки (обычно) есть для предопределенного списка значений. Если вы хотите разрешить своим пользователям заполнять собственный текст, вам следует подумать о созданииText поле с опцией автозаполнения.

Изменить: выбрать со значениями из БД

Если вы хотите создать выбор со списком опций, поступающих из базы данных, маршрут будет немного сложнее, но как только вы научитесь это делать, он станет намного проще.

ОБРАТИТЕ ВНИМАНИЕ: это не будет "решение для копирования и вставки". Поскольку у меня нет доступа к вашему коду, я придумываю имена (классы, пространства имен, методы, переменные) просто для создания полного примера:)

Прежде всего, вы должны создать собственный элемент. В этом случае это будет пользовательский выбор:

namespace Yournamespace;

use Zend\Form\Element\Select;
use Yournamespace\ActivityMapper;

class ActivitySelect extends Select {

    protected $activityMapper;

    public function __construct(ActivityMapper $activityMapper, $name = null, $options = []) {
        parent::__construct($name, $options);
        $this->activityMapper = $activityMapper;
    }

    public function init() {
        $valueOptions = [];
        foreach ($this->activityMapper->fetchAll() as $activity) {
            $valueOptions[$activity->getActivityId()] = $activity->getActivityName();
        }
        $this->setValueOptions($valueOptions);
    }

}

Что действительно важно, так это то, что вы должны создать экземпляр своего элемента (параметры, классы и т. Д.) Внутриinit метод.

Поскольку этот элемент имеет зависимость (ActivityMapper) вам нужно будет создать фабрику для этого элемента:

namespace Yournamespace;

use Zend\ServiceManager\Factory\FactoryInterface;
use \Interop\Container\ContainerInterface;

class ActivitySelectFactory implements FactoryInterface {

    public function __invoke(ContainerInterface $container, $requestedName, array $options = null): object {
        $activityMapper = $container->get(\Yournamespace\ActivityMapper::class);
        return \Yournamespace\ActivitySelect($activityMapper);
    }

}

Эту фабрику надо добавить в конфигурацию, точнее внутри module.config.php:

return [
    // ...
    'form_elements' => [
        'factories' => [
            \Yournamespace\ActivitySelect::class => \Yournamespace\ActivitySelectFactory::class,
        ]
    ]
    // ...
];

Теперь вы также должны изменить свою форму. Все элементы должны быть добавлены в форму внутриinit метод, а не внутри конструктора:

namespace Yournamespace;

use Zend\Form\Form;
use Zend\InputFilter\InputFilterProviderInterface;

class ActivityForm extends Form implements InputFilterProviderInterface {

    public function init() {
        parent::init();

        // ...
        $this->add([
            'name' => 'ACTIVITE1',
            'type' => \Yournamespace\ActivitySelect::class,
            'attributes' => [
                'class' => 'form-control',
                'id' => 'select-session1',
                'required' => true, // This will work only clientside, don't forget the inputfilter!
                'placeholder' => 'Choisir l\'activité',
            ],
            'options' => [
                'label' => 'Choisir l\'activité',
            ]
        ]);
        // ...

    }

    public function getInputFilterSpecification() {
        // ...
        $inputFilter[] = [
            'name' => 'ACTIVITE1',
            'required' => true
        ];
        // ...
        return $inputFilter;
    }

}

Наконец, вам также придется изменить свой контроллер, потому что вам нужно получить форму из FormElementManager:

namespace Yournamespace;

use Zend\Form\FormElementManager;

class YourController extends AbstractActionController {
    private $formManager;

    public function __construct(FormElementManager $formManager) {
        $this->formManager = $formManager;
    }

    public function choisirActiviteAction(){
        // ...
        $form = $this->formManager->get(\Yournamespace\ActivityForm::class);
        // ...
    }
}

Следующим хорошим шагом было бы создание плагина контроллера для $formManager, вместо того, чтобы делать это зависимостью каждого контроллера, но это другая проблема..

Спасибо за Ваш ответ! Я понимаю, что вы имеете в виду, но я сделал это, потому что я не хочу контролировать выбор, потому что я не могу контролировать все возможные варианты.

Поскольку параметры взяты из базы данных, я получаю от них запрос AJAX и добавляю все параметры к выбору в представлении. Таким образом, варианты могут быть разными и не фиксированы.

Вот мой запрос AJAX:

$("#input-dtNaissance").change(function() {
        $.when($(".activites-options").remove()).then(function() {
            if ($("#input-dtNaissance").val() != " ") {
                //on supprime les anciennes activités proposées au cas où il y en ai
                var year = $("#input-dtNaissance").val().substring(0,4);
                if (year == "") {
                    year = 1;
                }
                // si date supprimée/réinitialisée 
                if (year == 1) {
                    // on supprime les activités proposées du select
                    $(".activites-options").remove();
                } else {
                    $.getJSON("http://localhost/ecoleMunicipalSport/app/public/activite/listActivitySession1/" + year, function(data) {
                        data.forEach(element => {
                            var option = "<option value='" + element.ID_ACTIVITES + "' class='activites-options'>" + element.activite[0] + element.activite.substring(1).toLowerCase() + " avec " + element.INTERVENANT + " - " + element.HORAIREDEB + "/" + element.HORAIREFIN + " (" + element.site[0] + element.site.substring(1).toLowerCase() + ")" + "</option>";
                            $("#select-session1").append(option);
                        });
                    });
                    $.getJSON("http://localhost/ecoleMunicipalSport/app/public/activite/listActivitySession2/" + year, function(data) {
                        data.forEach(element => {
                            var option = "<option value='" + element.ID_ACTIVITES + "'class='activites-options'>" + element.activite[0] + element.activite.substring(1).toLowerCase() + " avec " + element.INTERVENANT + " - " + element.HORAIREDEB + "/" + element.HORAIREFIN + " (" + element.site[0] + element.site.substring(1).toLowerCase() + ")" + "</option>";
                            $("#select-session2").append(option);
                        });
                    });
                    $.getJSON("http://localhost/ecoleMunicipalSport/app/public/activite/listActivitySession3/" + year, function(data) {
                        data.forEach(element => {
                            var option = "<option value='" + element.ID_ACTIVITES + "' class='activites-options'>" + element.activite[0] + element.activite.substring(1).toLowerCase() + " avec " + element.INTERVENANT + " - " + element.HORAIREDEB + "/" + element.HORAIREFIN + " (" + element.site[0] + element.site.substring(1).toLowerCase() + ")" + "</option>";
                            $("#select-session3").append(option);
                        });
                    });
                }
            }
        });
    })

Я знаю, что это не очень безопасно, и если у вас есть лучшее решение с большей безопасностью, я открыт для предложений.

Добрый вечер.

PS: Извините, мой ужасный английский:)

Другие вопросы по тегам