Browsing articles in "Cookbook"
Nov 27, 2010
admin

Building an Iphone Application with SimpleMVC in a few hours

Hello! Welcome to Simple MVC! In this  book, We will build an iphone web application using Simple MVC and jQuery mobile. The purpose of this application is  to allow users to add and view RSS feeds. A demo of the application is available at : http://jquerymobile.demo.simplemvc.berejeb.com. The code is Directly bundled with the Simple MVC GitHub Repository as a default application. So You just have to grab the code from GitHub.

Even if you see a bunch of steps in this cookbook, this will not take a lot from your time. We just split each functionnality in a separate page.

Here are the steps that we will follow :

So lets start with the Installation!

Nov 27, 2010
admin

The add page

We need a form to implement the add page. To get that done, we will make use of the Simple MVC forms. Let’s start as always, by the controller add action :

    /**
     * add Action
     *
     */
    public function addAction()
    {
        $this->model->bind($this->Request);
        $this->model->checkin();
        $this->view->form = new FeedForm('Feed');
        $this->view->form->initFromModel($this->model);
        // Handle eventual errors
        if (isset($this->Request['errors']) && is_array($this->Request['errors']))
        {
            $this->view->form->setErrors($this->Request['errors']);
        }
    }

The add action will use a FeedForm that we will create later. we can directly init the form the model using the initFromModel method. This will create text fields directly from the model properties, and take care of not displaying the ids.
Since the add method will also handle the errors if the informations are not filled for example, we need to add a test on the errors request variable and set those one to the view.
We will create a new form under business/front/forms/FeedForm.php :

class FeedForm extends Form
{
}

That’s all what we need to set for the form. It will work because the initFromModel will create dynamically the form elements. However, we can create independent forms with fields that are not binded to the model form. We will cover that later in a separate tutorial concerning Forms.
Lets code the view part now, under the folder : business/front/views/Feed/add.php add the following code.

<?php
echo $this->languages['add_feed']?&gt;&lt;/h3&gt;&lt;?php
echo $this->form->render();
?>

That’s all we need to do in the view, the render method of the view will handle all the magic. again, we can customize the form rendering using decoractors. This will be also covered in the Form section later.

The add page lacks only one thing. The part that will verify and save the feed. To implement this, we need to code the saveAction :

 
    public function saveAction()
    {
        $this->model->bind($this->Request);
        $form = new FeedForm('Feed');
        $form->initFromModel($this->model);
        if ($form->validate())
        {
            if ($this->model->save())
            {
                $this->Router->redirect('index', 'Feed', $this->language['redirect']['element_saved'], CoreView::MESSAGE_TYPE_SUCCESS);
            }
            else
            {
                $this->Router->redirect('index', 'Feed', $this->language['redirect']['element_not_saved'], CoreView::MESSAGE_TYPE_ERROR);
            }
        }
        else
        {
            $params = array_merge(array('id' => $this->model->id, 'errors' => $form->getErrors()));
            $this->Router->redirect('add', 'Feed', $this->language['redirect']['element_not_saved'], CoreView::MESSAGE_TYPE_ERROR, $params);
        }
    }

The save action will first bind the contents of the model from the Request. this method basically fills the instance properties from the Request. After, we instanciate a new FeedForm and we initialise it from the model. To validate the form, we simply call the $form->validate() method. The framework will verify that all the validators are satisfied. By default, Simple MVC adds a default validators to all properties which is a NotEmpty validator. This is what makes you have required fields.
If the form is validated and the model is saved, we redirect to the index action with a success message, otherwise, we redirect to the add page with the errors we got from the $form->getErrors() method.
That’s all! You can try your form now.

These few steps show how to do stuff with Simple MVC. Of course the stuff we explored here is basic. For more details, you can see the API Documentation or the other specialised tutorials. We are continually updating those section to expose what can be done with the framework.

Nov 27, 2010
admin

The detail page

