====== Шаг3. Добавление форм для создания и редактирования новостей. Удаление новостей ====== ===== Действие по добавлению новостей ===== ==== Шаблон news/create.html для добавления новостей ==== Добавим в папку template/news файл шаблона create.html следующего содержимого: Limb3 tutorial

Create news

:
:
:
:
По-сути это обычная hmtl-страница, однако есть кое-какие детали: * **
** тег имеет атрибут **runat='server'**, который говорит шаблонизатору, что это не просто тег, а компонент шаблона и что ему присуще какое-либо активное поведение (какое именно - будет сказано потом). Обычно любым активным компонентам шаблона даются свои идентификаторы, то есть указывается атрибут **id**. * Обратите внимание, что элементы формы имеют идентификаторы, совпадающие по названию с названиями полей таблицы news. ==== Изменения в контроллере NewsController ==== Теперь расширим наш контроллер NewsController чтобы он мог принимать данные с формы и добавлять новые записи в базу данных: request->hasPost()) return; $news = new News(); $news->import($this->request); $news->save(); $this->redirect(); } } Мы добавили метод doCreate, который будет вызываться при получении нашим приложением запросов вида /news/create. Шаблон будет выбираться аналогично, то есть template/news/create.html, как в случае и с действием по-умолчанию display. Разберем тело метода doCreate(). if(!$this->request->hasPost()) return; lmbController для удобства по-умолчанию содержит в себе объекты Запроса **request** и Ответа **response** в качестве своих атрибутов и сокращения записи. Здесь мы проверяем, был ли POST запрос с нашей формы. Если нет - тогда мы просто в первый раз зашли на данную страницу и нужно просто отобразить форму. $news = new News(); $news->import($this->request); Мы создали экземпляр класс News и поместили в него все данные из запроса. News автоматически выберет из запроса только те поля, которые есть в таблице news (немного упрощенное описание, но пока оно нас устраивает). Именно поэтому мы дали полям формы в шаблоне create.html имена, совпадающие с названиями полей таблицы news. $news->save(); Мы сохраняем новую записи в базу данных и ... $this->redirect(); перебрасываем пользователя на страницу действия по-умолчанию, то есть на /news Попробуем набрать в адресной строке /news/create. Должно получиться следующее: {{{:limb3:ru:tutorials:basic:simple_create.png|:limb3:ru:tutorials:basic:simple_create.png}}} ===== Добавление валидации данных ===== Нам хотелось бы, чтобы к полям новостей применялись следующие правила: * поля title, date и annotation были бы обязательными для заполнения, * title был меньше 75 символов, * content - заполнялся бы по желанию пользователя. Для этого нам необходимо будет внести некоторые изменения в классы News, NewsController и расширить шаблон create.html. ==== Изменения в классе News ==== Итак, теперь класс News будет выглядеть следующим образом: addRequiredRule('title'); $validator->addRequiredRule('annotation'); $validator->addRequiredRule('date'); lmb_require('limb/validation/src/rule/lmbSizeRangeRule.class.php'); $validator->addRule(new lmbSizeRangeRule('title', 75)); return $validator; } } ?> lmbActiveRecord при вызове метода save() может проверять данные, которые в нее добавили при помощи валидатора. Валидатор создается при помощи метода _createValidator(). По-умолчанию, lmbActiveRecord :: _createValidator() возвращает пустой валидатор. Наша задача - создать свой собственный. Валидатор - объект класса **lmbValidator**, который располагается в [[limb3:ru:packages:validation|пакете VALIDATION]]. Валидатор состоит из набора правил валидации, которые мы в него и добавляем в методе **_createValidator()**. Обратите внимание, что строку $validator->addRequiredRule('title'); можно переписать как lmb_require('limb/validation/src/rule/lmbRequiredRule.class.php'); $validator->addRule(new lmbRequiredRule('title')); по своей сути эквивалентны,а второй вариант приведен для ясности - в большинстве случаев используется именно сокращеннй первый вариант. Итого мы использовали 2 правила: * **lmbRequiredRule** - обязывает поле присутствовать в проверяемом объекте * **lmbSizeRangeRule** - обязывает поле содержать определенное количество символов. В нашем случае - не больше 75. ==== Изменения в классе NewsController ==== В действие doCreate() контроллера NewsController нам нужно будет внести некоторые изменения: request->hasPost()) return; $news = new News(); $news->import($this->request); $this->useForm('news_form'); $this->setFormDatasource($news); if($news->trySave($this->error_list)) $this->redirect(); } } ?> Обратите внимание на следующие строки: $this->useForm('news_form'); $this->setFormDatasource($news); if($news->trySave($this->error_list)) $this->redirect(); При помощи первых двух строк мы связываем активный компонент формы, находящийся в шаблоне с объектом новости. Это позволит нам не терять данные в полях формы, если часть данных была введена неверно. Метод lmbActiveRecord :: **trySave($error_list)** возвращает true, если все данные были введены верно и false, если существовали ошибки. trySave() является лишь "оберткой" для метода save(): метод save() при обнаружении ошибок валидации генерирует исключение класса lmbValidationException, которое ловится в методе trySave(). ==== Изменения в шаблоне news/create.html ==== Теперь добавим в шаблон template/news/create.html код для отображения ошибок валидации: [...]

