Writing a CMS/Community with Smarty and the Zend Framework Part 3


In this part we will take a look at how the main content area can change based on user actions. This is basically done in the same way we display menus with the difference that we have to give insert_item() dynamic data.

The insert block for the main area looks like this:

{insert name=”item” controller=”$controller” function=”$function” id=”$id”}

$controller, $function and $id have been assigned in the indexController. The function in question looks like this:

function dAction(){
		$params = $this->_request->getParams();
		$this->smarty->assign('id', $params['id']);
		$this->smarty->assign('controller', $params['c']);
		$this->smarty->assign('function', $params['f']);
		$this->display();
	}

So if we enter this in the address field:

http://localhost/index/d/c/article/id/dogs

We will call the above function with the parameter article as controller and nothing for function and dogs as id. Since we pass null as f the function to call will default to “render” as shown in part 2.

Let’s take a look at the article controller:

class ArticleController extends ExtController{

	function init(){
		parent::init();
		$this->name			= 'article';
		$this->obj 			= Common::loadModel($this->name);
		parent::finishInit();
	}

	function render($params){
		if(empty($params['id']))
			return 'No parameters when trying to render article.';
		$article = $this->obj->fetchRowToArr($params['id'], false, 'article_slug');
		if($article->acl_level > $this->getAclLevel()){
			if(empty($article->noacc_target))
				return Common::loadController('index')->frontPage();
			else
				return $this->aclNoacc($article->noacc_target);
		}
		$this->smarty->assign('article', $article->toArray());
		return $this->fetch();
	}
}

So we fetch the article with the help of the ‘article_slug’ field which in the above case would be “dogs”. We countinue by checking the access control list for this article to see if the current user is allowed to view it. Lets take a look at getAclLevel():

function getAclLevel(){
		if(empty($this->acl->acl_level))
			return 0;
		return $this->acl->acl_level;
	}

Simple enough, if we are not logged in which is the same as an empty acl namespace, then we return 0. We can conclude from this that an article which has an acl_level of 0 is viewable by everyone.

Let’s pretend that the article has an acl_level of 1 for instance. In that case we would not be able to see it when not logged in (the check above fails). We then proceed by checking if a field called ‘noacc_target’ is set. If it is not set then we call frontPage in IndexController:

function frontPage(){
		$where = array("front_page" => 1, "acl_level" => 0);
		$articles = Common::loadModel('article')->fetchToArr(false, false, true, $where);
		$this->smarty->assign('articles', $articles);
		return $this->fetch('front_page.tpl');
	}

The above function will simply try and fetch all articles with an access level of 0 and display them instead of the content we were not allowed to see. Pretty crude at this stage but it’s easy to see how we could make this logic more sophisticated. Lets take a look at fetchToArr in ExtModel:

function fetchToArr($id_value = false, $id_field = false, $as_array = true, $where = false){
		if($where != false){
			$where_sql = array();
			foreach($where as $field => $value)
				$where_sql[] = $this->getAdapter()->quoteInto("$field = ?", $value);

			$rowset = $this->fetchAll($where_sql);
		}else if($id_field == false || $id_value == false){
			$rowset = $this->fetchAll();
		}else{
			$sql = $this->getAdapter()->quoteInto("$id_field = ?", $id_value);
			$rowset = $this->fetchAll($sql);
		}

		if($as_array == true && $rowset != false)
			return $rowset->toArray();
		else
			return $rowset;
	}

As is the case with fetchRowToArr() it’s pretty stupidly named as it obviously can return rowset objects too, not just arrays.

Now let’s retrace our steps, pretend we have a noacc_target value in the dogs article. In that case aclNoacc() executes as you can see above:

function aclNoacc($noacc){
		list($controller, $function) = explode("/", $noacc);
		return Common::loadController($controller)->$function();
	}

Simple enough. If we pretend that the value of noacc_target in the dogs article is “user/register” it’s easy to see that that will call the UserController with the function register(). That is what part 4 will be all about. User registration and all the headaches it brings with it in the form of for instance validating input and so on.

SQL for the article controller:

CREATE TABLE `db_articles` (
  `id` bigint(12) NOT NULL auto_increment,
  `article_slug` varchar(250) NOT NULL,
  `article_text` text NOT NULL,
  `article_class` varchar(250) NOT NULL,
  `acl_level` int(4) NOT NULL default '0',
  `noacc_target` varchar(250) NOT NULL,
  `front_page` tinyint(1) NOT NULL default '0',
  PRIMARY KEY  (`id`),
  UNIQUE KEY `article_slug` (`article_slug`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=4 ;


Related Posts

Tags: , ,