To implement the detail page, we will basically redo what we have done for the index page. One thing we will not redo it, however, is the template section. This will work for all the views.
So, let’s start with the controller and add the detail action.

    /**
     * Detail action
     *
     */
    public function detailAction()
    {
        if (!isset($this->Request['id']) || !is_numeric($this->Request['id']))
        {
            $this->Router->redirect('index');
        }
        $this->model->id = $this->Request['id'];
        $this->model->checkin();
        if (!isset($this->model->id) || empty($this->model->id))
        {
            $this->Router->redirect('index');
        }
        $this->view->feed = new stdClass();
        $this->view->feed->name  = $this->model->name;
        // get the rss feeds
        $this->getFeedInfos($this->view->feed, $this->model->url, $this->model->itemsNumber);
    }

The detail Action is supposed to get a feed id from the request, sot before getting the feeds, we verify if everything is okay with that parameter, and we also check if there is a
model corresponding to that id. This is done by affecting the id to the model and by calling the checkin method. This method will fill the object properties with the relative field if the id exists in the database. If the record is not found, the model properties remain empty and the id property we previously affected will be cleared also. That’s why we are checking on the id after the checkin call.
If the id does not exist, using the Router object, we can redirect the user using the redirect method. If the record exists, we will get the feed from the private method getFeedInfos to which we give three parameters: $this->view->feed: this will be where the feeds are stored. the url from the model, and the items number we want to retreive.

So let’s code that method :

    /**
     * Returns a list of elements from an rss Feed
     *
     * @param  mixed  $url
     * @param  int    $itemsNumber
     * @return array the rss items
     */
    private function getFeedInfos($feed, $url, $itemsNumber)
    {
        $rss = $this->getRSS($url, $itemsNumber);
        $feed->title = $rss->channel->title;
        $feed->description = $rss->channel->description;
        $feed->link = $rss->channel->link;
        $feed->lastUpdated = $rss->channel->lastBuildDate;
        $feed->image = $rss->channel->image;
        $feed->items = array();
        $i = 0;
        foreach ($rss->channel->item as $item)
        {
            if ($i == $itemsNumber) break;
            $feed->items[] = $item;
            $i++;
        }
    }
 
    /**
     * gets a feed
     *
     * @param  mixed  $url
     * @param  int    $itemsNumber Optional, defaults to 5.
     * @return SimpleXMLElement the element
     */
    private function getRSS($url, $itemsNumber = 5)
    {
        $feedKey = 'simplemvc_cache_feeds_list_' . $url;
        if (!$this->CacheManager->exists($feedKey))
        {
            $client = new CurlClient();
            $client->setUrl($url);
            $client->setReturnTransfer(true);
            $client->setAsGet();
            $feedRaw = $client->call();
            $this->CacheManager->set($feedKey, $feedRaw, $this->Config['general']['rss']['ttl']);
            $feeds = simplexml_load_string($feedRaw);
        }
        else
        {
            $feeds = simplexml_load_string($this->CacheManager->get($feedKey));
        }
        return $feeds;
    }

Okay, time to explain what we did. The getFeedInfo method will get the information from the getRSS method and fill only the information we need in the view from the result. nothing more to say for that method. However, it is in the getRSS method where things are done.
This method uses a cache mechanism. to implement that, we need to define a unique cache key : $feedKey. To check if there is the rss has been already checked before we use the exists method of the CacheManager. if it is the case, we use the get method to get the content.
If this is the first time we ask for this RSS, we will do a curl call to get the contents and store them in the cache by the occasion. We make use of the CurlClient class to get the contents. setURl, setReturnTransfer, setAsGet and call are self explanatory. Next, the CacheManager->set method stores the entry in the cache, and we affect a SimpleXMLElement to the $feeds variable.
We will do some refactoring later on to get out the CurlClient instanciation from the controller. if We want a unit testable code, we should not have instanciations directly in the controller. The CurlClient will be moved to the Container. we will cover that later.
This is all we need to do for the controller, Let’s code the view part. open a new file business/front/views/Feed/detail.php and add the following:

<div class="ui-grid-a">
    <?php if (!empty($this->feed->image->url)) { ?>
    <div class="ui-block-a">
        <a href="<?php echo $this->feed->link?>">
            <img src="<?php echo $this->feed->image->url?>" alt="<?php echo $this->feed->image->title?>" title="<?php echo $this->feed->image->title?>"/>
        </a>
    </div>
    <?php } ?>
    <div class="ui-block-b">
    <h3>
        <a href="<?php echo $this->feed->link?>">
            <?php echo $this->feed->title?>
        </a><br/>
        <?php echo $this->languages['last_updated'] . ' : ' . $this->feed->lastUpdated?>
    </h3>
    </div>
