Search Country use jQuery Ajax CakePHP4

I’m learned to search country use jQuery ajax in CakePHP4 based on my browsing below
https://makitweb.com/how-to-add-select2-in-cakephp-4-and-load-data-using-jquery-ajax/

I’m replaced with Countries table. Here’s below my complete code.
inside \Controller\CoutriesController.php

<?php
declare(strict_types=1);

namespace App\Controller;

/**
 * Countries Controller
**/
class CountriesController extends AppController
{
   public function index()
    {
        $countrires = $this->paginate($this->Countries);

        $this->set(compact('countries'));
    }

    //fungsi getCountriyList()
	public function getCountryList()
	{
		//nilai POST
		$search = "";
		if(isset($this->request->getData()['SearchTerm'])) {
			$search = trim($this->request->getData()['SearchTerm']);
		}
		
		//kumpulkan countries
		$COUNTRIES = $this->getTableLocator()->get('Countries');
		
		$query = $COUNTRIES->find('all');
		
		//nilai pencarian
		if(!empty($search)) {
			$query->where(['name LIKE' => "%".$search."%"]);
		}
		$query->order(['name' => 'ASC']);
		$query->limit(5);
		$countryList = $query->toArray();
		
		$data_arr = array();
		foreach($countryList as $country) {
			$data_arr[] = array(
				'id' => $country['id'],
				'name' => $country['name'],
				'sortname' => $country['sortname'],
				'phonecode' => $country['phonecode']
			);
		}
		
		echo json_encode($data_arr);
		die;
	}
}

I’m calling csrfToken inside \template\layout\default.php

<?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">
	<?php
		echo $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']) ?>

    <?= $this->fetch('meta') ?>
    <?= $this->fetch('css') ?>
    <?= $this->fetch('script') ?>
	<?php
		//embed bootstrap
		echo $this->Html->css('https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css');
		//embed css select
		echo $this->Html->css('https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/css/select2.min.css');
	?>
</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>
	<?php
		//embed jQuery dari google
		echo $this->Html->script('https://ajax.googleapis.com/ajax/libs/jquery/3.6.3/jquery.min.js');
		//embed select js
		echo $this->Html->script('https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/js/select2.min.js');
	?>
</body>
</html>

And then render output inside \templates\Countries\index.php

<html>
<head>
</head>
<body>
	<div class="row">
	  <div class="col-6">
		
		<!-- Country -->
		<div class="input" style="margin-bottom:15px;">
			<label for="selcountry">Country</label>
			<?php
				echo $this->Form->select(
					'selcountry',[],
									[
										'id' => 'selcountry',
										'empty' => '--Select Country--',
										'style' => 'width:250px;'
									]
					);
			?>
		</div>
		
		<!-- Select Country ID -->
		<?php
		echo $this->Form->control('countryid',array(
													['id' => 'countryid'],
													['label' => 'Selected Country ID'],
													['class' => 'form-control']
											));
		echo $this->Form->button('view', array(
												['type' => 'button'],
												['id' => 'btnview'],
												['value' => 'View Selected Country ID']
										));
		?>
	  </div>
	</div>
	<?php
		//embed jQuery dari google
		echo $this->Html->script('https://ajax.googleapis.com/ajax/libs/jquery/3.6.3/jquery.min.js');
		//embed select js
		echo $this->Html->script('https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/js/select2.min.js');
	?>
	<!-- script -->
	<script type="text/javascript">
	
	//baca csrfToken
	var csrfToken = $('meta[name="csrfToken"]').attr('content');
	$(document).ready(function(){
		
		//selectCountry
		$("#selcountry").select2({
			ajax: {
				url: "<?= $this->Url->build(['controller' => 'CountriesController', 'action' => 'getCountryList']) ?>",
				type: "post",
				dataType: 'json',
				delay: 250,
				headers:{
					'X-CSRF-Token': csrfToken
				},
				data: function (params) {
					return {
						searchTerm: params.term
					};
				},
				processResults: function(response) {
					return {
						results: response
					};
				},
				cache: true
			}
		});
		
		//Read selected value
		$('#btnview').click(function(){
			var countryid = $('#selcountry').val();
			$('#countryid').val(countryid);
		});
	});
	</script>
