MVC Code Structure


By David | October 8, 2012 | Home | Blog Categories | Helpful Resources

This is an for a php developer to help them understand the MVC coding structure in phpLD 5. This article is meant for a web developer to help them get started, but not for an everyday user.



New phpld code structure

/code - base and abstract classes
Phpld_View - view factory, creates a view class. Here we will replace smarty with the newer versions. This should be the only place where template instance creates.
Phpld_Db - Singleton class, which allows to access database object, to not use global $db, $tables everywhere - Phpld_Db::getInstance()->getAdapter() and Phpld_Db::getInstance()->getTables() should be used instead.

Phpld_App - main application class, used in bootstrap files, for example index.php code looks so:



require_once 'init_r.php';
require_once 'code/App.php';

$app = Phpld_App::getInstance();
$app->dispatch();
$app->run();

Phpld_Router_Request - resolves controller and action

Phpld_Controller_Abstract - Base controller class, inits view and layout instances, resolves template file to fetch

/application - here application code would be

Home page controller example

class IndexController extends PhpldfrontController
{
   public function indexAction()
   {
       $this->view->assign('maincontent', MAINCONTENT);

       $categoriesModel = new Model_Category();
       $categories = $categoriesModel->getCategories();

       $this->view->assign('categs', $categories);
   }
}

PhpldfrontController controller is a base class for all front end controllers, fetches widgets, sets meta tags and other routines.


I’ve added also an additional data layer to access database, nothing special, just to keep code together by its purposes. For example Model_Category class contains public function getCategories($idCategory = 0, $idUser = null) methds, which returns categories by parent and for user. It returns an array of Entity classes, for example Model_Category_Entity class code:


class Model_Category_Entity extends Phpld_Model_Entity
{
   public function getUrl()
   {
       if (!empty($this['URL'])) {
           $href = $this['URL'];
       } else {
           $href = DOC_ROOT.'/'.$this['CACHE_URL'];
       }
       return $href;
   }
}


This class just implements array access interface, so it’s accessible as usual array, but allows to add special methods, as getUrl():

class Model_Category_Entity extends Phpld_Model_Entity
{
   public function getUrl()
   {
       if (!empty($this['URL'])) {
           $href = $this['URL'];
       } else {
           $href = DOC_ROOT.'/'.$this['CACHE_URL'];
       }
       return $href;
   }
}

so we can use
{$cat->getUrl()} in template instead of {if !empty($scat.URL)}{$scat.URL}{else}{$smarty.const.DOC_ROOT}/{$scat.CACHE_URL|escape}{/if}, so if we decide to change url strategy we can do it one place.

Templates changes

Template files are split by folders now
[TEMPLATE_DIR]/views folder contains controller views. For example category view page template is here: /views/category/view.tpl, where
In CategoryController controller class it would be viewAction() method.
Common templates are in _shared folder

[TEMPLATE_DIR]/layouts folder contains layout template (zend like), In each controller and action can be set another layout file if needed, but by default it is /layouts/default.tpl

Now it’s code is:
{include file="views/_shared/header.tpl"}
{include file="views/_shared/top_bar.tpl"}
{$content}

{include file="views/_shared/footer.tpl"}


Controller guideline


In controller should NOT be any code like this:
class CategoryController extends PhpldfrontController
{
   public function indexAction()
   {
       if ($_GET[‘action’]) {
       }
   }
}

new code structure was created to get rid of long spaghettis of IF {} ELSEIF {} ELSEIF {}

You should create a new controller action to handle this.

We should also follow common code placing rules. On the beginning of action method should go gathering of input parameters, then action code and assigning of template variables at the end.
Here is an example:

class CategoryController extends PhpldfrontController
{
   public function indexAction()
   {
       // Get input parameters
       $categoryPath = $this->getParam('category');

       // Action code
       $categoryModel = new Model_Category();
       $idCategory = $categoryModel->getCategoryByUri('/'.$categoryPath);
       $categoryModel = new Model_Category();
       $category = $categoryModel->getCategory($idCategory);

       // Check is post was submitted
       if ($this->isPost()) {

       }

       // Assign variables
       $this->view->assign('category', $category);
       $this->view->assign('links', $category->getLinks());
   }
}


Controller helper methods:
getParam($paramName) - gets parameter from $_REQUEST parameter. Should be used instead of directly using $_GET or $_POST. This will require to us to filter input parameters

isPost() - returns true if post request was submitted instead of if ($_POST[‘submit’]){}. No need to add this extra field to forms when using this method.

Models