</div>
<div data-role="collapsible">
    <h3><?php echo $this->languages['you_are_reading_feed'] . ' : ' . $this->feed->name ?></h3>
    <?php
    if (!count($this->feed->items))
    {
        ?><div class="feed_element"><?php echo $this->languages['no_feed_entries']?></div><?php
    }
    else
    {
        foreach ($this->feed->items as $item)
        {
            ?>
                <div class="feed_element">
                <h4><a href="<?php echo $item->link?>"><?php echo $item->title?></a></h4>
                <p><?php echo $item->description ?></p>
                </div>
                <?php
        }
    }
    ?>
</div>

This follows same rules, looping through items to display the items information, using the language variables when needed. We already added the languages for the feed.detail page in the business/front/conf/languages.en.ini file.
Finished : Let’s test the page!, click on a feed and you should see the details with a nice sliding effect.
Let’s move forward to add an action that adds a feed.

Nov 27, 2010
admin

Verifying the index page

At this step, all is done to get the index action showing the list. Make sure you pointed your virtual host to the www directory. the conf directory contains a virtual host sample that allows you to do that. Here is the steps to do that :

$ sudo cp conf/virtual-host-sample.conf /etc/apache2/sites-enabed/simplemvc.conf
$sudo vi /etc/apache2/sites-enabed/simplemvc.conf
// put your ServerName and the path to the DocumentRoot and Directory
<VirtualHost *:80>
ServerName www.simplemvc.dev
DocumentRoot /var/www/simpleMVC/www
<Directory /var/www/simpleMVC/www>
AllowOverride All
Order allow,deny
allow from all
</Directory>
</VirtualHost>
// save the file and exit.
$ sudo vi /etc/hosts
// add the following line to your hosts file
127.0.0.1 www.simplemvc.dev
// save the file and exit
Type now http://www.simplemvc.dev/?controller=Feed&action=index you should see a page like : http://jquerymobile.demo.simplemvc.berejeb.com!

Pretty cool no?
A question that I see coming is : why should I add /?controller=Feed&action=index if This is my first page? You are absolutely right. This can be solved either by a rewrite rule, or by 2 lines added in the bootstrap file. Let’s add them right now. Open the www/index.php file and add the following as the first lines in your try block :

$_REQUEST['controller'] = Toolbox::getArrayParameter($_REQUEST, 'controller', 'Feed');
$_REQUEST['action'] = Toolbox::getArrayParameter($_REQUEST, 'action', 'index');

This should add a default action and controller names if nothing is provided from the request.
You can see the rendering on the iphone, it is really good.
This is all for the indexAction. When clicking on the feed title, we are redirected to the detail page, which we will start implementing right now!

Nov 27, 2010
admin

The business configuration files

In Simple MVC, the business configuration files are splitted as follow :

