Повторное использование форм в нескольких местах
В Nette у вас есть несколько вариантов повторного использования одной и той же формы в нескольких местах без дублирования кода. В этой статье мы рассмотрим различные решения, включая те, которых следует избегать.
Фабрика форм
Один из основных подходов к использованию одного и того же компонента в нескольких местах заключается в создании метода или класса, который генерирует компонент, а затем вызывает этот метод в разных местах приложения. Такой метод или класс называется фабрикой. Пожалуйста, не путайте с шаблоном проектирования фабричный метод, который описывает особый способ использования фабрик и не относится к данной теме.
В качестве примера давайте создадим фабрику, которая будет создавать форму редактирования:
Теперь вы можете использовать эту фабрику в различных местах вашего приложения, например, в презентаторах или компонентах. И мы сделаем это, запросив ее как зависимость. Итак, сначала мы запишем класс в конфигурационный файл:
А затем используем его в презентаторе:
Вы можете расширить фабрику форм дополнительными методами для создания других типов форм в соответствии с вашим приложением. И, конечно, вы можете добавить метод, создающий базовую форму без элементов, которую будут использовать другие методы:
Метод createForm()
пока не делает ничего полезного, но это быстро
изменится.
Зависимости фабрики
Со временем станет очевидно, что формы должны быть многоязычными. Это
означает, что нам необходимо установить переводчик для всех форм. Для этого
мы модифицируем класс FormFactory
, чтобы он принимал объект
Translator
в качестве зависимости в конструкторе и передавал
его форме:
Поскольку метод createForm()
вызывается и другими методами,
создающими конкретные формы, нам нужно установить транслятор только в
этом методе. И все готово. Нет необходимости изменять код презентатора
или компонента, что очень хорошо.
Другие фабричные классы
В качестве альтернативы вы можете создать несколько классов для
каждой формы, которую вы хотите использовать в своем приложении. Такой
подход может повысить читаемость кода и облегчить управление формами.
Оставьте исходный FormFactory
для создания только чистой формы с
базовой конфигурацией (например, с поддержкой перевода) и создайте
новую фабрику EditFormFactory
для формы редактирования.
Очень важно, что привязка между классами FormFactory
и
EditFormFactory
осуществляется путем композиции,
а не наследования
объектов:
Использование наследования в этом случае было бы совершенно
непродуктивным. Вы бы очень быстро столкнулись с проблемами. Например,
если бы вы захотели добавить параметры в метод create()
, PHP выдал бы
ошибку, что его сигнатура отличается от родительской. Или при передаче
зависимости классу EditFormFactory
через конструктор. Это привело бы к
тому, что мы называем " ад
конструктора".
В целом лучше отдать предпочтение композиции, а не наследованию.
Работа с формами
Обработчик формы, вызываемый после успешной отправки, также может
быть частью класса-фабрики. Он будет работать, передавая отправленные
данные в модель для обработки. Любые ошибки он будет передавать обратно в форму. Модель в
следующем примере представлена классом Facade
:
Пусть ведущий сам выполняет перенаправление. Он добавит еще один
обработчик к событию onSuccess
, который будет выполнять
перенаправление. Это позволит использовать форму в разных
презентаторах, и каждый из них может перенаправлять на разные места.
Это решение использует свойство форм: когда addError()
вызывается
на форме или ее элементе, следующий обработчик onSuccess
не
вызывается.
Наследование от класса формы
Построенная форма не должна быть дочерней по отношению к форме. Другими словами, не используйте это решение:
Вместо того чтобы создавать форму в конструкторе, используйте фабрику.
Важно понимать, что класс Form
– это прежде всего инструмент
для сборки формы, то есть конструктор форм. А собранную форму можно
считать его продуктом. Однако продукт не является частным случаем
конструктора; между ними нет отношения is a, которое лежит в основе
наследования.
Компонент формы
Совершенно другой подход – создать компонент, включающий форму. Это дает новые возможности, например, отображение формы определенным образом, поскольку компонент включает в себя шаблон. Или сигналы могут быть использованы для AJAX-коммуникации и загрузки информации в форму, например, для подсказок и т.д.
Давайте создадим фабрику, которая будет производить этот компонент. Достаточно написать ее интерфейс:
И добавить его в конфигурационный файл:
И теперь мы можем запросить фабрику и использовать ее в презентере: