CakePHP and JQuery

Although Prototype is the default Javascript Framework for CakePHP, using JQuery (or any other Ajax Framework) with Cake could not be easier. Perhaps the most difficult aspect of integrating JQuery with Cake was trying to find documentation on some of those little things that are necessary to return a result set without an error (see my post, CakePHP and Ajax: Missing View).

Note: I purposely wrote this post as if I were speaking to someone who has never used CakePHP. So some parts of this post may be common knowledge to the more experienced Bakers.

Routing

First let’s add a route. Understanding routing is very important (especially when making Ajax requests). Open the file app/config/routes.php and scroll down to the bottom. If you have never opened this file previously, you should see the default routing:

Router::connect('/', array('controller' => 'pages', 'action' => 'display', 'home'));

Add the following route below the existing routes:

Router::connect('domainnames/', array('controller' => 'domainnames', 'action'=> 'index'));

Basically, the route above say that when the url:

http://somesite/domainnames/

is loaded in the browser, the domainnames controller’s index method will be called. More on this later.

The Controller

So I’ll create a controller named domainnames_controller.php. I save the file in app/controllers.

class DomainnamesController extends AppController {
 
	var $helpers = array('Javascript', 'Html');
	var $components = array('RequestHandler');
 
	function index() {
		$this->pageTitle = 'Web 2.0 Domain Names';
		$this->layout = 'default_web20_domains';
	}
}

I’ve added the Javascript Helper and the RequestHandler Component. The Javascript Helper is used to load jquery and other files.

You see the controller contains the index method that is called in the routing.php file.

$this->layout tells the controller the name of the default layout.

Layout

Create a new Html file. Name it default_web20_domains.ctp and save it under apps/views/layouts/

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
	<head>
		<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
		<title><?php echo $title_for_layout ?></title>
		<?=$html->meta('keywords', 'Web 2.0 Domain Search');?>
		<?=$html->css('web20_styles');?>
		<?=$html->css('jquery-ui/custom-theme/jquery-ui-1.7.2.custom');?>
		<?=$html->css('imdomainsearch/imDomainSearch');?>
		<?= $scripts_for_layout ?>
	</head>
        <body>
                <!-- body content -->
        </body>
</html>

We need the < ?= scripts_for_layout ? > to load jquery and other necessary files.

The View

Now we did not specify a view (‘action’ => ‘display’, ‘home’),
So the controller will automatically look for a file with the same name as the action value in the routes.php file (‘action’=> ‘index’)

Action = controller method = default view name

First create a folder named domainnames under the app/views directory.

Now create a file named index.ctp and save it under app/views/domainnames/.

<?php
$javascript->link(array('jquery/jquery-1.3.2.min', 'jquery/jquery-ui/jquery-ui', 'jquery/curvycorners', 'jquery/imDomainSearch/jquery.imDomainSearchSite-0.5', 'jquery/curvy_settings', 'jquery/imdomainsearch_settings'), false);
?>

I’m adding jquery, jquery ui, and jquery plugins. These files will be loaded via the scripts_for_layout in the default layout file (default_web20_domains.ctp).

<?= scripts_for_layout ?>

The scripts_for_layout will load all the javasript files on the web page. I you viewed the source in the browser, you will see:

<script type="text/javascript" src="jquery/jquery-1.3.2.min.js"></script>
<script type="text/javascript" src="jquery/jquery-ui/jquery-ui.js"></script>
<script type="text/javascript" src="jquery/curvycorners.js"></script>

All Javascript files should be saved under the app/webroot/js/ folder. I generally create sub-folders so that I can group related files. For instance, I created a folder named jquery under the js folder. Then I place the jquery-1.3.2.min file inside the jquery folder.

All other files placed under relevantly named folders. For instance, the domain search plugin is saved under the folder jquery/domainsearch/.

Of course, you can save them in whatever scheme you like, just as long as they are located in the app/webroot/js/ folder.

Plugins

One of the javascript files that loaded is named imdomainsearch_settings (terrible name). This file contains the settings for the jquery Domain Search plugin. Let’s create it.

Create a file named imdomainsearch_settings.js and save it under app/webroot/js/jquery.

?View Code JAVASCRIPT
$(document).ready(function(){
	$("#leftSideTop").imDomainSearch({
		search_url:'domainnames/search',
		showOptions: true,
		web2_url: "domainnames/web20",
		category_url:'domainnames/getCategories'
	});
 
	$('.menu').hover(function() {
		$(this).animate({
			height: "40px"
		}, 1500), function(){
			$(this).animate({
				height: "24px"
			}, 1500);
		}	  
	});
});

The imDomainSearch plugin uses Cakes routing for the search_url, web20_url, and, and category_url options.

Search Method

The search_url option in the imDomainSearch plugin calls the search method in the domainnames controller:

class DomainnamesController extends AppController {
 
	var $helpers = array('Javascript', 'Html');
	var $components = array('RequestHandler', 'DomainSearch');
 
	function index() {
		$this->pageTitle = 'Web 2.0 Domain Names';
		$this->layout = 'default_web20_domains';
	}
 
	function search() {
		// tells Cake not render a view
		$this->autoRender = false;
		// set the debug level to 0
		if ( $this->RequestHandler->isAjax() ) {
		   Configure::write ( 'debug', 0 );
		}
		//call checkDomain method of DomainSearch Component
		return $this->DomainSearch->checkDomain();
	}

Note: For more information on autoRender and debug see my post: CakePHP and Ajax: Missing View.

Passing Parameters

I can also pass parameters to the method. There are multiple ways to do it.

Option 1

Change the search_url option in the imDomainSearch plugin. We will pass the variable ‘ajaxally‘.

?View Code JAVASCRIPT
search_url:'domainnames/search/ajaxally'

Now we can change the search method in the domainnames controller:

function search($dname) {
	// tells Cake not auto render the view
	$this->autoRender = false;
	// set the debug level to 0
	if ( $this->RequestHandler->isAjax() ) {
	   Configure::write ( 'debug', 0 );
	}
	//call checkDomain method of DomainSearch Component
	//$dname = ‘ajaxally’
	return $this->DomainSearch->checkDomain($dname);
}

Option 2

We could alternatively, use $_GET with a named parameter. First we change the search_url option.

?View Code JAVASCRIPT
search_url:'domainnames/search/?dname=ajaxally'

And then change the search method:

function search() {
	// tells Cake not render a view
	$this->autoRender = false;
	// set the debug level to 0
	if ( $this->RequestHandler->isAjax() ) {
	   Configure::write ( 'debug', 0 );
	}
	//call checkDomain method of DomainSearch Component
	//$dname = ‘ajaxally’
	return $this->DomainSearch->checkDomain($_GET[‘dname’]);
}

Well that’s it. As you can see integrating JQuery with CakePHP is not at all difficult. Enjoy.

Be Sociable, Share!

Checkout My New Site - T-shirts For Geeks