Попробуйте добавить ещё один отзыв в нашу гостевую книгу.
Теперь стоит «подшлифуем» предыдущую функцию. Сделаем проверку вводимых
данных, семантическую обработку текста отзыва и добавим смайлики. Для проверки правильности вводимых пользователем
данных мы будем использовать класс валидации (информация по нему:
http://code-igniter.ru/user_guide/libraries/validation.html). Для проверки мы будем использовать следующий правила. Для поля «author» - проверку на пустоту и максимальное ограничение в 50 символов. Для поля «email» - проверку на пустоту, ограничение в 50 символов и проверку на правильность введённого адреса. Текст отзыва проверим только на пустоту. Также в правилах для каждого поля укажем обработку их «trim»-функцией. Задаются правила следующим образом. Создаётся массив полей. В каждой ячейке этого массива указываются правила для конкретного поля. Если правил несколько то они перечисляются через знак «|». Вот как это будет выглядеть у нас:
PHP |
$rules = Array(); $rules['author'] = 'trim|required|max_length[50]'; $rules['email'] = 'trim|required|max_length[50]|valid_email'; $rules['text'] = 'trim|required'; |
Здесь
trim — указывает что нужно обработать содержимое поля этой функцией (так же можно использовать такие функции как md5, htmlspecialchars, strtolower и т.д.)
required — полу обязательно должно быть заполнено.
max_length[50] — максимальная длинна строки в этом поле — 50 символов.
valid_email — данные должны представлять из себя правильный e-mail адрес.
Полный список правил и функций-обработчиков Вы можете найти в документации к классу «Validation». Вы наверное заметили что мы не проверяем имя автора на наличие только алфавитных или алфавитно-цифровых символов. Сделано это потому что CI не может работать с русскоязычными символами — он их воспринимает как неалфавитные. Установка правил производится методом «set_rules», ему нужно передать массив наших правил в качестве одиночного. Запуск проверки производится вызовом метода «run». Если этот метод вернёт «true», то все данные совпадают с установленными нами правилами. От этого и будем отталкиваться. Мы проведём валидацию данных и по её результатам будем выполнять добавление запроса. Код метода «make_answer» в итоге должен стать таким:
PHP |
// Загружаем библиотеку валидации $this->load->library('validation');
// Создаём массив правил $rules = Array(); $rules['author'] = 'trim|required|max_length[50]'; $rules['email'] = 'trim|required|max_length[50]|valid_email'; $rules['text'] = 'trim|required';
// Устанавливаем правила $this->validation->set_rules($rules);
// Только если все указанные правила соблюдены добавляем запись if($this->validation->run()) { $author = $this->input->post('author',true); $email = $this->input->post('email',true); $text = $this->input->post('text',true);
$this->Querys->addAnswer($author,$email,$text); }
// Выводим все отзывы self::index(); |
Обратите внимание вот ещё на что: если вдруг данные не проходят проверку, то метод «run» не только возвращает «false», но и помещает сообщения с указанием ошибок в свойство «error_string», поэтому для того, чтобы пользователь мог увидеть сообщения о допущенных им ошибках, в начало шаблона «answer_form» добавим следующие строки:
Код |
<center> <?if(isset($this->validation->error_string)):?> <?=$this->validation->error_string?> <?endif;?> </center> |
Здесь мы специально проверяем заполненность свойства функцией «isset», потому что при его отсутствии PHP будет выводить ошибку типа «notice». Конечно же, вывод ошибок можно просто отключить (так стоит делать только в полностью рабочих приложениях), но так как у нас тренировочное приложение, то сообщения об ошибках, даже самых незначительных, должны выводиться. Проверим теперь работу наших правил. Отправьте скрипту пустую форму. Если Вы всё сделали правильно, то должны увидеть сообщения «The author field is required.», «The email field is required.» и «The text field is required.» Другие сообщения будут выводиться на иные ошибки. Например если Вы не правильно укажете e-mail, то сообщение будет таким: «The email field must contain a valid email address.».
Воспользуемся ещё одной возможностью библиотеки «validation». Если информация из полей не прошла проверку, то при новом отображении формы имеется возможность ввести в её поля то, что вводил до этого пользователь. То есть, если в форме 7 полей, а ошибка лишь в одном, то пользователю не нужно будет заново всё заполнять, а лишь изменить то поле, в котором он допустил ошибку. Это встречается сейчас почти на каждом сайте. В классе валидации для этого используется метод «set_fileds», которому необходимо передать набор полей в виде массива.
PHP |
// Создаём массив полей $fields = Array(); $fields['author'] = 'author'; $fields['email'] = 'email'; $fields['text'] = 'text';
// Устанавливаем эти поля $this->validation->set_fields($fields); |
Вставим этот код до запуска проверки методом «run». После проверки данные из этих полей занесутся в свойства класса «validation», откуда могут быть считаны. Теперь нам нужно подредактировать шаблон формы таким образом, чтобы в наших полях отображались введённые данные, если конечно они есть. Для этого замените код поля «author» c
Код |
<input type='text' name='author' value=''/> |
на
Код |
<?if(isset($this->validation->author)):?> <input type='text' name='author' value='<?=$this->validation->author?>'/> <?else:?> <input type='text' name='author' value=''/> <?endif;?> |
код
Код |
<input type='text' name='email' value=''/> |
на
Код |
<?if(isset($this->validation->email)):?> <input type='text' name='email' value='<?=$this->validation->email?>'/> <?else:?> <input type='text' name='email' value=''/> <?endif;?> |
и
Код |
<textarea name='text' cols='20' rows='5'></textarea> |
на
Код |
<?if(isset($this->validation->text)):?> <textarea name='text' cols='20' rows='5'><?=$this->validation->text?></textarea> <?else:?> <textarea name='text' cols='20' rows='5'></textarea> <?endif;?> |
Здесь мы просто за место кода полей ввели выражение типа «если было значение в полях то выводить его». Можно обойтись и полностью без конструкции if, вводя например такой код
Код |
<input type='text' name='email' value='<?=$this->validation->email?>'/> |
Но опять же, при обычном обращении к главной странице будет выскакивать notice-ошибка PHP о том, что свойство «$this->validation->email» не установлено. В целях проверки того, что мы сейчас проделали введите любые данные в поля формы и специально допустите какую-нибудь ошибку (например не заполните поле имени). После отправки формы Вы должны увидеть сообщения об ошибке, и поля формы автоматически заполнятся тем, что Вы ввели ранее.
Теперь займёмся семантической обработкой поступившего от пользователя текста. Под семантической обработкой подразумевается замена специальных символов (или их комбинаций) на их html-эквиваленты. Например перенос строки «\r\n» заменяется на «<br />», двойной перенос на «<p></p>» и так далее. Для подобных задач в CI имеется хэлпер «Typography» (информация по нему:
http://code-igniter.ru/user_guide/helpers/...hy_helper.html). Его
функция «auto_typography» форматирует передаваемый ей текст для привидения его к семантически правильному виду. Добавим вызов этого хэлпера перед получением значений введённых полей, а сразу после определения переменной «text» вызовем нужную нам функцию:
PHP |
$text = auto_typography($text); |
На очереди смайлики. В CI есть очень удобный и полезный хелпер «Smiley» (http://code-igniter.ru/user_guide/helpers/smiley_helper.html). Он отвечает за преобразование текстовых смайликов в картинки. С ним придётся немного повозиться. Скачайте по этой ссылке архив со смайликами:
http://codeigniter.com/download_files/smileys.zip и поместите изображения из него в папку «images/smileys». В код конструктора нашего контроллера добавьте загрузку этого хелпера. Мы помещаем его именно в конструктор потому что в методе добавления записи нам нужно будет им воспользоваться чтобы об
работать полученный текст, и в методе показа списка ответов — чтобы сделать отображение списка смайлов около формы. Обработка текста производится функцией «parse_smileys». Ей нужно передать 2 параметра — текст, который надо об
работать и путь к папке со смайликами. Добавим её вызов в метод «answer_add», после обработки текста функцией «auto_typography».
PHP |
$text = parse_smileys($text,config_item('base_url').'images/smileys/'); |
Для получения адреса хоста мы используем функцию «config_item», которая является общей функцией (http://code-igniter.ru/user_guide/general/common_functions.html). Можно было бы использовать для этого специальный класс «Config», но тогда бы строка кода получилась больше:
PHP |
$text = parse_smileys($text,$this->config->item('base_url').'images/smileys/'); |
Хотя существенной разницы нет. Вы можете использовать какой угодно вариант, разницы в результате работы от этого не появится.
Наконец подключим список смайлов к форме ввода комментария для того чтобы пользователь смог кликом мышки добавить нужный ему смайл. Здесь всё проходит в 2 этапа. На первом эапе в заголовок страницы нужно добавить вызов функции «js_insert_smiley». Ей нужно передать 2 параметра — имя формы (у нас это «answer_form») и имя поля (у нас - «text») куда смайлики будут вставляться. Вызовем её в шаблоне «header» прямо перед закрывающим тегом «head»:
Код |
<?=js_insert_smiley('answer_form', 'text');?> |
Эта функция генерирует простой JS-код который отвечает за добавление смайлов в текстовое поле:
Код |
<script type="text/javascript"> function insert_smiley(smiley) { document.answer_form.text.value += " " + smiley; } </script> |
Теперь займёмся отображением смайликов около нашей формы. В этом нам поможет функция «get_clicable_ssmileys» которой нужно передать всего один параметр — путь к папке с картинками смайликов.
PHP |
$image_array = get_clickable_smileys(config_item('base_url').'images/smileys/'); |
Эта функция возвращает массив соответствий смайликов и кликабельных ссылок на них. После получения этого массива нам нужно как-то обработать его чтобы на выходе получить код таблицы со смайлами. Мы сделаем так чтобы смайлы выстраивались в 2 ряда. Здесь есть 2 варианта — вставить цикл обработки этого массива в шаблон или же воспользоваться библиотекой «HTML Table» (http://code-igniter.ru/user_guide/libraries/table.html) генерирующей HTML-таблицы. Второй вариант намного лучше потому что он проще в реализации. В первом случае нам пришлось бы описывать цикл в шаблоне, добавлять туда код который бы определил когда начать новую строку и т.д. А с вышеупомянутым классом всё намного проще, в чём Вы сами сейчас убедитесь. Впишите его подключение прямо в начале метода «index»:
PHP |
$this->load->library('table'); |
Для генерации нашей таблицы требуется вызвать всего 2 метода. Первый из требуемых методов - «make_columns». Он сгенерирует нужные колонки. Нужно передать ему 2 параметра — массив смайлов и число обозначающее их количество на строку. В нашем случае это число 20 потому что смайлов всего 40, а нам нужно чтобы они выстроились в 2 строки. И второй метод - «generate», ему нужно лишь передать результат действия прошлого метода.
PHP |
// Генерируем код колонок таблицы смайлов $col_array = $this->table->make_columns($image_array, 20); |
Код получившейся таблицы возвращается методом «generate»
PHP |
// Генерируем код таблицы смайлов и добавляем его в передающиеся шаблону данные $data['smiley_table'] = $this->table->generate($col_array); |
Из шаблонов сейчас стала доступна переменная «smiley_table» которая содержит код нужной нам таблицы. Вставим показ этой переменной между полями формы и кнопкой оправки отзыва новой строкой в таблице:
Код |
<tr> <td width="81" valign="top"><img src="/images/rc.gif" width=55 height=24 alt=""></td> <td colspan='2'><?=$smiley_table?></td> </tr>
|
В итоге прямо под формой у Вас в 2 ряда должны отображаться смайлы.
При клике на них в текстовое поле сообщения должны добавляться их текстовые эквиваленты. Попробуйте оставить отзыв со смайликом.
Теперь приступим к разбиению отзывов на страницы, а именно — по десять штук на страницу. Для того, чтобы наше разбиение можно было увидеть, оставьте на сайте 11 или более сообщений. Для решения этой задачи воспользуемся библиотекой «Pagination» (информация по ней:
http://code-igniter.ru/user_guide/libraries/pagination.html). Итак, чтобы сделать то, что нам нужно, требуется загрузить эту библиотеку, определить минимум три параметра — базовый URI, количество объектов на странице, общее количество объектов в базе, ну и под конец вызвать метод «initialize», которому следует все эти данные передать. После этого код страниц будет возвращаться методом «create_links». Его мы передадим вместе с массивом отзывов шаблону «answers_list» и запишем туда код отображения списка страниц (к слову о 11 отзывах - если страниц будет меньше чем 2, то метод «create_links» не вернёт ничего).
Обратите внимание на то, что нам нужно будет передать общее количество
данных в базе. Для этого мы сейчас добавим соответствующий метод в нашу модель. Он будет просто возвращать количество записей в таблице.
PHP |
function getAnswersCount() { $sql = "SELECT COUNT(id) as count FROM guestbook"; $query = $this->db->query($sql); $row = $query->result_array();
return $row[0]['count']; } |
Теперь займёмся кодом контроллера. Сначала создадим массив данных необходимых для работы библиотеки «Pagination»:
PHP |
$pagination_config = Array(); $pagination_config['base_url'] = config_item('base_url').'/guestbook/index/'; // Обозначаем общее количество отзывов $pagination_config['total_rows'] = $this->Querys->getAnswersCount(); // Число отзывов на страницу $pagination_config['per_page'] = 10; |
Обратите внимание на то что мы подставляем в основной URI строку «guestbook/index/». Мы это делаем, потому что в конец этой ссылки будут подставляться данные о странице. Если же мы будем использовать просто обращение к корню сайта (что с точки зрения запросов одинаково), то данные о странице будут восприниматься как имя контроллера, и сервер всегда будет возвращать ответ 404.
Теперь нам нужно инициализировать страницы:
PHP |
$this->pagination->initialize($pagination_config); |
Ну и под конец добавим код страниц в массив «data», хранящий данные для шаблона:
PHP |
$data['pages_code'] = $this->pagination->create_links(); |
В итоге в методе «index» у нас должен получиться следующий код:
PHP |
// Загружаем библиотеку "Pagination" и библиотеку «HTML Table» $this->load->library(Array('pagination','table')); // Загружаем хелпер "Date" $this->load->helper('date');
// Формируем массив параметров для генерации страниц $pagination_config = Array(); $pagination_config['base_url'] = config_item('base_url').'/guestbook/index/'; // Обозначаем общее количество отзывов $pagination_config['total_rows'] = $this->Querys->getAnswersCount(); // Число отзывов на страницу $pagination_config['per_page'] = 10; // Инициализируем страницы $this->pagination->initialize($pagination_config);
// Получаем массив отзывов $answers = $this->Querys->getLastAnswers();
$image_array = get_clickable_smileys(config_item('base_url').'images/smileys/');
// Генерируем код колонок таблицы смайлов $col_array = $this->table->make_columns($image_array, 20); // Создаём массив данных для передачи в шаблон $data = Array(); $data['answers'] = $answers; // Генерируем код таблицы смайлов и добавляем его в передающиеся шаблону данные $data['smiley_table'] = $this->table->generate($col_array); // Добавляем в данные для шаблона код страниц $data['pages_code'] = $this->pagination->create_links();
// Обрабатываем шаблоны $this->load->view('header'); // Передаём в шаблон данные $this->load->view('answers_list',$data); $this->load->view('answer_form'); $this->load->view('footer'); |
А в сам шаблон «answers_list» нужно добавить всего одну строку в самый конце кода:
Код |
<center><?=$pages_code;?></center> |
И всё. Теперь по центру экрана будет отображаться список страниц. Обратите внимание на ссылки, которые указывают на страницы:
http://ci/guestbook/index/10http://ci/guestbook/index/20http://ci/guestbook/index/30То есть каждая страница указывается в виде номера, с записи которого надо начать вывод. В соответствии с этим, мы модифицируем наши методы «index» в контроллере и метод «getLastAnswers» в модели. Будем передавать им число полученное из ссылки и с помощью «LIMIT» выводить ограниченное количество записей. Для того, чтобы метод «index» принимал данные из ссылки, укажем, что ему должен передаваться один параметр - «start_limit» (Как осуществляется передача
данных в функции из ссылок Вы можете прочитать в разделе «URI в Code Igniter»:
http://code-igniter.ru/user_guide/general/urls.html).
PHP |
function index($start_limit = 0) |
В самом начале кода мы пропустим это значение через функцию «intval», дабы избежать неприятностей, ведь эти данные пользователь может легко подделать, и доверять им нельзя.
PHP |
$start_limit = intval($start_limit); |
Передадим этот параметр методу «getLastAnswers» нашей модели для того, чтобы он поместился в запрос. Для этого заменим строку
PHP |
$answers = $this->Querys->getLastAnswers(); |
на
PHP |
$answers = $this->Querys->getLastAnswers($start_limit); |
Осталось лишь модифицировать метод «getLastAnswers». Добавим ему параметр «start_limit», который должен передаваться при вызове и заменим строки осуществления запроса с
PHP |
$sql = "SELECT * FROM guestbook ORDER BY id DESC"; $query = $this->db->query($sql); |
на
PHP |
$sql = "SELECT * FROM guestbook ORDER BY id DESC LIMIT ?,10"; $query = $this->db->query($sql,$start_limit); |
Теперь гостевая книга показывает отзывы в соответствии с номером страницы.
Если у Вас возникли какие-то трудности, то готовый код приложения Вы можете взять в файле «gb_sql.zip» который приложен к статье.