application/models folder
Models are another level of database interaction structure. They contains code, which manipulates some specific entity data.
The simplest implementation of model is the following:

class Model_User extends Phpld_Model_Abstract
{
   protected $_entityClass = 'Model_User_Entity';

   protected $_modelTable = 'user';
}

where $_entityClass is a class name of one single item in a list of users and $_modelTable is a name of table in PHPLD tables list ($tables global variable). It extends Phpld_Model_Abstract abstract class, which has 3 methods now:

public function entity($data) - creates a class instance of $_entityClass type.

public function update($data, $where)
and
public function insert($data)

Last 2 used to update and insert data in $_modelTable table.

Model Entity

application/models/[MODEL_NAME] folder
Model entity is a very simple class, which just implements ArrayAccess PHP SPL interface. It created to allow manipulating data of entity and create some accessor methods, like “getUrl()” in Category and Link entities or “getLinks()” method of Category entity.

Data collection

Another helper class, which allows to iterate through list of entities and also knows how much entites it has and how many of them there are in non-filtered query.

In PHPLD we can often meet code, which gets links (categories) by some criterias and then makes the same query but without LIMIT with COUNT(*) to get number of results. This creates overhead in proejcts with big number of links, so instead of it we should use this:

       $query = "SELECT SQL_CALC_FOUND_ROWS * FROM [TABLE] WHERE [CONDITIONS]";
       $links = $this->_db->CacheGetAll($query);
       $count = $this->_db->getOne("SELECT FOUND_ROWS() as count");
This allows to get number of rows without limit without the second “count” query.

Then we can create a collection in this way:

       $collection = new Phpld_Model_Collection(Model_Link_Entity, $count);
       $collection->setElements($links);
second “count” parameter is optional. There is also “setCountWithoutLimit()” method, whichsets count. countWithoutLimit() method returns this number.


Paginator

Phpld_Paginator is a helper class, which helps not to write in controller code bunch of code, like it was done before in index.php

It’s constructor gets 2 parameters - LinksPerPage and PagerGroupings(how many pages to show in paginator)
$paginator = new Phpld_Paginator($LinksPerPage, $PagerGroupings);

It has methods, which helps to compose queries to get data - getOffset() - offset for limit and getLimit(), which returns complete LIMIT X, Y string. Here is an example of it’s usage to get category links for page -
$links = $category->getLinks(false, $paginator->getOffset(), $paginator->getPerPage());

It also has assign method, which assigns paginator to template. Example:
$paginator->assign($this->layout, $links->countWithoutLimit(),  'MainPaging');


Breadcrumbs


In controller use you can use $this->breadcrumbs('Yarr', 'http://google.com'); method to add items to breadcrumbs. Second URL parameter is optional. This helper method uses Phpld_Breadcrumbs class inside, which handles adding items to breadcrumbs and rendering

Current User Entity

There is a special singleton class for interacting with current user instance - Model_CurrentUser
Has following methods:
getInstance() - returns an instance. As class is a singleton - this is the only way to get it’s instance
isLoggedIn()
getId()
getLevel()
getPermissions()
loadData() - returns current user data
update() - overloads Model_User::update (). Adds current user ID to update query, so no need to set ID when updating user data.
Usage examples:
Model_CurrentUser::getInstance()->isLoggedIn() //check is user logged n

// Update current user data
$user = Model_CurrentUser::getInstance();
$user->update($data);

Flash Messenger

Used to show success/error/info/warning mesages after redirect.
In controller action you can run one of these methods to add mesages:

$this->fm()->error(‘message’);
$this->fm()->info(‘message’);
$this->fm()->success(‘message’);
$this->fm()->warning(‘message’);

After redirect messages will be shown once

Meta tags

Controller has setMeta() helper method, usage example:
$this->setMeta('keywords', $data['META_KEYWORDS']);

If tag not set in controller - default will be used, which is set in admin panel

Page Title

Use setTitle() method.
It has 2 parameters - $value and $rewrite = false;
B default this method appends text to previously set title text. Second parameter allows to rewrite previously set data



« Back to Helpful Resources
Previouse article: What is phpLD?
Next article: Listing Types Development Guide

Publish date: October 8, 2012
Printer version    

Support Our Sponsors

Posts by Category

   categories Articles
   categories Development Blog
   categories Helpful Resources
   categories Mods
   categories News
   categories Spotlight on Great Directories
   categories Templates
   categories Tutorials

Hosting

A great prize awaits if you use our recommended host. Take a look at our special offer to find out how you can get our product virtually free. or receive other benefits. We also have a recommended hosts page, and we give you credits such as our product just for signing up with them.