The flawless upgrade to Cake 1.3

Cake 1.3 has been around for quite some time now, but I never had the desire to upgrade with it being in such a beginning stage. Well seeing as how its now in Alpha and many users are testing it with no problems, I thought it would be a good idea. The project I was going to upgrade is quite large, heres a quick rundown of just how large:

19 controllers, 8 components, 15 locales, 64 models, 2 plugins, 6 vendors, 8 stylesheets, 14 javascripts, 7 helpers, 159 views

This isn't counting the admin panel, which is a whole separate app, and which I have not upgraded yet. Now lets get onto the upgrade, its probably the easiest thing to do. All I did was follow the migration guide. First off was checking to see if I used any deprecated methods, which was simple, all I did was search the whole app folder for words like del(. I was surprised to find I used it like 5 times, when I always preferred the full delete().

Next in the list was upgrading to the new Router conventions, which lucky for me didn't apply. I never used any non basic conventions, I mean why would you! One thing that bugged me though is the new page title implementation. It took me quite a while to go through all those controllers, and all the actions within them. Another nuisance was adding "echo" to all the flash() calls in the views, and removing the "inline" parameter from all meta() and css() calls, but wasn't too time consuming.

One of my most favorite updates was the new pagination support with passedArgs. I had to hack all my paging before, but in the new update I removed it all and it worked wonderfully! Thanks Cake team :]

All in all, the upgrade went smooth. If you follow Cake conventions all the way through, you don't need to do much alterations. I for one am looking forward to the future versions.

Why pure OOP, just for the sake of doing pure OOP

Lately all I have seen is the "Pure OOP is the way to go mentality" without much reasons to back up why its beneficial. I write OOP code, but I don't write overly verbose, bloated and cluttered OOP code either. I attend Zendcon, I have my PHP certification, I read PHP blogs on a daily basis, I have had multiple OOP discussions with other developers, but in the end I still ask the question, "Why do you spend so much time writing and separating your objects? When in the end its unnecessary as you are not extending them in the future anyways."

Before I begin, I want to do a quick review on how I got onto this topic. It started a few days ago when Brandon Savage posted his article Why Great Development Tools Don't Seem To Be Written In PHP, in which I agreed with him. Further into the comments, many users mentioned the PHP bug tracker Arbit Tracker. After downloading the source and browsing the code, I came to the following conclusion and posted this comment on Brandons entry:

After looking at Arbit... Why do people always need to use SO MANY files and classes to do such a basic task? Its unbelievable how bloated some projects can get. There is a thing with being to modular.