</body>
</html>

why the result comes error, below this

Warning (2) : compact(): Undefined variable $countries [in C:\xampp\htdocs\jqueryload\src\Controller\CountriesController.php, line 23]
Warning (512) : Unable to emit headers. Headers sent in file=C:\xampp\htdocs\jqueryload\vendor\cakephp\cakephp\src\Error\Renderer\HtmlErrorRenderer.php line=36 [in C:\xampp\htdocs\jqueryload\vendor\cakephp\cakephp\src\Http\ResponseEmitter.php, line 71]
Warning (2) : Cannot modify header information - headers already sent by (output started at C:\xampp\htdocs\jqueryload\vendor\cakephp\cakephp\src\Error\Renderer\HtmlErrorRenderer.php:36) [in C:\xampp\htdocs\jqueryload\vendor\cakephp\cakephp\src\Http\ResponseEmitter.php, line 168]
Warning (2) : Cannot modify header information - headers already sent by (output started at C:\xampp\htdocs\jqueryload\vendor\cakephp\cakephp\src\Error\Renderer\HtmlErrorRenderer.php:36) [in C:\xampp\htdocs\jqueryload\vendor\cakephp\cakephp\src\Http\ResponseEmitter.php, line 197]
Warning (2) : Cannot modify header information - headers already sent by (output started at C:\xampp\htdocs\jqueryload\vendor\cakephp\cakephp\src\Error\Renderer\HtmlErrorRenderer.php:36) [in C:\xampp\htdocs\jqueryload\vendor\cakephp\cakephp\src\Http\ResponseEmitter.php, line 197]
Warning (2) : Cannot modify header information - headers already sent by (output started at C:\xampp\htdocs\jqueryload\vendor\cakephp\cakephp\src\Error\Renderer\HtmlErrorRenderer.php:36) [in C:\xampp\htdocs\jqueryload\vendor\cakephp\cakephp\src\Http\ResponseEmitter.php, line 236]

I hope someone can help me to fix this, thanx !

In your index function, you’ve initialized the variable $countrires, not $countries.

1 Like

for a while, the test was running, but I’m checked in debug browser, I get error message below

Failed to load resource: the server responded with a status of 404 (Not Found) /jqueryload/countries-controller/get-country-list:1

where’s the line code, should I fix it below
\Controller\CountriesController.php

<?php
declare(strict_types=1);

namespace App\Controller;

class CountriesController extends AppController
{
    //fungsi getCountriyList()
	public function getCountryList()
	{
		//nilai POST
		$search = "";
		if(isset($this->request->getData()['SearchTerm'])) {
			$search = trim($this->request->getData()['SearchTerm']);
		}
		
		//kumpulkan countries
		$COUNTRIES = $this->getTableLocator()->get('Countries');
		
		$query = $COUNTRIES->find('all');
		
		//nilai pencarian
		if(!empty($search)) {
			$query->where(['name LIKE' => "%".$search."%"]);
		}
		$query->order(['name' => 'ASC']);
		$query->limit(5);
		$countryList = $query->toArray();
		
		$data_arr = array();
		foreach($countryList as $country) {
			$data_arr[] = array(
				'id' => $country['id'],
				'name' => $country['name'],
				'sortname' => $country['sortname'],
				'phonecode' => $country['phonecode']
			);
		}
		
		echo json_encode($data_arr);
		die;
	}
}

I hope someone could help me to fix it, thanx

Where does the /jqueryload part of that URL come from?

the url jqueryload is my root folder that used to test jQuery and CakePHP, below this
http://localhost/jqueryload/Countries/index

So the URL you reference should be /jqueryload/countries/get-country-list, not /jqueryload/countries-controller/get-country-list, presumably.