jQuery UI library provided different types of user interface widgets that are easy to implement on the page. One of the powerful widget is autocomplete.
It displays the suggestion list while typing in the input box. You can preload its data on the client side while initialization or load it dynamically using AJAX.
In this tutorial, I show how you can add jQuery UI Autocomplete in CakePHP 4 and load MySQL database data using jQuery AJAX.
Contents
- Create Table
- Database Configuration
- Create Model
- Create Controller
- Include jQuery and CSRF token
- Create Template
- Output
- Conclusion
1. Create Table
In the example, I am using users
Tables. It has the following structure and data –
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@makitweb.com', 'Bhopal'), (2, 'bsonarika', 'Sonarika Bhadoria', 'female', 'bsonarika@makitweb.com', 'Indore'), (3, 'sunil', 'Sunil singh', 'male', 'sunil@makitweb.com', 'Pune'), (4, 'vishal', 'Vishal Sahu', 'male', 'vishal@makitweb.com', 'Bhopal'), (5, 'jiten', 'jitendra singh', 'male', 'jitendra@makitweb.com', 'Delhi'), (6, 'shreya', 'Shreya joshi', 'female', 'shreya@makitweb.com', 'Indore'), (7, 'abhilash', 'Abhilash namdev', 'male', 'abhilash@makitweb.com', 'Pune'), (8, 'ekta', 'Ekta patidar', 'female', 'ekta@makitweb.com', 'Bhopal'), (9, 'deepak', 'Deepak singh', 'male', 'deepak@makitweb.com', 'Delhi'), (10, 'rohit', 'Rohit Kumar', 'male', 'rohit@makitweb.com', 'Bhopal'), (11, 'bhavna', 'Bhavna Mahajan', 'female', 'bhavna@makitweb.com', 'Indore'), (12, 'ajay', 'Ajay singh', 'male', 'ajay@makitweb.com', 'Delhi'), (13, 'mohit', 'Mohit', 'male', 'mohit@makitweb.com', 'Pune'), (14, 'akhilesh', 'Akhilesh Sahu', 'male', 'akhilesh@makitweb.com', 'Indore'), (15, 'ganesh', 'Ganesh', 'male', 'ganesh@makitweb.com', 'Pune'), (16, 'vijay', 'Vijay', 'male', 'vijay@makitweb.com', 'Delhi');
2. Database Configuration
- Open
config/app_local.php
file. - Specify your database configuration details in the
Datasources
default
.
'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. Create Model
- CreateÂ
Users
 Model.
bin/cake bake model Users
- This will create 2 files –
src/Model/Entity/User.php src/Model/Table/UsersTable.php
src/Model/Entity/User.php
In this Entity class specify field names that you want to allow insertion and updation. You can either remove the field name or set it to false
 if you don’t want to allow.
Completed Code
<?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
This Table class tells ORM which table needs to use and defines validation rules for the fields.
Completed Code
<?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. Create Controller
- Create aÂ
AutcompleteController.php
 file inÂsrc/Controller/
 folder. - CreateÂ
AutocompleteController
 Class that extendsÂAppController
.
Create 2 method –
- index()Â
- getUserSuggestions() – Using this method handle jQuery UI AJAX requests and return autocomplete suggestion list.
Read POST search
value and assign it to $search
variable. Create an object of Users
Table using – $this->getTableLocator()->get('Users')
. If $search
is not empty then set WHERE
to search on name
field using LIKE
.
I have set limit of 5 you can remove it or adjust it according to your requirement while implementing on your project.
Create $data_arr
Array to store return response and loop on the fetched records. Store $user['id']
to value
key of $data_arr
and $user['name']
to label
key of $data_arr
Array.
Return $data_arr
in JSON format.
Completed Code
<?php declare(strict_types=1); namespace App\Controller; class AutocompleteController extends AppController { public function index(){ } // Get Autocomplete Data public function getUserSuggestions(){ ## POST value $search = trim($this->request->getData()['search']); ## Fetch users $USERS = $this->getTableLocator()->get('Users'); $query = $USERS->find('all'); // Search value 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. Include jQuery and CSRF token
I am including JS libraries and CSRF token on templates/layout/default.php
file.
Stored CSRF token in <meta >
tag –
<?= $this->Html->meta('csrfToken', $this->request->getAttribute('csrfToken')); ?>
Include jQuery and jQuery UI library in <head >
section –
<!-- 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>
Completed Code
<?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. Create Template
Create Autocomplete
folder in templates/
location. In the Autocomplete
 folder create index.php
file – templates/Autocomplete/index.php
.
Create 2 input elements –
- The first input element is use to initialize jQuery UI autocomplete.
- The second input element is use to display the selected item value. I am displaying userid in this element.
jQuery
Read CSRF token from the <meta >
tag and assign it to csrfToken
variable.
Initialize autocomplete on #searchuser
and set 3 options –
- source – Using this option load data.
Send AJAX POST request to $this->Url->build(['controller' => 'Autocomplete','action' => 'getUserSuggestions'])
, set dataType: 'json'
, pass typed value as data – { search: request.term }
, also pass CSRF token using headers – { 'X-CSRF-Token': csrfToken }
.
On successful callback pass response data to response()
.
- select – This event triggers when an item is selected from the suggestion list.
Store selected item label
in #searchuser
and value
in #userid
.
- focus – This event triggers when navigating the list using the keyboard arrow keys.
Store selected item label
in #searchuser
and value
in #userid
.
Completed Code
<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/javascript"> // Read CSRF Token var csrfToken = $('meta[name="csrfToken"]').attr('content'); $(document).ready(function(){ // Initialize $( "#searchuser" ).autocomplete({ source: function( request, response ) { // Fetch data $.ajax({ url: "<?= $this->Url->build(['controller' => 'Autocomplete','action' => 'getUserSuggestions']) ?>", type: 'post', dataType: "json", data: { search: request.term }, headers:{ 'X-CSRF-Token': csrfToken }, success: function( data ) { response( data ); } }); }, select: function (event, ui) { // Set selection $('#searchuser').val(ui.item.label); // display the selected text $('#userid').val(ui.item.value); // save selected id to input return false; }, focus: function(event, ui){ $( "#searchuser" ).val( ui.item.label ); $( "#userid" ).val( ui.item.value ); return false; }, }); }); </script>
7. Output
8. Conclusion
jQuery UI autocomplete can greatly enhance the search functionality of your web pages it makes them more user-friendly and efficient. Users can easily find what they are looking for by simply typing a few characters, and the real-time search suggestions can significantly improve their experience.
I hope this tutorial has been helpful in getting you started.
You can also checkout this tutorial if you want to know auto-populate dropdown using jQuery AJAX in CakePHP 4.
If you found this tutorial helpful then don't forget to share.