Create news

  {$message}
:
[...]
Для вывода ошибок мы использовали тег ****, который передает список ошибок валидации из формы в компонент, указанный атрибутом **target**. Ошибки будут выводится при помощи тегов и работу которых уже была описана. Ошибки валидации будут попадать в шаблон автоматически, так как мы связали объект класса News с активной формой в методе doCreate() контроллера NewsController. Теперь попробуем ввести неверные данные и проверить систему валидации: {{{:limb3:ru:tutorials:basic:simple_create_errors.png|:limb3:ru:tutorials:basic:simple_create_errors.png}}} Если вы увидели нечто подобное, значит вы все делаете правильно. ===== Действие по редактированию новости ===== ==== Шаблон edit.html ==== Шаблон по редактированию новости template/news/edit.html выглядит почти точно также как и template/news/create.html: Limb3 tutorial

Edit news

  {$message}
:
:
:
:
Налицо большое дублирование, которое может быть легко устранено. Мы займемся оптимизацией шаблонов чуть позже. ==== Метод NewsController :: doEdit() ==== Теперь добавим метод doEdit в класс NewsController, чтобы наш контроллер мог правильно отрабатывать действие edit: request->get('id')); $this->useForm('news_form'); $this->setFormDatasource($news); if(!$this->request->hasPost()) return; $news->import($this->request); if($news->trySave($this->error_list)) $this->redirect(); } ?> Строкой $news = new News((int)$this->request->get('id')); мы загружаем объект новости с определенным идентификатором, который мы получаем из запроса. Обратите внимание, что мы связали форму в шаблоне с новостью до проверки $this->request->hasPost(), так как нам нужно передавать данные в шаблон в любом случае. При первоначальном отображении формы поля уже будут заполнены полями из загруженной новости. ==== Модификация шаблона template/news/display.html ==== Теперь изменим шаблон template/news/display.html чтобы вывести ссылку на страницу редактирования новостей. Добавим новую колонку для вывода доступных действий: Newsline

Newsline.

Create news

ID Date Title Actions
{$id} {$date} {$title} Edit   Delete
{$annotation}
Здесь мы использовали тег [[limb3:ru:packages:wact:tags:lmb_request_tags:lmb_route_url_tag|]], который является по сути аналогом тега , однако он умеет формировать атрибут href на основе параметров, которые ему указаны в атрибуте **params**. По сути route_url осуществляет процесс разбора строки запроса вида /news/create в обратном порядке. Все, что касается деталей разбора запроса выходит за рамки данного туториала, однако если вам интересны правила, на основе которых осуществляется определение текущего контроллера, посмотрите файл limb/web_app/settings/routes.conf.php. Поясним работу тега : Create news Этот код сформирует строку вида: Create news. news будет взят приложением автоматически, так как мы находимся на странице, за которую отвечает контроллер news. create будет взято из пары action:create, где action - это название параметра, а create - значение параметра. Точно также формируются ссылки на действия edit и delete. Параметры в атрибуте params тега разделяются через запятую. То есть тег вида Edit сформирует ссылку вида: Edit Если вы все сделали правильно, тогда вы должны иметь теперь возможность создавать и редактировать новости. ===== Удаление новостей ===== Для удаления объектов lmbActiveRecord используется метод destroy(). Добавим метод NewsController :: doDelete(): request->get('id')); $news->destroy(); $this->redirect(); } } ?> Пояснять код нет необходимости. ===== Что дальше? ===== Далее: [[step4|Шаг4. Оптимизация шаблонов. Добавление постраничного вывода.]]