Jump to content

Using the atkFrontController: Difference between revisions

From NusaATK
Peter (talk | contribs)
No edit summary
 
Peter (talk | contribs)
Line 69: Line 69:


= Spicing things up =
= Spicing things up =
To be continued...
Until now we've only seen the tip of the iceberg. The real power of the atkFrontController relies in the way you can link actions together, use Ajax etc. So let's look at a more complex version of our ''HelloController''.
 
  class HelloController extends atkFrontController
  {
    public function indexAction()
    {
      $this->name = $this->request['name'];
    }
   
    public function resultAction()
    {
      $this->name = $this->request['name'];
      $this->renderPartial('result');
    }
  }
 
Still doesn't look that complicated, does it? The ''result'' action needs some explanation though. As you can see the last call inside this action is a call to the method ''renderPartial''. As we've seen before if you simply assign some template variables in your action method ATK automatically renders a template with the same name as your action. If you want to (re-)use another template you can call the ''render'' method inside your action method and specify a different template. However, you can also choose to call the ''renderPartial'' or ''renderContent'' method. If you call the ''renderPartial'' method you need to supply a name for the partial template you want to render. A partial template is a template that is prefixed by an underscore (''"_"''). If you call ''renderPartial'' the partial template will be rendered instead of the normal action template and the results will be immediately outputted to the browser. So this means the layout will not be rendered. This makes the ''renderPartial'' really useful for Ajax requests where you need to update only a small part of a page and don't want an entire page to be returned. For even more simple Ajax requests where you only need to return a simple string for example you can use the ''renderContent'' method. You need to supply this method with a string you want to output to the browser. Just like with the ''renderPartial'' method the ''renderContent'' method outputs it's content immediately and terminates the script (without rendering the layout first).
 
Now that we've created our controller and actions, let's create the template for the ''index'' action, named ''index.tpl'':
 
  <form onsubmit="new Ajax.Updater('result', '{_url action="result"}'); return false;">
    <input type="text" name="name" value="{$name|escape}" />
    <input type="submit" value="Say hello!" />
  </form>
 
  {_partial "result"}
 
Inside the ''index'' action template we use some new tags. The ''{_url}'' tag renders a string containing an URL to a certain controller action. If you don't specify the ''controller'' parameter it assumes you want to use the current controller. So in the example above we render the URL to the ''result'' action of the ''hello'' controller. The ''{_partial}'' tag can be used to include partials in your template. The partial template has all template variables available of the action template but you can choose to override template variables by specifying them as parameters for the ''{_partial}'' tag.
 
The ''partial'' result template needs to be named ''_result.tpl'' and needs to have the following contents:
 
  <nowiki><div id="result"></nowiki>
    {if $name}Hello {$name}!{/if}
  <nowiki></div></nowiki>
 
This template is both used from within the ''result'' action (by calling ''renderPartial'') and the ''index'' action's template (by using the ''{_partial}'' tag). As you can see we check inside this template if the ''name'' variable is set and has a non-empty value, if so we render the string ''"Hello {$name}!"''.
 
