CakePHP: Как добавить jQuery UI Autocomplete с помощью AJAX в CakePHP 4

Библиотека jQuery UI предоставляет различные типы виджетов пользовательского интерфейса, которые легко реализовать на странице. Одним из мощных виджетов является автозаполнение (Autocomplete).
Он отображает список предложений при вводе текста в поле ввода. Вы можете предварительно загрузить его данные на стороне клиента при инициализации или загрузить их динамически с помощью AJAX.
В этом руководстве я покажу, как можно добавить jQuery UI Autocomplete в CakePHP 4 и загрузить данные базы данных MySQL с помощью jQuery AJAX.
И так, давайте приступим к практике:
1. Создайте таблицу
В примере я использую таблицы пользователей (Users
). Она имеет следующую структуру и данные:
CREATE TABLE `users` (
`id` int(11) NOT NULL,
`username` varchar(50) NOT NULL,
`name` varchar(60) NOT NULL,
`gender` varchar(10) NOT NULL,
`email` varchar(60) NOT NULL,
`city` varchar(80) NOT NULL
);
ALTER TABLE `users`
ADD PRIMARY KEY (`id`);
ALTER TABLE `users`
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;
INSERT INTO `users` (`id`, `username`, `name`, `gender`, `email`, `city`) VALUES
(1, 'yssyogesh', 'Yogesh singh', 'male', 'yogesh@makecodes.ru', 'Bhopal'),
(2, 'bsonarika', 'Sonarika Bhadoria', 'female', 'bsonarika@makecodes.ru', 'Indore'),
(3, 'sunil', 'Sunil singh', 'male', 'sunil@makecodes.ru', 'Pune'),
(4, 'vishal', 'Vishal Sahu', 'male', 'vishal@makecodes.ru', 'Bhopal'),
(5, 'jiten', 'jitendra singh', 'male', 'jitendra@makecodes.ru', 'Delhi'),
(6, 'shreya', 'Shreya joshi', 'female', 'shreya@makecodes.ru', 'Indore'),
(7, 'abhilash', 'Abhilash namdev', 'male', 'abhilash@makecodes.ru', 'Pune'),
(8, 'ekta', 'Ekta patidar', 'female', 'ekta@makecodes.ru', 'Bhopal'),
(9, 'deepak', 'Deepak singh', 'male', 'deepak@makecodes.ru', 'Delhi'),
(10, 'rohit', 'Rohit Kumar', 'male', 'rohit@makecodes.ru', 'Bhopal'),
(11, 'bhavna', 'Bhavna Mahajan', 'female', 'bhavna@makecodes.ru', 'Indore'),
(12, 'ajay', 'Ajay singh', 'male', 'ajay@makecodes.ru', 'Delhi'),
(13, 'mohit', 'Mohit', 'male', 'mohit@makecodes.ru', 'Pune'),
(14, 'akhilesh', 'Akhilesh Sahu', 'male', 'akhilesh@makecodes.ru', 'Indore'),
(15, 'ganesh', 'Ganesh', 'male', 'ganesh@makecodes.ru', 'Pune'),
(16, 'vijay', 'Vijay', 'male', 'vijay@makecodes.ru', 'Delhi');
2. Конфигурация базы данных
Откройте файл config/app_local.php.
Укажите детали конфигурации вашей базы данных в Datasources по умолчанию.
'Datasources' => [
'default' => [
'host' => '127.0.0.1',
/*
* CakePHP will use the default DB port based on the driver selected
* MySQL on MAMP uses port 8889, MAMP users will want to uncomment
* the following line and set the port accordingly
*/
//'port' => 'non_standard_port_number',
'username' => 'root',
'password' => 'root',
'database' => 'cakephp4',
/*
* If not using the default 'public' schema with the PostgreSQL driver
* set it here.
*/
//'schema' => 'myapp',
/*
* You can use a DSN string to set the entire configuration
*/
'url' => env('DATABASE_URL', null),
],
/*
* The test connection is used during the test suite.
*/
'test' => [
'host' => 'localhost',
//'port' => 'non_standard_port_number',
'username' => 'my_app',
'password' => 'secret',
'database' => 'test_myapp',
//'schema' => 'myapp',
'url' => env('DATABASE_TEST_URL', 'sqlite://127.0.0.1/tests.sqlite'),
],
],
3. Создание модели
Создайте модель Users
bin/cake bake model Users
В результате будет создано 2 файла
src/Model/Entity/User.php
src/Model/Table/UsersTable.php
src/Model/Entity/User.php
В этом классе Entity укажите имена полей, которые вы хотите разрешить вставлять и обновлять. Вы можете либо удалить имя поля, либо установить его в false
, если не хотите разрешать.
Готовый код
<?php
declare(strict_types=1);
namespace App\Model\Entity;
use Cake\ORM\Entity;
class User extends Entity
{
protected $_accessible = [
'username' => true,
'name' => true,
'gender' => true,
'email' => true,
'city' => true,
];
}
src/Model/Table/UsersTable.php
Этот класс указывает ORM, какую таблицу нужно использовать, и определяет правила валидации для полей.
Готовый код
<?php
declare(strict_types=1);
namespace App\Model\Table;
use Cake\ORM\Query;
use Cake\ORM\RulesChecker;
use Cake\ORM\Table;
use Cake\Validation\Validator;
class UsersTable extends Table
{
public function initialize(array $config): void
{
parent::initialize($config);
$this->setTable('users');
$this->setDisplayField('name');
$this->setPrimaryKey('id');
}
public function validationDefault(Validator $validator): Validator
{
$validator
->scalar('username')
->maxLength('username', 50)
->requirePresence('username', 'create')
->notEmptyString('username');
$validator
->scalar('name')
->maxLength('name', 60)
->requirePresence('name', 'create')
->notEmptyString('name');
$validator
->scalar('gender')
->maxLength('gender', 10)
->requirePresence('gender', 'create')
->notEmptyString('gender');
$validator
->email('email')
->requirePresence('email', 'create')
->notEmptyString('email');
$validator
->scalar('city')
->maxLength('city', 80)
->requirePresence('city', 'create')
->notEmptyString('city');
return $validator;
}
public function buildRules(RulesChecker $rules): RulesChecker
{
$rules->add($rules->isUnique(['username']), ['errorField' => 'username']);
$rules->add($rules->isUnique(['email']), ['errorField' => 'email']);
return $rules;
}
}
4. Создание контроллера
Создайте файл AutcompleteController.php в папке src/Controller/.
Создайте класс AutocompleteController, который расширяет AppController.
Создайте 2 метода
- index()
- getUserSuggestions() - С помощью этого метода обрабатываются запросы jQuery UI AJAX и возвращается список предложений автозаполнения.
Читаем значение POST search
и присваеваем его переменной $search
. Создадим объект таблицы Users
, используя - $this->getTableLocator()->get('Users')
. Если $search
не пуст, установим WHERE
для поиска по полю name
с помощью LIKE
.
Я установил ограничение в 5, вы можете удалить его или скорректировать в соответствии с вашими требованиями при реализации вашего проекта.
Создаем массив $data_arr
для хранения возвращенного ответа и выполнения цикла по полученным записям. Сохраним $user['id']
в ключе value
массива $data_arr
и $user['name']
в ключе label
массива $data_arr
.
Вернем $data_arr
в формате JSON.
Готовый код
<?php
declare(strict_types=1);
namespace App\Controller;
class AutocompleteController extends AppController
{
public function index(){
}
// Получение данных для автозаполнения
public function getUserSuggestions(){
## значение POST
$search = trim($this->request->getData()['search']);
## Получение пользователей
$USERS = $this->getTableLocator()->get('Users');
$query = $USERS->find('all');
// Значение для поиска
if(!empty($search)){
$query->where(['name LIKE' => "%".$search."%"]);
}
$query->order(['name' => 'ASC']);
$query->limit(5);
$usersList = $query->toArray();
$data_arr = array();
foreach($usersList as $user){
$data_arr[] = array(
'value' => $user['id'],
'label' => $user['name']
);
}
echo json_encode($data_arr);
die;
}
}
5. Подключим jQuery и CSRF-токен
Я подключу библиотеки JS и CSRF-токен в файле templates/layout/default.php.
Сохраним CSRF-токена в теге <meta>
<?= $this->Html->meta('csrfToken', $this->request->getAttribute('csrfToken')); ?>
Подключим jQuery и библиотеку jQuery UI в раздел <head>.
<!-- jQuery UI CSS -->
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.13.2/themes/smoothness/jquery-ui.css">
<!-- jQuery -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.3/jquery.min.js"></script>
<!-- jQuery UI JS -->
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.13.2/jquery-ui.min.js"></script>
Готовый код
<?php
$cakeDescription = 'CakePHP: the rapid development php framework';
?>
<!DOCTYPE html>
<html>
<head>
<?= $this->Html->charset() ?>
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- CSRF Token -->
<?= $this->Html->meta('csrfToken', $this->request->getAttribute('csrfToken')); ?>
<title>
<?= $cakeDescription ?>:
<?= $this->fetch('title') ?>
</title>
<?= $this->Html->meta('icon') ?>
<link href="https://fonts.googleapis.com/css?family=Raleway:400,700" rel="stylesheet">
<?= $this->Html->css(['normalize.min', 'milligram.min', 'cake']) ?>
<!-- jQuery UI CSS -->
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.13.2/themes/smoothness/jquery-ui.css">
<!-- jQuery -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.3/jquery.min.js"></script>
<!-- jQuery UI JS -->
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.13.2/jquery-ui.min.js"></script>
<?= $this->fetch('meta') ?>
<?= $this->fetch('css') ?>
<?= $this->fetch('script') ?>
</head>
<body>
<nav class="top-nav">
<div class="top-nav-title">
<a href="<?= $this->Url->build('/') ?>"><span>Cake</span>PHP</a>
</div>
<div class="top-nav-links">
<a target="_blank" rel="noopener" href="https://book.cakephp.org/4/">Documentation</a>
<a target="_blank" rel="noopener" href="https://api.cakephp.org/">API</a>
</div>
</nav>
<main class="main">
<div class="container">
<?= $this->Flash->render() ?>
<?= $this->fetch('content') ?>
</div>
</main>
<footer>
</footer>
</body>
</html>
6. Создадим шаблон
Создайте папку Autocomplete в папке templates/. В папке Autocomplete создайте файл index.php
Создайте 2 элемента input
- Первый элемент input используется для инициализации автозаполнения jQuery UI.
- Второй элемент input используется для отображения значения выбранного элемента. В этом элементе я отображаю userid.
jQuery
Прочитаем CSRF-токен из тега <meta> и присвоим его переменной csrfToken.
Инициализируем автозаполнение на #searchuser и установим 3 опции
- source – При использовании этой опции загружаются данные.
Отправим AJAX POST запрос $this->Url->build(['controller' => 'Autocomplete','action' => 'getUserSuggestions'])
, установим dataType: 'json'
, передадим значение как данные - { search: request.term }
, также передадим CSRF-токен с помощью заголовков - { 'X-CSRF-Token': csrfToken }
.
При успешном обратном вызове передадим данные ответа в response().
- select - Это событие срабатывает, когда элемент выбран из списка предложений.
Метка выбранного элемента хранится в #searchuser
, а value
- в #userid
.
- focus - Это событие срабатывает при навигации по списку с помощью клавиш со стрелками.
Сохраним label
выбранного элемента в #searchuser
и value
в #userid
.
Готовый код
<div class="row">
<div class="col-6">
<!-- -->
<?php
echo $this->Form->control('searchuser',['id'=>'searchuser','label'=>'Search User','class' => 'form-control']);
echo $this->Form->control('userid',['id'=>'userid','label' => 'Selected User ID','class' => 'form-control']);
?>
<!-- -->
</div>
</div>
<!-- Script -->
<script type="text/jаvascript">
// Чтение CSRF-токена
var csrfToken = $('meta[name="csrfToken"]').attr('content');
$(document).ready(function(){
// Инициализация
$( "#searchuser" ).autocomplete({
source: function( request, response ) {
// Получение данных
$.ajax({
url: "<?= $this->Url->build(['controller' => 'Autocomplete','action' => 'getUserSuggestions']) ?>",
type: 'post',
dataType: "json",
dаta: {
search: request.term
},
headers:{
'X-CSRF-Token': csrfToken
},
success: function( data ) {
response( data );
}
});
},
select: function (event, ui) {
// Установим выбор
$('#searchuser').val(ui.item.label); // отобразить выбранный текст
$('#userid').val(ui.item.value); // сохранить выбранный идентификатор для ввода
return false;
},
focus: function(event, ui){
$( "#searchuser" ).val( ui.item.label );
$( "#userid" ).val( ui.item.value );
return false;
},
});
});
</script>
Вывод
Автозаполнение jQuery UI может значительно расширить функциональность поиска на ваших веб-страницах, сделав их более удобными и эффективными. Пользователи могут легко найти то, что они ищут, просто набрав несколько символов, а поисковые предложения в реальном времени могут значительно улучшить их опыт.
Я надеюсь, что это руководство было полезным для начала работы.
Посетители, находящиеся в группе Гости, не могут оставлять комментарии к данной публикации.