Yii PHP фреймворк: создаем поле с автозаполнением

16 мая, 2010
yii php framework autocomplete

Приветствую всех!

Сегодня я покажу небольшой пример использования виджета CAutoComplete из фреймворка Yii. Как несложно догадаться, он создаёт текстовое поле, под которым может появляться список с вариантами подстановок.

Принцип создания такого поля довольно прост. На странице нужно поместить обычное текстовое поле и назначить событию onKeyUp обработчик, который будет отправлять AJAX запросы серверу. В этих запросах нужно передавать введённый посетителем текст. Сервер ищет совпадения с этим текстом в БД и возвращает результат браузеру. JavaScript обработчик создаёт список с вариантами, полученными от сервера, и показывает его под полем.

Как видите, алгоритм несложный, но рутинной работы много.

Теперь, давайте разберёмся, что сделает за вас виджет, а что придётся делать вам.

Для работы виджет использует плагин Autocomplete библиотеки jQuery, т.е. писать JS код от вас не потребуется (если, конечно, вы не хотите изменить стандартное поведение плагина).

Кроме того, виджет создаст текстовое поле и подключит все необходимые JS и CSS файлы. Вам нужно будет только указать некоторые настройки.

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

Теперь рассмотрим пример.

Допустим, у нас есть база данных с названиями стран. Таблица называется countries, а поле, в котором хранятся названия – c_name.

Создаём для этой таблицы модель.

yiic shell
model countries

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

Теперь нужно создать текстовое поле. CAutoComplete – это обычный виджет, поэтому поместить его можно где угодно. Если хотите, чтобы поле выводилось на отдельной странице – добавляйте его в соответствующее представление, хотите показывать на каждой странице – добавляйте в макет (layout).

Код вставки виджета выглядит так.

  1. $this->widget('CAutoComplete',
  2.     array(
  3.         'model'=>'countries',
  4.         'name'=>'country',
  5.         'url'=>array('countries/autocomplete'),
  6.         'minChars'=>2,
  7.     )
  8. );

Во втором параметре необходимо передать массив с параметрами. Обязательными являются первые два.
model – имя модели.
name – атрибут name текстового поля.
url – адрес скрипта, который будет обрабатывать AJAX запросы.
minChars – минимальное количество символов, при котором выполняется отправка запроса.

Естественно, это не все параметры. Подробный их перечень вы найдете на странице документации.

По мере ввода текста серверному скрипту будут отправляться AJAX запросы вида:

index.php?r=countries/autocomplete&q=%D0%B0%D0%BB&limit=10&timestamp=1273944702297

В параметре q передаётся введённый посетителем текст, а в параметре limit – максимальное количество подстановок.

Рассмотрим метод, выполняющий обработку этого запроса.

  1. public function actionAutoComplete() {
  2.    
  3.     if (isset($_GET['q'])) {
  4.        
  5.         $criteria = new CDbCriteria;
  6.         $criteria->condition = 'c_name LIKE :country';
  7.         $criteria->params = array(':country'=>$_GET['q'].'%');
  8.        
  9.         if (isset($_GET['limit']) && is_numeric($_GET['limit'])) {
  10.             $criteria->limit = $_GET['limit'];
  11.         }
  12.        
  13.         $countries = countries::model()->findAll($criteria);
  14.        
  15.         $resStr = ";
  16.         foreach ($countries as $country) {
  17.             $resStr .= $country->c_name."\n";
  18.         }
  19.         echo $resStr;
  20.     }
  21. }

Здесь мы проверяем, пришли ли параметры и формируем запрос.

Условие записываем с помощью класса CDbCriteria. В атрибуте condition указываем название поля и операцию сравнения (LIKE). В атрибуте params – текст, введенный пользователем. Обратите внимание, мы добавляем к нему знак %, т.е. найдены будут все страны, названия которых начинаются с указанных букв.

Затем добавляем параметр limit и выполняем запрос (findAll).

Из результатов поиска формируем строку с найденными названиями стран. Разделителем служит символ новой строки (это требование плагина). И отправляем результат браузеру.

Как видите, пользоваться виджетом совсем не сложно.

Все вопросы, советы и замечания пишите в комментариях.

Удачи!

Понравилась статья? Подписывайтесь на продолжение rss link !

Или на мой твиттер twitter link

]]>

Добавьте эту страницу в google.com bobrdobr.ru del.icio.us technorati.com linkstore.ru news2.ru rumarkz.ru memori.ru moemesto.ru

]]>

Опубликовано в MySQL, PHP, Web разработка, Yii View Comments

]]>
  • Jay
    Конечно круто кодить только на PHP не пользуясь JavaScript, но посмотрите на то что пишет Yii в JavaScript. Иногда гораздо легче реализовать простые Ajax запросы методом jQuery - $('#element').load('?r=controller/action',{var:value});
  • Я согласен. Но никто не запрещает использовать вместе с Yii свои скрипты, если код, который генерирует Yii вас не устраивает.
  • Спасибо за интересный примерчик! Думаю, пригодится!
  • Storm
    Спасибо! Статья как раз вовремя :)
    Попутно возник вопрос:
    не подскажете как можно в ajax-запросе передать кроме содержимого поля, значение выпадающего списка, расположенного на той же форме, где поле с автодополнением?

    У CAutoComplete есть параметр extraParams (http://www.yiiframework.com/doc/api/CAutoComplete#extraParams-detail), который позволяет в ajax-запросе передавать дополнительные параметры. А вот как в него загрузить значение <select> что-то не соображу :|</select>
  • Судя по всему, CAutoComplete немного урезает возможности плагина Autocomplete.

    В документации сказано, что параметру extraParams можно передавать функцию. Но если передать функцию в настройках CAutoComplete, то она будет взята в кавычки, т.е. станет обычной строкой.

    Поэтому решение такое.

    Написать свой js скрипт с кодом

    jQuery("#country").setOptions({
    'extraParams':{'mypar':function() {return $("#myselect").val();}}}
    );

    country - id поля с автозавершением,
    myselect - id выпадающего списка.

    Подключить этот скрипт с помощью registerClientScript()
  • Storm
    Большое спасибо! Если бы сам и додумался, то еще не скоро :)
  • По-моему из $_GET['q'] надо удалять %, иначе передадут % и будет ошибка.
    Вы еще не используете gii для кодогенерации?
  • Согласен, проверять полученные данные нужно обязательно.
    gii попробовал, но особых преимуществ пока не почувствовал.
  • Michael
    Спасибо, очень нужная вещь
  • test10
    demo?
  • Не вижу смысла. Все-равно код придется переделывать под конкретную БД.
  • SamDark
    У CDbCriteria есть метод addSearchCondition. С ним будет немного чище.
  • Спасибо!

    Получилось так

    $criteria->addSearchCondition('c_name', $_GET['q'].'%', false);

    если оставить с дефолтными настройками
    $criteria->addSearchCondition('c_name', $_GET['q']);
    то % будет добавлен с обоих сторон, а это не совсем то, что хотелось получить :)
blog comments powered by Disqus ]]>