Creating dependent dropdowns in CakePHP 2 involves using AJAX to dynamically load data into the second dropdown based on the selection in the first. Here’s how you can implement a dependent dropdown of “State” and “District” in CakePHP 2:

Steps to Implement

1. Database Setup

Ensure you have two tables: states and districts, where districts has a state_id column to link districts to states.

Example schema:

  • states table:
    • id (Primary Key)
    • name (State Name)
  • districts table:
    • id (Primary Key)
    • name (District Name)
    • state_id (Foreign Key referencing states.id)

2. Controller Logic

In your controller (e.g., LocationsController):

  • Load states for the first dropdown.
  • Create an action to fetch districts based on the selected state.
class LocationsController extends AppController {
    public $uses = ['State', 'District'];

    public function index() {
        $states = $this->State->find('list', ['fields' => ['id', 'name']]);
        $this->set(compact('states'));
    }

    public function getDistricts($stateId = null) {
        $this->autoRender = false; // Disable view rendering
        if ($this->request->is('ajax') && $stateId) {
            $districts = $this->District->find('list', [
                'conditions' => ['District.state_id' => $stateId],
                'fields' => ['id', 'name']
            ]);
            echo json_encode($districts);
        }
    }
}

3. View

In your view file (e.g., index.ctp), create the dropdowns and include jQuery for AJAX:

echo $this->Form->create('Location', ['id' => 'LocationForm']);
echo $this->Form->input('state_id', [
    'type' => 'select',
    'options' => $states,
    'empty' => 'Select a State',
    'id' => 'StateDropdown'
]);
echo $this->Form->input('district_id', [
    'type' => 'select',
    'options' => [],
    'empty' => 'Select a District',
    'id' => 'DistrictDropdown'
]);
echo $this->Form->end();
?>

<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script>
$(document).ready(function() {
    $('#StateDropdown').change(function() {
        var stateId = $(this).val();
        if (stateId) {
            $.ajax({
                url: "<?php echo $this->Html->url(['controller' => 'locations', 'action' => 'getDistricts']); ?>/" + stateId,
                type: "GET",
                dataType: "json",
                success: function(data) {
                    var districtDropdown = $('#DistrictDropdown');
                    districtDropdown.empty();
                    districtDropdown.append('<option value="">Select a District</option>');
                    $.each(data, function(key, value) {
                        districtDropdown.append('<option value="' + key + '">' + value + '</option>');
                    });
                },
                error: function() {
                    alert('Unable to fetch districts.');
                }
            });
        } else {
            $('#DistrictDropdown').empty().append('<option value="">Select a District</option>');
        }
    });
});
</script>

4. Routing

Ensure your routes are configured correctly for the AJAX request:

Router::connect('/locations/getDistricts/*', ['controller' => 'locations', 'action' => 'getDistricts']);

5. Result

  • The “State” dropdown is populated with data from the states table.
  • When a state is selected, an AJAX request fetches the corresponding districts and populates the “District” dropdown dynamically.

This approach ensures your dependent dropdown works efficiently in CakePHP 2.


Here is the SQL to create the districts table with the specified schema:

CREATE TABLE districts (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255) NOT NULL,
state_id INT NOT NULL,
FOREIGN KEY (state_id) REFERENCES states(id) ON DELETE CASCADE ON UPDATE CASCADE
);

Insert Query for Indian Districts
INSERT INTO districts (name, state_id) VALUES
— Andhra Pradesh
(‘Anantapur’, 1),
(‘Chittoor’, 1),
(‘East Godavari’, 1),
(‘Guntur’, 1),
(‘Kadapa’, 1),

— Arunachal Pradesh
(‘Tawang’, 2),
(‘West Kameng’, 2),
(‘East Kameng’, 2),
(‘Papum Pare’, 2),
(‘Kurung Kumey’, 2),

— Assam
(‘Baksa’, 3),
(‘Barpeta’, 3),
(‘Biswanath’, 3),
(‘Bongaigaon’, 3),
(‘Cachar’, 3),

— Bihar
(‘Araria’, 4),
(‘Arwal’, 4),
(‘Aurangabad’, 4),
(‘Banka’, 4),
(‘Begusarai’, 4),

— Gujarat
(‘Ahmedabad’, 5),
(‘Amreli’, 5),
(‘Anand’, 5),
(‘Aravalli’, 5),
(‘Banaskantha’, 5),

— Karnataka
(‘Bagalkot’, 6),
(‘Ballari’, 6),
(‘Belagavi’, 6),
(‘Bengaluru Rural’, 6),
(‘Bengaluru Urban’, 6),

— Maharashtra
(‘Ahmednagar’, 7),
(‘Akola’, 7),
(‘Amravati’, 7),
(‘Aurangabad’, 7),
(‘Beed’, 7),

— Tamil Nadu
(‘Ariyalur’, 8),
(‘Chengalpattu’, 8),
(‘Chennai’, 8),
(‘Coimbatore’, 8),
(‘Cuddalore’, 8),

— Uttar Pradesh
(‘Agra’, 9),
(‘Aligarh’, 9),
(‘Allahabad’, 9),
(‘Ambedkar Nagar’, 9),
(‘Amethi’, 9),

— West Bengal
(‘Alipurduar’, 10),
(‘Bankura’, 10),
(‘Birbhum’, 10),
(‘Cooch Behar’, 10),
(‘Dakshin Dinajpur’, 10);

Secured By miniOrange