CakePHP - dynamic application’s homepage – another approach.

One of the thing a webmaster has to deal with is to create a homepage. It was also my recent problem. I needed to create a prototype of app’s main page that should include some logo, some menu, the newest events (posts with event info added by users), login form and some footer. More or less such prototype:

 1

Some ideas that I found on Internet were:

  • to extend Pages Controller or,
  • replace the default route to point to another page.

More about the above here:
http://teknoid.wordpress.com/2008/11/17/get-yourself-a-new-home-alternative-to-homectp/
http://www.phpfreaks.com/forums/index.php?topic=240370.0
http://www.phpfreaks.com/forums/index.php?topic=240370.0

I chose another solutions: the elements.

First off all we need to have some basic functionality. In my case a basic EventsController and UsersController. First step is to create a layout. It is usual that a webapp uses at least two layouts. One for a home page and another one (or more) for subpages.

I called my layouts: mainpage.ctp and default.ctp for the other pages.

To define a layout for a page we have to go to the page’s controller. In my case I had to change PageController (which by default is in cake\lib\controller folder):

function display() {
    $this->layout = 'mainpage';
    (…)
}

Creating a layout is as easy as creating a website. A sample file default.ctp we can find in cake/libs/view/layouts/ and modify it for our needs. We only have to remember about some variables that carry data from controller:

  • $title_for_layout – page title that is defined in controller's functions.
function view($id = null) {
   $this->pageTitle ='Events';
(...)
}
  • $scripts_for_layout – contain external sources for example scripts or css files added by html helper.
  • $content_for_layout - data gathered from controller.

To create the usual html content – meta tags, charset, form etc. we can use html helper. More about it here: http://book.cakephp.org/view/206/Inserting-Well-Formatted-elements

Now is the time to create elements. I needed four. Two for menus that are more or less static and another two dynamic. First one is a login form and next one displays newest events on the main page. The elements are placed in app/views/elemens/.

menu.ctp:

<?php echo $html->link("home", "/", array(), null, false); ?>
<?php echo $html->link("events", "/events", array(), null, false); ?>

menufooter.ctp

<?php echo $html->link("Contact Us", "/kontakt", array(), null, false); ?>
<?php echo $html->link("Terms of Service", "/zasady", array(), null, false); ?>
<?php echo $html->link("Cooperate", "/wspolpraca", array(), null, false); ?>
<?php echo $html->link("Advertise", "/reklama", array(), null, false); ?>
			
<?php 
echo $html->link(
  $html->image('cake.power.gif', array('alt'=> __("CakePHP: the rapid development php framework", true),   'border'=>"0")),
  'http://www.cakephp.org/',
  array('target'=>'_blank'), null, false);?>

The first two are easy and there is nothing to explain.

For user authentication I used Auth Component (http://book.cakephp.org/view/172/Authentication). The default login action is users/login.

login.ctp

<?php
$session->flash();    
$session->flash('auth');
?>
<?php  
if(!$session->check('Auth.User')){
	echo "

Please log in.

"; echo $form->create('User', array('action' => 'login')); echo $form->input('username'); echo $form->input('password'); echo $form->end('Login'); } else{ echo "

Hello ".$session->read('Auth.User.name')."

"; echo $html->link("logout", "/users/logout", array(), null, false); } ?>

The last element – newest.ctp - must pick up some data from EventsController. For that I created a function in the controller that will provide the data for the element.

function main_show_newest(){
		$events = $this->Event->find('all', array('order' => array('Event.insert_date ASC'),'limit' => 3));
		return $events;
	}

Then in the element we use $this->requestAction('events/main_show_newest') to request data from the controller.

newest.ctp

<?php $events = $this->requestAction('events/main_show_newest');?>

<?php echo __("Newest events around......") ?>

<?php foreach($events as $event): ?>
  • <?php echo $event['Event']['name']; ?>
    <?php echo $event['Event']['starting_date']; ?>-<?php echo $event['Event']['end_date']; ?>
    <?php echo $event['Event']['description']; ?> <?php echo $html->link("more", array( 'controller' => 'events', 'action'=>'view', 'id'=>$event['Event']['id']), null, false); ?>
<?php endforeach; ?>

There is also another possibility. In controller we use simply $this->paginate() and then in the element $this->requestAction('events/main_show_newest/sort:insert_date/direction:asc/limit:3').

To include an element menu.ctp to the layout use $this->element('menu').

The full mainpage layout:

mainpage.ctp

<?php echo $html->docType(); ?>



<?php echo $html->charset(); ?>
	Kultura.info.pl - <?php echo $title_for_layout; ?>
	
<?php
 echo $html->meta('description','Best event tracker ever!');
 echo $html->meta('keywords', 'event, events');
 echo $html->css('kultura.generic');
 echo $scripts_for_layout;
?>
	


<?php echo $this->element('login');?>
<?php $session->flash(); ?> <?php echo $content_for_layout; ?>

The other layout at this moment has only one difference in comparison to main page layout: it has no login form. I use it everywhere but the main page. Because I left the name default.ctp for this layout I don’t need to declare or configure it anywhere.

And that’s it. I hope it gives a basic overview of this concept.