Just take a guess at how many files are required for a basic issue tracker... just guess. There are 2,077 files and 402 folders, and remember this is still an alpha version so that can grow even larger. Basically my first reaction was "Seriously? Do we really need all these files and classes to create a simple and basic bug/issue tracker". I have nothing against Arbit, nor the developers (They know there PHP for sure), but there is something terrible wrong about this in my opinion. This is a "3rd party script that is installable on a users machine", yet looks like a full blown framework and application. When I download a script to install on my machine, I want it to be lightweight, usable, easy and customizable. I find something really wrong about this when it takes this many classes to do such a basic task, and on top of that it requires multiple dependencies like EZ Components and CouchDB (and from what I could find, this wasn't even in the source! Now add more files into the final count). After my comment everyone seemed to post the same response: "Well of course, its a pure OOP project", and "This is what happens when you do it in true OOP", and "Nothing beats an OOP setup!".

I mentioned that a project does not need an abstract, an interface or even an exception for every class in its system, and I received this lovely little response.

If you want superior software then you use the standard and that (just) happens to be object oriented methodologies.

Drop object oriented methodologies and you drop way too many other natural benefits to software development; so enough of your bullsh*t okay?

I find this response laughable. Please tell me what those natural benefits are? To expand on classes if you want to customize it or create your own? To extend them even further? Dependency Injection? Multiple other reasons... You get my point. That's what abstract and interfaces are for. So why create them when YOU KNOW you will never extend them further, or even bother creating child classes. It seems everyone is in this mentality of "Ill do pure OOP just for the sake of doing OOP."

I can see when abstract and interfaces are required, like Zend Framework for example, but even then its overkill. Very rarely does anyone ever extend or use the abstract/interfaces in Zend. I've worked at many jobs and on many projects that utilized Zend, and have even worked with individuals that do the "Pure OOP" approach, and still I have not seen them extend objects like they are supposed to be, or use OOP to its fullest. I can only recall very few instances when people actually extended the objects, and it was primarily for Auth classes to customize to fit their application.

Another thing I dislike about pure OOP approaches is the amount of code you have to write to do such basic tasks. Take for example the routing components of Zend:

$this->getRouter()->addRoute('user', new Zend_Controller_Router_Route('user/:username', array('controller' => 'user', 'action' => 'info')));

I mean, whats so difficult about the following approach (below)? Why do you need to create a whole new object as an argument, when the object is just going to be a toArray() anyways and set as a property? Oh I know, its because you want to maybe use a Route_Regex class, or a Route_Hostname class. Now my question is, why would those even need to be their own class? Because they each do a different purpose and have their own methods that overwrite the abstracts? I guess that's where we disagree then. I honestly don't see a reason why these should be "split" up. The Router should manage all routes and package the class appropriately. Breaking up the classes isn't being "Pure OOP", its just being overly modular.

Say and think what you wish, but there's nothing wrong with the following piece of code either. But you'll probably find something wrong with static methods as well, seeing as how it doesn't add any OOP functionality.

Router::addRoute('user', 'user/:username', array('controller' => 'user', 'action' => 'info'));

I also have a problem with the amount of getters and setters I see everywhere. Have you not heard of __call, __get, __set, __isset, or __unset? But I digress, that topic is for another entry at another time.

I'll stop ranting now, its a matter of preference. Id also like to note that CakePHP (a non-pure OOP approach, but still OOP) has the same functionality and customization as Zend and Symfony (both pure OOP approaches). So why do you think Cake is inferior to the others? Personally, I think it has more beneficial and useful functionality.

Sorry for the lack of activity

Its been over a month since I posted an entry and even longer then that since it was a CakePHP entry. My goal was to post on average two entries a week, or at most 10 entries a month, but I have failed to do that so I am sorry. I mainly have been absent because of my new job I started on November 2nd, and it has been taking up most of my time and day. Furthermore, I haven't worked in CakePHP for months, seeing as how I have no new projects or features to add to my existing ones. I still haven't upgraded to 1.3!

However, I recently started on another CakePHP project and will hopefully have a few more topics to talk about. Lastly, you may have heard me mention on Twitter that I started building my own framework, which is 100% true. As of right now, the framework has a fully functional Controller and View system, but is missing a Model/database. For the Model aspect, I think I will be going down the Doctrine adapter route, and possibly building my own later on.

Here are just a couple of features currently implemented in the system: Routing, Environments, Controller containers (similar to Zend modules), Class dependencies (not really injection, you'll have to see an example), Registry (Factories and config injection), Lazy loading dependencies, Hooks and callbacks, Debugging and error logging, Exception handling, App global configuration, and has been built using a modular system. What does a modular system mean you ask? Well it basically means that you can use your own script or any 3rd party script in place of the default module. For example, you can use the frameworks view engine, or you can configure it to use a Twig or Smarty adapter engine very easily. The same goes for helpers, libraries, models (Doctrine adapter), extensions, etc. The only modules that can not be changed are the controller and core classes that are used to run the framework.

I'm pretty happy with my self and how this framework came along so far, and I will be showing some code snippets at a later time. Besides all that, I will try my best to start posting actively again!

The awesomeness of 5.3 Namespaces

If you haven't heard of Namespaces, or even PHP 5.3, you need to stop living under a rock. I've had quite a bit of fun the past month messing around with namespaces in 5.3, and I have got to say, they are the greatest addition to PHP yet. If you are unfamiliar with namespaces, it's a feature that allows you to add another layer of ownership and packaging to functions and classes, similar to how classes add a layer onto methods (ala functions).

In most applications and frameworks, you would see classes with very long names (I'm pointing the finger at you Zend!). This was implemented so that the classes would not conflict with internal and external (3rd party vendor) scripts. This is no longer the case, we can simply use namespaces! Lets take a look at some code we would write in 5.2 and lower.

class App_Utilities_Session { 
	public static function get($key) { }
	public static function set($key, $value) { }
}
// Basically, annoying!
App_Utilities_Session::set('User', array());

You can see how this would get really annoying and time consuming having to write the long class names over and over again through out your application. We can now rewrite the code above using namespaces. Do note, that the namespace declaration has to be at the very top of your code; although comments and the declare() function can be above it.

namespace App\Utilities;
class Session { 
	public static function get($key) { }
	public static function set($key, $value) { }
}
// Still kind of annoying
\App\Utilities\Session::set('User', array());

Now you may be thinking how this would make any difference, it's still a long class name to write... actually its even longer! Yeah well, namespaces also come bundled with aliases, if you don't feel like writing such long strings. Aliases allow you to declare alternative names for namespaces within the current scope (file). To apply an alias, you would write the "use" command with the Namespace path. You could either call the namespace by its base class name, or you can give it an alias. For example:

use App\Utilities\Session;
// Now that is much easier!
Session::get('user');
use App\Utilities\Session as S;
// Even easier!
S::get('user');

Even though namespaces are great and add extra functionality, there are a few things you should know about. Firstly, any class or function that isn't namespaced, or is within the global scope (SPL, Exception, etc), must be prepended with a backslash. If the backslash is not present, PHP will believe the class is within the current namespace and it fail.

$d = new \DirectoryIterator();
$e = new \Exception();

You would also need to prepend any global function. However, while developing I found that the backslash is not needed, unless you have a custom method with the same name of a function within the global scope.

class Debugger {
	public static function log() { }
}
// Use the global log function
$o = \log();

Another benefit of using namespaces is when you structure your application and file paths to mirror the namespace names. For example, if I use the Session namespace above, I may have a folder structure like so.

// App\Utilities\Session
/app/utilities/session.php

This comes in handy when you have a custom function to convert a namespace into a file path, and vice versa. Furthermore, the get_class() method will now return the classname with the full namespace declaration.

$class = get_class($session);
// App\Utilities\Session

There are loads of implementations of features related to namespaces, I have only named off a few of the important ones. If you have not used 5.3 yet, I highly recommend you do so. Either by upgrading your server or installing a local server; my localhost of choice is XAMPP (it comes with 5.3 by default!). I also highly suggest looking at the namespace guide for more information.

Fixing the missing Model and AppModel replacement errors

If you are a CakePHP developer, I am almost certain you have run into this problem on multiple occasions. What problem are you referring to you ask? Well, the problem that you have when your model is not being found and Cake automatically substitutes it with AppModel. Cake does this on purpose so that your relations and HABTM's do not need the junction Model to operate correctly. This works in most cases, but sometimes you get some weird errors or missing method problems. But before I continue with this, lets setup a quick scenario so I can better explain this problem. I will be using an example of relating users to teams.

User Model - users Table
Team Model - teams Table
TeamsUser Model - teams_users Table (Join)
User -> hasAndBelongsToMany -> Team
Team -> hasAndBelongsToMany -> User
TeamsUser -> belongsTo -> User, Team

In our code we are stating that a user can be on multiple teams, and a team can have multiple users. Are relation seems pretty simple, but lets not rely on Cake to magically figure everything out. In some cases we would receive the following errors:

  • Model "User" is not associated with model "Team"
  • Warning (512): SQL Error: 1064: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'myCustomMethod' at line 1 [CORE\cake\libs
    \model\datasources\dbo_source.php, line 514] Query: myCustomMethod

Now what do those errors mean? Well the first one states that our Models can not be related. So the first thing we need to do is check that our Models naming conventions are correct: model names are singular and camelcased, where as the filenames are singular, underscored and lowercased (without having _model in the filename). The second error means we are trying to call a method on a Model that does not have that method in its class. In other words, it basically means our Model is not being loaded and the AppModel is being loaded in its place. This happens when Cakes naming magic fails to load the correct Model or we have improperly followed conventions.

Most of these problems can be fixed by following the proper naming conventions. I'd also like to note that most of these errors appear during HABTM relations, and can easily be fixed with the following:

  • With any relation, its best to define the "className" parameter. By doing this, we are telling Cake the exact name of our Model, instead of having Cake rely on the relation name (which can easily be changed to custom text).
  • When defining conditions or containments, be sure to include the model name followed by the column name: Model.field
  • Important! When working with complex HABTM relations, define the "className, joinTable and with" parameters. If you have complex relations with crazy table names, its highly required you define the joinTable and with parameters.

During one of my projects, I had a Model that had a HABTM relationship, in which that HABTM had its own HABTM relationship, so it got quite complex. I ran into problems over and over again where Models would not be related and the AppModel was used instead. I later found out that the problem was the with parameter. Since I didn't define it manually, Cake could not figure out the correct HABTM Model to use, hence the whole application broke. Its pretty funny that my whole app didn't work for weeks, all based on this small declaration.

So, since we know how to fix this problem, lets define our relations:

class User extends AppModel {
	public $hasAndBelongsToMany = array('Team' => array(
		'className' => 'Team',
		'joinTable' => 'teams_users',
		'with' => 'TeamsUser',
		'foreignKey' => 'user_id',
		'associationForeignKey' => 'team_id'
	));
}

So in conclusion, follow the naming conventions and define the required parameters when creating relations, and I promise you, you won't have any problems.

To bake or not to bake...

By now most of you have heard that the awesome Nate Abele (which I had the privilege of talking to at Zendcon) is leaving the CakePHP team. A lot of developers were taken back by this and are unsure if they should continue to develop with CakePHP. Now, I find this ludicrous on many levels. Sure Nate was the lead developer, but that doesn't mean he was the only one. We still have the mighty Mark Story and the returning Larry Masters.

I had the opportunity to attend Nate's "Future of CakePHP" panel at Zendcon in which he talked about many of the problems facing current frameworks. Towards the end of the panel he showed off the new Cake 3 functionality using filters and closures, which I have to say, is pretty clever and badass. Now if you haven't figured out by now, the new Lithium project is a fork of the Cake 3 branch, so basically Lithium is a new 5.3 specific framework, which I am fully looking forward to fiddling with. Others have already figured this out, and we should expect it sometime this Monday, according to Nate.

Now where does this leave the future of CakePHP? It will stay the same. I know for once thing, ill continue to develop and pump out scripts because I see no reason in stopping. Additionally, if Lithium is anywhere near the same setup, I can easily port my current component, behaviors, etc to the Lithium architecture. I don't see CakePHP dieing anytime soon, simply because Lithium is an experimental 5.3 framework, and 5.3 wont take off as fast anytime soon. However it should be fun to mess with :]

I wish Nate Abele and the CakePHP team good luck with their new endeavors, I will thorougly be looking forward to both projects.

AJAX calls in CakePHP: The JSON Response

The controller and HTTP response are now working correctly, so it is time to display the response message to the client. We will achieve this by utilizing jQuery to output our JSON. The plan is to show a success message if the JSON passed or display a list of errors if it has failed. To display the messages we need to create our HTML elements that will hold the responses.

<div id="responseSuccess" class="responseBox" style="display: none"></div>
<ul id="responseError" class="responseBox" style="display: none"></ul>

Before we can write our Javascript to handle the JSON, we need to first inspect the JSON response. Our JSON "data" message can come in 3 possible formats: a simple string, an array containing the error messages, or an object containing the error messages / post data with their key values. Below are a couple examples of how our JSON response could be formatted:

// Single string error
{"success":false,"data":"No username/password","code":-1}
// An array containing the errors
{"success":false,"data":["No username","No password"],"code":-1}
// Errors / Post data and their key
{"success":false,"data":{"username":"No username","password":"No password"},"code":-1}
{"success":true,"data":{"username":"Miles","password":"p4ssw0rd"}}

Now this poses a significant problem. If our response data can be sent as 3 possible formats, we need to write our Javascript to be able to handle all possible variations. We can do this by creating a loop for the arrays/objects and store the values in a custom array, and for the single string just return the message. The following code block can do just that, and all we need to do is place it within the "success" parameter of our AJAX call.

function login() {
	var data = $("#UserAddForm").serialize();
	$.ajax({
		type: "post",
		url: "/ajax/login/",
		data: data,
		dataType: "json",
		success: function(response, status) {
			// Response was a success
			if (response.success) {
				$("#responseSuccess").html(response.data).slideDown();
			// Response contains errors
			} else {
				var errors = [];
				if (typeof(response.data) == ("object" || "array")) {
					$.each(response.data, function(key, value) {
						var text = isNaN(key) ? key + ": " + value : value;
						errors.push("<li>"+ text +"</li>");
					});
				} else {
					errors.push("<li>"+ response.data +"</li>");
				}
				errors = errors.join("\n");
				$("#responseError").html(errors).slideDown();
			}
		}
	});
	return false;
}

Pretty simple right? We can improve on this code by adding a setTimeout() that will remove the response box after 5 seconds. Additionally we can add the AJAX error argument that is called if the AJAX mechanism fails as a whole.

// Remove box after 5 seconds
setTimeout(function() {
	$(".responseBox").slideUp();
}, 5000);
error: function(XMLHttpRequest, textStatus, errorThrown) {
	$("#responseError").html("<li>An unexpected error has occurred.</li>").slideDown();
}

Our Javascript is now complete, but we could improve on it yet again. Say you have multiple AJAX calls that all utilize the same type of callback mechanism. It would be a major pain and waste of time to write all that code over and over again. What we can do is separate the code into 3 separate functions, all handling certain aspects of the logic. Our final code may look something like the following.

/**
 * Fire an AJAX call to login the user
 */
function login() {
	var data = $("#UserAddForm").serialize();
	$.ajax({
		type: "post",
		url: "/ajax/login/",
		data: data,
		dataType: "json",
		success: function(response, status) {
			handleCallback(response, status);
		},
		error: function(XMLHttpRequest, textStatus, errorThrown) {
			handleError(XMLHttpRequest, textStatus, errorThrown);
		}
	});
	return false;
}
/**
 * Handle the AJAX callbacks
 */
function handleCallback(response, status) {
	// Response was a success
	if (response.success) {
		$("#responseSuccess").html(response.data).slideDown();
	// Response contains errors
	} else {
		var errors = [];
		if (typeof(response.data) == ("object" || "array")) {
			$.each(response.data, function(key, value) {
				var text = isNaN(key) ? key + ": " + value : value;
				errors.push("<li>"+ text +"</li>");
			});
		} else {
			errors.push("<li>"+ response.data +"</li>");
		}
		errors = errors.join("\n");
		$("#responseError").html(errors).slideDown();
	}
	// Remove box after 5 seconds
	setTimeout(function() {
		$(".responseBox").slideUp();
	}, 5000);
	return false;
}
/**
 * Handle an AJAX failure
 */
function handleError(XMLHttpRequest, textStatus, errorThrown) {
	$("#responseError").html("<li>An unexpected error has occurred.</li>").slideDown();
}

Now there are multiple ways for your to handle a JSON response, but the approach above is a pretty straight forward implementation of displaying a success or failure message. Be sure that when you write your AJAX requests, that the $.ajax() function has a dataType of json, or your JSON response will completely fail.

AJAX calls in CakePHP: The Controller

Now that you have setup the Javascript and view to properly fire off an AJAX call, it's time to process the call within the Controller. The AJAX call was firing off to AjaxController::login(), so lets begin by creating the action. What we need to do is check to see if the username and password is set (validation), then attempt to login the user by using the AuthComponent. If the login is successful, or even if it fails, we will return a JSON response.

Below would be a basic setup to accomplish what we need to do. However, in your actual application you would apply more strict validation and sanitization, but for the sake of the tutorial I will not.

function login() {
	$this->layout = 'ajax'; // Or $this->RequestHandler->ajaxLayout, Only use for HTML
	$this->autoLayout = false;
	$this->autoRender = false;
	$response = array('success' => false);
	if (!empty($this->data['User']['username']) && !empty($this->data['User']['password'])) {
		if ($this->Auth->login($this->data)) {
			$response['success'] = true;
			$response['data'] = $this->data['User'];
		} else {
			$response['data'] = 'Username/password combo incorrect';
			$response['code'] = 0;
		}
	} else {
		$response['data'] = 'No username/password';
		$response['code'] = -1;
	}
	$this->header('Content-Type: application/json');
	echo json_encode($response);
	return;
}

As an added bonus, I will supply an example of how to achieve the same result above using my AjaxHandlerComponent. The component does all the necessary preparations and output leaving you to write less code.

function login() {
	if ($this->AjaxHandler->valid($this->data['username'], true) && $this->AjaxHandler->valid($this->data['password'], true)) {
		if ($this->Auth->login($this->data)) {
			$this->AjaxHandler->response(true, $this->data);
		} else {
			$this->AjaxHandler->response(false, 'Username/password combo incorrect', 0);
		}
	} else {
		$this->AjaxHandler->response(false, 'No username/password', -1);
	}
	$this->AjaxHandler->respond();
	return;
}

Basically what we need to do, to get a proper JSON response is to build the response array. We create an array with a success variable that would be a true or false. If the success is true that means the core logic that we want completed was a success, else the AJAX logic failed and the user should try again. We also have a data index that would house the error/success message(s), an array of data to use, or anything else you might need. Lastly we have a code index which could be used to differentiate the levels of errors and their importance. Once we have our response array complete, we set the correct headers and respond it back while encoding it with json_encode().

On top of building the response we need to configure the controller a bit. We need to disable the view and layout from rendering or we will receive the "Missing View" errors within Cake, and we also need to remove the layout so that our response is not surrounded by HTML (unless you want to respond with HTML, but we are using JSON). We do this by setting autoLayout and autoRender to false -- furthermore we set the layout to ajax which would be required for HTML responses.

You must be thinking to yourself, "Wow that was easy, we are now done!", but you are wrong! We still have one final step, validating that the request is a legitimate AJAX call. To achieve this we will use the RequestHandler::isAjax() method. Since all of our AJAX calls are housed in the AjaxController, we can place this code in the beforeFilter() so it applies to all actions. If your AJAX actions are within your primary controllers, you will need to add a bit more logic.

I will be using the SecurityComponent in my examples, but you can use die() or something similar in place of blackHole(), like Controller::redirect().

// Must be disabled or AJAX calls fail
$this->Security->validatePost = false;
if (!$this->RequestHandler->isAjax()) {
	$this->Security->blackHole($this, 'You are not authorized to process this request!');
}
// Use the following code in place of blackHole()
// $this->redirect(null, 401, true);

The previous code should blackhole any request that does not contain the XMLHttpRequest header. To further build on this code, we can check to make sure the AJAX request is coming from the current domain, if not then kill it. Our final beforeFilter() should look something like the following.

function beforeFilter() {
	parent::beforeFilter();
	// Must be disabled or AJAX calls fail
	$this->Security->validatePost = false;
	if (!$this->RequestHandler->isAjax()) {
		$this->Security->blackHole($this, 'You are not authorized to process this request!');
	} else {
		if (strpos(env('HTTP_REFERER'), trim(env('HTTP_HOST'), '/')) === false) {
			$this->Security->blackHole($this, 'Invalid referrer detected for this request!');
		}
	}
}

The controller code should now be complete and ready for your amazing AJAX use. We could however improve it a little more by utilizing the RequestHandlerComponent and some of its methods, but ill leave that up to you to adventure into. In the next chapter we will go over the response and how to interact with the JSON.

AJAX calls in CakePHP: The Front-end

One of topics I always see pop up in the CakePHP Google Groups is how to correctly do AJAX calls in CakePHP. I will be splitting this up into 3 different entries, the first will be pertaining to the view/Javascript (front-end) and how to fire off the AJAX call, the second will deal with the controller action and how to process the request, and the final entry will be dealing with the response (in JSON format).

Additionally I will be using jQuery for all my Javascript interactions. Some developers ask me if I have ever used CakePHP's built in Javascript helpers, and I always so no. I don't find the benefit in using the helpers when it causes extra parsing in the front-end by running it through PHP objects, when you can simply write out the function name manually within the HTML template, which takes no processing!

Now lets begin by creating your forms within the templates. I will be doing a user login system to demonstrate the AJAX calls. Take note that I am applying a "return false" on the form's onsubmit attribute. This will stop the form from posting when a user hits enter, so that they must use the AJAX trigger.

<?php echo $form->create('User', array('onsubmit' => 'return false;'));
echo $form->input('username');
echo $form->input('password');
echo $form->end(); ?>
<button type="button" onclick="login();">Login</button>

The form is pretty straight forward, so lets start out by creating our login() function within the Javascript. The login() function will be firing an AJAX call to AjaxController::login(). Furthermore, I will NOT be doing any form input validation in the AJAX, feel free to figure it out yourself!

function login() {
	var data = $("#UserAddForm").serialize();
	/* Or no serialization (Read #2 below)
	var username = $("#UserUsername").val();
	var password = $("#UserPassword").val();
	var data = "username="+ username +"&password="+ password;
	*/
	$.ajax({
		type: "post",		// Request method: post, get
		url: "/ajax/login/",	// URL to request
		data: data,		// Form variables
		dataType: "json",	// Expected response type
		success: function(response, status) {
			// Will continue in part 3
		},
		error: function(response, status) {
			alert('An unexpected error has occurred!');
		}
	});
	return false;
}

There are a few key points I would like to discuss first about the code above, before continuing with the tutorial.

1) AJAX functions

In my example I am using jQuery's built in ajax() function. However, you can use the alternative post() function, but as a personal preference I like to use ajax(). (I will also post an article about the difference between get/post and when to use each one).

2) Form input names

By default if you use jQuery's serialize() function, it will convert all inputs into name/value pairs and wrap them into a query string. This means it also includes the "data[Model][field]" setup when posting to your AjaxController, which in turn means you can access the data at $this->data['Model']['field'].

If you want to do it the old fashion way (or when its not possible to serialize()), you can create the query string yourself by grabbing the value of each input and building the name/value pairs (You can see this in the example below). However, if you do not include the "data[Model][]" around each of the named variables, you cannot access the data in the controller with $this->data, you would have to use the $this->params['form']['field']. Below is a quick example of the possible jQuery data values and how to access them in CakePHP.

var data = "data[Model][field]=foobar";
$field = $this->data['Model']['field']; // Equals foobar
var data = "data[field]=foobar";
$field = $this->data['field']; // Equals foobar
var data = "field=foobar";
$field = $this->params['form']['field']; // Equals foobar

If you go the path of not wrapping your fields in data[] and are using my AjaxHandlerComponent, the component will automatically process and parse the jQuery posted data into the controllers $this->data.

3) Response type (dataType)