So now we've looked at the code, what are we trying to accomplish? '''TO BE CONTINUED....'''

Revision as of 09:33, 31 July 2007

ATK Howto: Using the atkFrontController

Complexity: Intermediate
Author: Peter C. Verhage <peter@achievo.org>

List of other Howto's

Preface

The atkFrontController can be used to implement the MVC pattern in your web application. It's part of ATK and can be used stand-alone for ATK applications but can also be easily integrated in WDE using the atkFrontController plug-in. If you use a recent version of ATK or WDE the atkFrontController is out-of-the-box available without any special installation or configuration needed. The atkFrontController has been heavily inspired by Ruby on Rails.

This how-to will give a short introduction on usage of the atkFrontController in stand-alone mode. It will soon be extended to add information about usage in WDE, usage of Ajax and some new features that will be coming soon.

Basic usage

First you need to checkout ATK or download the latest ATK nightly in a directory that's browseable by your webserver. Copy atk.inc and the example config.inc.php from the atk/skel directory to the root directory of your application. Create a directory atktmp and make it writeable to your webserver. Create a file named index.php with the following contents:

 <?php
 $config_atkroot = "./";
 require_once($config_atkroot."atk.inc");
 atkimport('atk.front.atkfrontcontroller');
 $request = $_REQUEST;  
 $output = atkinstance('atk.ui.atkoutput');  
 $content = atkFrontController::dispatchRequest($request);
 $output->output($content);
 $output->outputFlush();

Create a directory modules and inside this directory create a directory called example, this will be the ATK module we will be working from. Inside the module directory you need to create a directory called controllers. Inside this directory you can place your controller files. A controller file should be named class.<name>controller.inc where <name> can be replaced by your custom name. Inside the controller file you should create a class which follows the same naming scheme and extends the atkFrontController class. E.g.

 class HelloController extends atkFrontController
 {
 }

The example controller above should be placed in a file named class.hellocontroller.inc.

After you've created the controller class you can start adding actions. An action is a method that uses the following naming scheme <name>Action and is declared public. Inside an action you can assign template variables as if they were instance variables of your controller you can also choose to use your controller as if it were an array and assign template variables that way. E.g.

 class HelloController extends atkFrontController
 {
   public function helloAction()
   {
     // assign a template variable (method 1)
     $this->title = "Hello!";
     
     // assign another template variable (method 2)
     $this['name] = $this->request->name;
   }
 }

In the example above you can also see that request variables can be accessed by the /$this->request/ object. In the same manner you can store/retrieve information to/from the session using the /$this->session/ object.

Now that we've assigned some template variables let's look at how we can access them in our template. First we need to create a template for our action. Templates are stored in the templates directory of the controller's module. They are stored using the naming scheme <module>/<controller>/<action>.tpl. So this means that for our hello action we need to create a template called hello.tpl in the directory templates/example/hello of our module. Our template might look like the following:

 <h1>{$title}</h1>
 Hello {$name}!

As you can see you can simply use the template variables by name. You can also choose to store your template in a templates directory in the root of your ATK application or in the skel/templates directory inside your module directory. ATK will first try to find the template in the application root templates directory, then in your module's templates directory and finally in the module's skel/templates directory

Because we are using the atkFrontController in stand-alone mode we should also create a layout. The layout is given the result of the action and all of the action template variables. The result of the action is made available through the special template variable /$content_for_layout/. Our layout file might look like the following:

 <html>
 <head>
 <title>{if $title}{$title}{else}Hello{/if}</title>
 </head>
 <body>
   {$content_for_layout}
 </body>
 </html>

A layout is first searched for in the application root's layouts directory, then in the module's layouts directory and finally in the module's skel/layouts directory using a naming scheme of <module>/<controller>.tpl. If no layout is found the exact same directories are searched for a template using the naming scheme <module>/root.tpl. Finally if still no layout template has been found the exact same directories are searched for a template called root.tpl.

Now that we've created our controller with custom action let's browse to it to check if everything works as expected. You should browse to the earlier created index.php and add a parameter uri with the value <module>/<controller>/<action> and another parameter name with your name, so for example http://localhost/?uri=example/hello/hello/&name=Peter.

If everything works as expected you will end up with a page that says Hello Peter! (although it might say something different if your name isn't Peter...).

Spicing things up

Until now we've only seen the tip of the iceberg. The real power of the atkFrontController relies in the way you can link actions together, use Ajax etc. So let's look at a more complex version of our HelloController.

 class HelloController extends atkFrontController
 {
   public function indexAction()
   {
     $this->name = $this->request['name'];
   }
   
   public function resultAction()
   {
     $this->name = $this->request['name'];
     $this->renderPartial('result');
   }
 }

Still doesn't look that complicated, does it? The result action needs some explanation though. As you can see the last call inside this action is a call to the method renderPartial. As we've seen before if you simply assign some template variables in your action method ATK automatically renders a template with the same name as your action. If you want to (re-)use another template you can call the render method inside your action method and specify a different template. However, you can also choose to call the renderPartial or renderContent method. If you call the renderPartial method you need to supply a name for the partial template you want to render. A partial template is a template that is prefixed by an underscore ("_"). If you call renderPartial the partial template will be rendered instead of the normal action template and the results will be immediately outputted to the browser. So this means the layout will not be rendered. This makes the renderPartial really useful for Ajax requests where you need to update only a small part of a page and don't want an entire page to be returned. For even more simple Ajax requests where you only need to return a simple string for example you can use the renderContent method. You need to supply this method with a string you want to output to the browser. Just like with the renderPartial method the renderContent method outputs it's content immediately and terminates the script (without rendering the layout first).

Now that we've created our controller and actions, let's create the template for the index action, named index.tpl:

 <form onsubmit="new Ajax.Updater('result', '{_url action="result"}'); return false;">
   <input type="text" name="name" value="{$name|escape}" />
   <input type="submit" value="Say hello!" />
 </form>
  
 {_partial "result"}

Inside the index action template we use some new tags. The {_url} tag renders a string containing an URL to a certain controller action. If you don't specify the controller parameter it assumes you want to use the current controller. So in the example above we render the URL to the result action of the hello controller. The {_partial} tag can be used to include partials in your template. The partial template has all template variables available of the action template but you can choose to override template variables by specifying them as parameters for the {_partial} tag.

The partial result template needs to be named _result.tpl and needs to have the following contents:

 <div id="result">
   {if $name}Hello {$name}!{/if}
 </div>

This template is both used from within the result action (by calling renderPartial) and the index action's template (by using the {_partial} tag). As you can see we check inside this template if the name variable is set and has a non-empty value, if so we render the string "Hello {$name}!".

So now we've looked at the code, what are we trying to accomplish? TO BE CONTINUED....