Showing posts with label #opensource. Show all posts
Showing posts with label #opensource. Show all posts

Friday, October 16, 2009

AJAX in cakePhp, #cakephp, #php,

AJAX CakePHP
Using AJAX with CakePHP tutorial

CakePHP is a wonderful framework. Unfortunately, like a lot of software, documentation is severly lacking. The effort is definitely there, but with an API containing the occassional "Enter description here... unknown_type", it definitely makes things a bit more difficult. Especially for someone who adopted the RTFM mantra many years ago.

For this article, we're going to try and figure out how to get AJAX and cake to work together without having to comb cake's manual, wiki, the bakery, users' sites and tutorials and Google groups.

First things first - you'll need to have cake installed and running.

Next things second - you'll need to get the scriptaculous and prototype libraries. (I haven't tried any other AJAX libraries, but these seem to work just fine for now).

Note: there was an issue where the code crashed firefox that turned out to be caused by the prototype.js that's included in scriptaculous being the incorrect version. Therefore, I recommend downloading them separately.

You'll need to place the scriptaculous and prototype files in /app/webroot/js directory.

Now you need to add the following inside the tag of your layout file (/app/views/layout/default.thtml) to make them available:

print $html->charsetTag('UTF-8');
print $javascript->link('prototype');
print $javascript->link('scriptaculous.js?load=effects');
?>

At this point, you have 2 options - to use the RequestHandler component or not. If you're doing fancier AJAX things, you can check CakePHP's manual on RequestHandler, but to keep things simple, we won't use it.

In your controller's action, you want to add:

// controller file
var $helpers = array('Html', 'Javascript', 'Ajax');

function view() {
$this->render('layout file', 'ajax');
}

First we want to make sure we're using cake's built-in helpers, including the AJAX helper. In your action, you'll change the render action to include the ajax option, which tells cake to crunch the information and send the data somewhere rather than displaying a new page. We'll see where in a second.

What you want to do next is create a link, but not just any link. You want to enable an ajax link, and to do that you use the ajax helper that comes with cake.

// view file
echo $ajax->link('link text', '/controller/action',
array('update' => 'div id')
);

This will automatically generate a link with the appropriate attributes to output the ajax into the div you specify. Note: don't forget the forward slash - cake needs to be able to find your controller, otherwise nothing will appear to happen (no errors will be shown either).
Styling it

If you want to add a css class to the link, add the undocumented 'class' option as part of the options array.

// view file
echo $ajax->link('link text', '/controller/action',
array('update' => 'div id', 'class' => 'aclass'));

What about images?
To include an image to be linked rather than text, you simply include the html for the image in place of the first parameter, but be sure to add FALSE so the code doesn't get escaped.

echo $ajax->link('',
'/controller/action/',
array('update' => 'div id'),
null,
FALSE
);

Multiple divs
That's all fine and dandy, but what if you wanted to update more than one div at a time? To do that, you'll need to add an array of divs to update, and also use the $ajax helper to create the divs.

echo $ajax->link('link text', 'controller/action',
array('update' => array('div1', 'div2'))
);

// create the div code rather than hard-coding

echo $ajax->div('div1');
echo $ajax->divEnd('div1');

echo $ajax->div('div2');
echo $ajax->divEnd('div2');

So it updates. How do I make it look cool?
To add effects, you'll need to add the effect to the link:

$ajax->link('link text', 'controller/action',
array('update' => 'div id',
'loaded' => 'scriptaculous effect')
);

You can use loaded/loading or any of the other available options listed in the manual under helpers.
A complete example
We'll create a simple example here to demonstrate.

/**
* $Id: approot/controllers/things_controller.php
*/

class ThingsController extends AppController
{
var $name = 'Things';
var $helpers = array('Html', 'Javascript', 'Ajax');

// we're not going to use a model for this example, but
// it would be easy to use a database thanks to cake
var $uses = null;

/**
* initial page load
*/
function index() {

// preload dynamic data
$this->set('data1', 'content will update here');
$this->set('data2', 'here too');

$this->render('neat');

}//index()

/**
* display content action
*
* @param int id of content to display
*/
function view($id) {

// content could come from a database, xml, etc.
$content = array(
array('somebody is baking brownies',
'become a cake baker',),
array('knowledge is not enough',
'we must also apply - bruce lee')
);

$this->set('data1', $content[$id][0]);
$this->set('data2', $content[$id][1]);

// use ajax layout
$this->render('neat', 'ajax');

}//view()

}//ThingsController
?>




print $html->charsetTag('UTF-8');
print $javascript->link('prototype');
print $javascript->link('scriptaculous.js?load=effects');
?>





Really neat stuff here


// update both divs
echo $ajax->link('update divs', '/things/view/0',
array('update' => array('dynamic1', 'dynamic2'))
);
echo ' | ';
// use an effect
echo $ajax->link('blinders', '/things/view/1',
array('update' => array('dynamic1', 'dynamic2'),
'loading' => 'Effect.BlindDown(\'dynamic1\')')
);
?>



div('dynamic1'); ?>


divEnd('dynamic1'); ?>

div('dynamic2'); ?>


divEnd('dynamic2'); ?>

Thursday, August 27, 2009

Data Validation in #cakePhp, #open Source, #php

Cake goes a long way in taking the monotony out of form input validation. Everyone hates coding up endless forms and their validation routines. CakePHP makes it easier and faster.

To take advantage of the validation features, you'll need to use Cake's FormHelper in your views. The FormHelper is available by default to all views at $form.

Here's our add view:

Plain Text View
create('Post');echo $form->input('title');echo $form->input('body', array('rows' => '3'));echo $form->end('Save Post');?>
Here, we use the FormHelper to generate the opening tag for an HTML form. Here's the HTML that $form->create() generates:

Plain Text View

If create() is called with no parameters supplied, it assumes you are building a form that submits to the current controller's add() action (or edit() action when id is included in the form data), via POST.

The $form->input() method is used to create form elements of the same name. The first parameter tells CakePHP which field they correspond to, and the second parameter allows you to specify a wide array of options - in this case, the number of rows for the textarea. There's a bit of introspection and automagic here: input() will output different form elements based on the model field specified.

The $form->end() call generates a submit button and ends the form. If a string is supplied as the first parameter to end(), the FormHelper outputs a submit button named accordingly along with the closing form tag. Again, refer to Chapter "Built-in Helpers" for more on helpers.

Now let's go back and update our /app/views/posts/index.ctp view to include a new "Add Post" link. Before the , add the following line:

Plain Text View
link('Add Post',array('controller' => 'posts', 'action' => 'add'))?>
You may be wondering: how do I tell CakePHP about my validation requirements? Validation rules are defined in the model. Let's look back at our Post model and make a few adjustments:

Plain Text View
array( 'rule' => 'notEmpty' ), 'body' => array( 'rule' => 'notEmpty' ) );}?>
The $validate array tells CakePHP how to validate your data when the save() method is called. Here, I've specified that both the body and title fields must not be empty. CakePHP's validation engine is strong, with a number of pre-built rules (credit card numbers, email addresses, etc.) and flexibility for adding your own validation rules. For more information on that setup, check the Data Validation chapter.

Now that you have your validation rules in place, use the app to try to add a post with an empty title or body to see how it works. Since we've used the input() method of the FormHelper to create our form elements, our validation error messages will be shown automatically.