One major feature of jQuery is the "dataType" variable within its AJAX calls. If you are responding with a JSON object with the HTTP header of application/json, be sure to set the dataType to json or your response will fail -- this goes the same for XML. If your responding with plain text or HTML you can omit the dataType variable.

Pro Tip: If you are responding with a JSON content type, jQuery will automatically decode the JSON object for you (and apply it to the response argument for success, error, etc), so that you do not have to use a 3rd party library.

Now that we have the form and Javascript written, lets test our AJAX call. If you have Firebug installed (which you should), open it beforehand to check the HTTP request and response. If everything worked correctly so far, you should see the following HTTP request and response headers (Do note, your headers will be similar, and not exactly the same!).

// Request Headers
POST /ajax/login/ HTTP/1.1
Host: localhost
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.3) Gecko/20090824 Firefox/3.5.3 (.NET CLR 3.5.30729)
Accept: application/json, text/javascript, */*
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
X-Requested-With: XMLHttpRequest
Content-Length: 73
// Response Headers
HTTP/1.x 200 OK
Server: nginx/0.8.15
Date: Thu, 01 Oct 2009 23:22:13 GMT
Content-Type: application/json
Transfer-Encoding: chunked
Connection: keep-alive
X-Powered-By: PHP/5.2.10
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
// Posted Variables
data[User][password] password
data[User][username] milesj

Basically what these headers are telling us is that our request was posted to /ajax/login/ and the server responded with an OK using the Content-Type of application/json. If you are unfamiliar with HTTP headers, I highly suggest you read the book "HTTP Developers Handbook, by Chris Shiflett.

That is all for now in this entry, stay tuned shortly for part 2 where I discuss the controller and action setup and how to properly respond to an AJAX call. Hope this helps you confused developers so far!

Code snippets now available

So over the years I have written many small code snippets, functions and what have you, and thought it would be a good idea to release them to you guys. I use most of these snippets on my own projects and applications and are great to be re-usable everywhere. Most, if not all the snippets, will deal with PHP and Javascript, however I have thrown in some CakePHP and jQuery ones.

View all 21 code snippets

Ajax Handler

On top of releasing my code snippets, I have recently made my AjaxHandler component available. The component can be placed in any CakePHP application and then applied to specific controller actions to handle them as Ajax requests. The handler does nearly everything automatic and even responds with the correct data structure and content type.

Check it out and let me know what you think!

Download the Ajax Handler