.
|-- business
      |-- conf
      |   `-- apps.ini.changeme
      `-- front
          |-- conf
          |   |-- access.ini
          |   |-- front.ini.changeme
          |   |-- languages.en.ini
          |   `-- user_rights.ini

the business/conf folder contains a file named apps.ini.changeme. This file specifies common configuration for the business layer, it should be renamed to apps.ini and customized. Here is its content :

[database]
host = localhost;
user = *****;
password = *****;
database = *****;
type = mysql;
 
[template]
URL = http://simplemvc.berejeb.com/;
 
[controller]
 
[model]
 
[view]
autorender_template = 1;
 
[cache]
;allowed types : Array, File, APC
type = File;
prefix = simplemvc;
directory = /tmp;

So as you notice, the file contains global sections like database, which handles the database connection params, template, controller, model and view sections, and cache section. Those can be a global placeholder for your common configurations across your applications.

You can then override those sections per application. For each Application you write, you must add a .ini file under business//conf/. So in our case, business/front/conf/front.ini. by default you have a front.ini.changeme for the module front. I’ve already put the configuration by default in this file :

[general]
application.session.checkFrequency = "300000";
images.destination_dir = "/the/path/to/your/images/uploads/";
images.destination_url = "/images/uploads/";
rss.ttl = 10000;

You have to copy that file under front.ini and from there, you can override the global conf file. for example, if you have two applications that are dealing with different database connections, you can overrite the database section to sepecify the connection params for each application.

Also, remember in the boostrap file, we had some lines of code that were dealing with access. The helper was actually looking for the acces.ini configuration file ccess.ini :
This file indicates if each action should be public or protected.

; Access Config file : 
; 0 - public
; 1 - protected
Feed.index = 0;
Feed.detail = 0;
Feed.add = 1;

This is basically what we need to get the config working.
Move on to the next section, let’s take a look at our first page!

Nov 27, 2010
admin

A first view

The Simple MVC views follow the two-step view pattern. This allows you to specify a global container page in which you can specify your head page, your foot page and may be some lateral columns. In the main part of your page, you will display each time the contents of your specific action (index, detail, add etc.).
The views also deal with JavaScript and CSS libraries. In Simple MVC, the view is also a class which is placed under business/{your-module-application}/views/ . Since the view has to deal with templates and partial views, we have some other files to store the template folder and the view folder. We call a template the global container page, and view the partial specific view.
Since the templates will be used by many views, they are pretty independent, so they are placed under business/{your-module-application}/templates.
Here is a structure of the files we should have at the end:

$ tree business/front/views/
views
|-- Feed
|   |-- add.php
|   |-- detail.php
|   `-- index.php
|-- FeedView.php
|-- Main
|   |-- footer.php
|   `-- header.php
`-- MainView.php
$ tree business/front/templates/
templates
`-- default.php

The views folder contains Two sections: Feed and Main, each one is composed by a View.php file and a folder. Actually, the Feed.php file will handle the view class itself, whereas the folder wil contain the html related to each action.
The Main section is a common section which is extended by the other views. this allows reusing common calls, script calls, css calls, common html code etc.
You will understand better with an example. So let’s write our index view:
First, we will create our FeedView and MainViews classes under views (placed under business/front/views/FeedView.php and business/front/views/FeedView.php)

/**
 * Feed Front View
 */
class FeedView extends MainView
{
}
class MainView extends CoreView
{
    /**
     * index Action
     *
     */
    public function alwaysAction()
    {
        $this->addJs('/scripts/jquery-1.4.4.min.js');
        $this->enableJQueryMobile();
    }
 
    /**
     * Adds the js and css for the jqueryMobile Framework
     *
     */
    private function enableJQueryMobile()
    {
        $this->addCss('/scripts/jquery.mobile-1.0a2/jquery.mobile-1.0a2.min.css');
        $this->addJs('/scripts/jquery.mobile-1.0a2/jquery.mobile-1.0a2.min.js');
    }
}

Since all the code we need to have is a common code untill now, we wrote it in the MainView. Basically, we just need to include our Javascript and CSS needed. In this case, and since we are using jQueryMobile as a framework for our iphone application, all we need to do is to include the javascriot for the jQuery Framework, and the Javascript and CSS for jQueryMobile.
For purpose of simplicity, the jQuery Mobile is directly bundled in the default www folder of Simple MVC. You can change the scripts and styles if a new version has been released.

Next step is to write our first template. Usually, we need to do this once for every module, unless you want different templates for your sections. so We will add a default template under business/front/templates/default.php:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <title><?php echo $this->languages['title']?></title>
       <?php $this->renderCss();?>
       <?php $this->renderJs();?>
    </head>
<body>
<div data-role="page">
    <?php
        $this->render('header', 'Main');
        $this->renderMessages();
        $this->main();
        $this->render('footer', 'Main');
    ?>
</div>
</body>
</html>

Not too long. Let’s explain :
- in the head section, to display the title, we used $this->languages['title'], this allows you to have a multilingual application. Later on, we will have to fill a language file with the needed variables. Next in the head section, we have to call the renderCss and renderJs methods to get the previously pushed css and js code in the view.
- in the body section, the first php line uses the method render. this allows actually to call specific blocks in the view, here we are calling the header block and the footer block.
Thos blocks are actually under the Main view (see the file hierarchy above). The main() method will get the specific view to display it in the middle of the page.

Allright, what we are missing to get the work complete ? I’ll tell you:
- the partials (header, footer, feed index)
- the language file
Let’s start to write our header file, this one has to be under business/front/views/Main/header.php

<div data-role="header">
    <h1><?php echo $this->languages['title']?></h1>
</div>
<div data-role="content"><!--begin content -->
    <div id="jqm-homeheader">
        <h1><?php echo $this->languages['title']?></h1>
        <p><?php echo $this->languages['description']?></p>
    </div>

Notice always here that we are using the languages to display our text. Also notice the attributes and the specific classes of the jQueryMobile framework. Those will allow it to display correctly the styles and effects under iphone. This is what I like in this framework, it is the progressive enhancement method!
Anyway :-) lets write our footer file under business/front/views/Main/footer.php

</div><!-- end content -->
<div data-role="footer" class="ui-bar">
    <div data-role="controlgroup" data-type="horizontal">
    <a href="/" data-role="button" data-icon="home"><?php echo $this->languages['home']?></a>
        <a href="/?controller=Feed&action=add" data-role="button" data-icon="plus"><?php echo $this->languages['add']?></a>
    </div>
</div>

Lets write the index specific view, this view will list the feeds. open a new file under business/front/views/Feed/index.php and add the following lines :

        <ul data-role="listview" data-inset="true" data-theme="c" data-dividertheme="b">
        <li data-role="list-divider"><?php echo $this->languages['list']?></li>
        <?php
        if (count($this->feeds))
        {
            foreach ($this->feeds as $feed)
            {
        ?>
            <li><a href="/?controller=Feed&action=detail&id=<?php echo $feed->id?>"><?php echo $feed->name;?></a></li>
        <?php }
        } else { ?>
 
        <li><?php echo $this->languages['no_feeds']?></li>
        <?php }?>
        </ul>

In the index.php, all we do is that we are looping through the feed items to display the name and add a link to the detail page.
With those files, the view part is almost complete. We should move forward to add the language variables. This will be explained in the next section The configuration and helpers.

Nov 27, 2010
admin

A first model definition

In the previous section, we wrote our indexAction which makes use of a FeedModel model. Like the controllers, the models are modelized by classes. Again, you can choose the filename you want to store the models, Simple MVC will find the model by itself. Despite, we follow a folder hierarchy and some standards to place each file in an appropriate folder. The models are places under business/{your-module-application}/models. So in our case business/front/models.
So lets create our FeedModel under that folder:

/**
 * Feed Model
 */
class FeedModel extends CoreModel
{
    /**
     * Table Name
     *
     * @var mixed  Defaults to 'feed'.
     */
    protected $_tableName = 'feed';
 
    /**
     * Table keys
     *
     * @var array  Defaults to array('id').
     */
    protected $_tableKeys = array('id');
 
    // public properties
    /**
     * Feed Name
     *
     * @var string  Defaults to null.
     */
    public $name = null;
 
    /**
     * Feed Url
     *
     * @var string  Defaults to null.
     */
    public $url = null;
 
    /**
     * Items to be shown
     *
     * @var int  Defaults to null.
     */
    public $itemsNumber = null;
}

As you notice, the two protected properties of the Feed model will specify the table name and the table keys. the following will specify the properties, (the fields in the table). At the current version, Simple MVC is still implementing the Active Record pattern, However, this is subject to change in latter version to implement another pattern which will allow to have some separation of the table definition from the model itself, and to allow dis-coupling column names with properties names.
You understand though that we need to have to create a table corresponding to the model. Here is the SQL :

CREATE TABLE IF NOT EXISTS `feed` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) NOT NULL,
  `url` varchar(255) NOT NULL,
  `itemsNumber` int(11) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 ;
 
// make some insert directly when you create your tables
INSERT INTO `feed` (`id`, `name`, `url`, `itemsNumber`) VALUES
(1, 'Anis berejeb', 'http://feeds.feedburner.com/AnisBerejeb', 5),
(2, 'Houssem Bensalem', 'http://www.hbensalem.com/feed/', 4);

This is all we need for the model, all the magic is here since the FeedModel extends the CoreModel. However, the FeedModel is the placeholder where you will do your Data related logic. For example if you need to write some specific methods to deal with the data and return a certain collection or a certain instance, it should be in the model and not in the controller. The controller has just to “ask” the model to give him the data needed.
So Let’s continue to have our working index page, let’s have a look at the view section.

Nov 27, 2010
admin

A first controller action

The controller is modelized by a class that should be placed under business/{your-module}/controllers/. So in our case : business/front/controllers/. Just for a purpose of file lisibility, you can name your file Controller.php, you can name your file whatever you want, Simple MVC will find it :-) . We will create a FeedController that will handle the logic of
- adding feeds
- calling the feed urls and getting the feed items
- displaying the feed detail
So if we analyse those few lines, we will notice that we need some methods in our controller to :
- show the list page : this will be our index page, we will call it indexAction
- show the detail page : this will be our detail page, we will call it detailAction
- show an add page : we need an addAction
- save the added feed : we need a saveAction.
we will need to have few other method to do some glue.
So lets start!

class  FeedController extends CoreController
{
    /**
     * Inject dependencies
     *
     * @param  Container  $container The Container
     */
    public function setContainer(Container $container)
    {
        parent::setContainer($container);
        // database is set on the business layer. this will allow the use of
        // the mvc without coupling automatically the database.
        $this->Database           = $container['Database'];
        $this->Request = $container['Request'];
        $this->languages   =  $container['Language'];
    }
 
}

The first method we wrote is setContainer. this method allows us to customize what we need to have as accessible objects in our controller, it takes an instance of a Container, and gets some objects. In this case, we collect the Database object, since we need to store the feed addresses, the Request object since we need to deal with request variables, and the languages array since we need to manage many languages in our application.
Lets continue, the second method we will write is the alwaysAction, this action is actually always called before triggering our actions. Remember the call of frontDispatcher->route in the bootstrap file, this method will actually call the alwaysAction before calling our specific one (indexAction, addAction etc.). But why we need to write an always Action for our case? the response is that in all our actions, we will need to have an instance of the model we will use. for example, to list the feeds, we need this instance, to show the details, we will need it also etc. So instead of having to instanciate it in every action, we will override the alwaysAction and have our model instance in ther. the method will look like :

 public function alwaysAction()
    {
        parent::alwaysAction();
        $this->model = new FeedModel($this->Database);
    }

As you noticed, the model instance is also a class, and takes a database instance as a constructor parameter. We will look more in detail at the model in the following actions, and in the Understanding the Models section.
Next! we will write our index action, here is the code:

    /**
     * Index Action
     * will list the feeds
     */
    public function indexAction()
    {
        $feeds = $this->model->findAll();
        if (false !== $feeds)
        {
            $this->view->feeds = $feeds->fetchAll();
        }
    }

That’s it? yes, this is all we need to have for the moment :-) what we are doing here is that: we get all our feed using the findAll method of the model, and fetch all of them in the view. We didn’t spoke about the feed yet, we will do that later on. all you need to understand now is that we are passing the feeds to the view, it is its responsibility to display them.
We need to make that first page work, what we are missing to get this working? the model definition, and the view definition. so lets see how to add our model definition.

Nov 27, 2010
admin

The bootstrap file

the mean of www directory is to handle your webroot files. this is the only folder that should be accessible via your web server, also, you can have many webroots that are binded to each of your applications. in this way you share the api and the business code between your applications.
First, create an index.php file and edit it. The first thing we have to do is to import the libraries we need to load: here is the code

// include the configuration file
require_once(dirname(__FILE__) . '/../conf/configuration_front.php');
// include the autoload manager
require_once(dirname(__FILE__) . '/../core/autoloadManager.php');
// set the cache file for the autoload
autoloadManager::setSaveFile(dirname(__FILE__) . '/../tmp/front.php');
// add the folders you want to the  autoload, you should add always CORE to have the core files
autoloadManager::addFolder(CORE);
autoloadManager::addFolder(BUSINESS);
// trigger the autoload registration
spl_autoload_register('autoloadManager::loadClass');

Second, we will write some logic to handle the public or protected sections of our websites, inject our needed dependencies to the dispatcher and trigger the routing method to call the appropriate method in the controller. Here is the code :

try
{
    // get the dispatcher instance
    $front = frontDispatcher::getInstance();
    // get the actions
    $actions = AccessHelper::getActions();
    // authenticate using the actions configuration
    $AuthManager = new AuthManager($actions);
    // tell the Auth Manager where to route if the authentication failed
    $AuthManager->authenticate($front, '/?controller=Feed&amp;action=index');
    // get the appropriate application controller
    $Container = ContainerFactory::get('front');
    // inject the access configuration
    $Container['Access'] = $actions;
    // inject the Authentication object
    $Container['AuthManager'] = $AuthManager;
    // inject the request object
    $Container['Request'] = $_REQUEST;
    // inject the session object
    $Container['Session'] = SessionManager::getSession('front');
 
    // Route using the container as a confi
    $front->route($Container);
}
catch (Exception $e)
{
        // instanciate the debugging console, true is for debugging mode, false is the default
        $console = new DebugConsole($e, true);
        // render the errors
        $console->render();
 
}

Ok, I think this bunch of code needs some explanation. You may notice that there is maybe a lot of code for a bootstrapper, you could be right. However, I prefer to see what the framework is supposed to do for those action instead of having them at a separate layer. So lets explain the code :

  • $front = frontDispatcher::getInstance(); : This is quite simple, we are getting the instance of the front dispatcher.

next – and if we need  to use the Authentication and access manager , we need to add the following lines. Basically, the AccessHelper::getActions will return the list of the public and protected actions of our applications. The helper is related to a configuration file in which you can customize if the user should be authentified or not to access a certain action. The authenticate method of the AuthManager takes as parameters the dispatcher and the default url if the authentication fails.

  • $actions = AccessHelper::getActions();
  • $AuthManager = new AuthManager($actions);
  • $AuthManager->authenticate($front, ‘/?controller=Feed&amp;action=index’);

The folloging lines the code contains concern the Dependency injection container. The idea is that we have to pass all the dependencies of our controller from outside. The mechanism is more explained in the section Dependency injection container of this tutorial.

  • // get the appropriate application controller
    $Container = ContainerFactory::get(‘front’);
    // inject the access configuration
    $Container['Access'] = $actions;
    // inject the Authentication object
    $Container['AuthManager'] = $AuthManager;
    // inject the request object
    $Container['Request'] = $_REQUEST;
    // inject the session object
    $Container['Session'] = SessionManager::getSession(‘front’);

The last line of the try block will trigger the route method of the dispatcher. this allows to call the approppriate action on the approppriate controller.
In the catch block, using the DebugConsole, we display a friendly message to the user. A second parameter, set to true in a debug mode, allows displaying the exception stack trace for the developer.

So at this moment, the frontDispatcher root method is called, we have now to start writing our first controller!.

Nov 27, 2010
admin

Prepare the application skeleton

At this step, Simplemvc should be configured. In this part, we will start building our new application called front which will be the front end application.
Lets create the squeleton needed for a standard application. Since all the code is driven by classes and that Simple MVC uses an autoloading mechanism, is is not necessary to place the classes in a defined folder. But it is good to have some logic decomposition of the classes. Also, this could facilitate to have a namespacing implementation. The Simple MVC Autoload system supports perfectly Namespaces. there is even a Namespaces branch at github.
Here is a sample :

$ mkdir business/front
$ cd business/front
$ mkdir controllers models views container forms helpers templates
$ cd ../../
$ tree
.
`-- business
    `-- front
        |-- container
        |-- controllers
        |-- forms
        |-- helpers
        |-- models
        |-- templates
        `-- views

This is what we need for the moment as folders in the business layer.
We should do one last thing to get the structure complete, under the root folder :

$ cd www
$ mkdir images scripts styles
$ tree
.
|-- images
|-- scripts
`-- styles

In the next section, we will start with the bootstrap file, check it here!

Pages:12»