views:

1518

answers:

10

I am developing a website in PHP and I would like to use a mvc framework to do this as I want to gain experience with PHP frameworks.

I have looked at Zend, CakePHP, and CodeIgniter and I have not been able to find an intuitive way to accomplish this.

What I need to do is create a layout that will be for example:

<html>
<head>
<!--scripts go here-->
</head>
<body>
<div id='banner'></div>
<div id='menu'><?php $this->layout()->menu ?></div>
<div id='container'><?php $this->layout()->content ?></div>
<div id='ads'><?php $this->layout()->ads ?>
<div id='footer'>blah</div>
</body>
</html>

I am looking for a framework that could do this simply without a lot of hacks as this should be simple to accomplish from my perspective.

This would pull the menu, content, and ads from separate controllers and views and would of course be dynamic content. I do not want to put the menu code into every view...

Maybe this is simple and I am just going about it the wrong way?

Any help is appreciated.

Thank you,
-Ben

A: 

You're probably not looking for a framework so much as a templating engine. Try Smarty.

UltimateBrent
A: 

Smarty or Tempalte lite

easement
+1  A: 

Each of the PHP libraries you have mentioned have templating and can accomplish what you need.

Pick a library and get to grips with it. It will pay off over time. Templating engines like Smarty are good, but a full framework offers a lot more.

andyuk
I don't think I explained myself correctly.The following webpage really explains what I am trying to accomplish but I was unable to get this to work...http://teethgrinder.co.uk/perm.php?a=Zend-Framework-Menus-Navigation
A: 

In Cake you could put this in an element that you just include via

echo $this->element('menu');

You can make this element as complicated or simple as you like. If you need it to automatically highlight in which section of the page you are, there are several methods. For example, set a variable in each Controller/Action that the element can pick up on.

// Controller
$this->set('currentNode', 'homepage');

// Menu Element
if ($currentNode == 'homepage') {
    // add class 'selected' to menu item, or something like this
}

Depending on how complicated your application is, you could also keep it completely self-contained.

// Menu Element
if ($this->controller == 'home') {
    // highlight this menu item, add extra sub-items, re-calibrate flux capacitor
}

The point being, there are certainly ways to do this, but it depends on the framework you use and what exactly you need to accomplish. It should be rather trivial to do in any framework, and your choice of framework/templating engine should not depend on this little feature.

deceze
how would this fit in the mvc pattern so I don't put this in every view? in a layout?Thanks for the response.
Yes, a layout is the best place to put it.
deceze
thank you, that is exactly what I needed to know!
Do you know how to do this in CodeIgniter?
Sorry no, never used CodeIgniter. As I said though, there's a way to do this in every framework, so don't sweat it. Choose which framework you like best first, based on all the other requirements you surely have, then find out the best way to do this in your framework of choice.
deceze
A: 

In Zend Framework (which is the only one I know of those you mentioned) there are several ways to accomplish this. I prefer the Helper way.
Your layout will look:

<html>
<head>
<!--scripts go here-->
</head>
<body>
<div id='banner'></div>
<div id='menu'><?php $this->menu() ?></div>
<div id='container'><?php $this->layout()->content ?></div>
<div id='ads'><?php $this->ads() ?>
<div id='footer'>blah</div>
</body>
</html>

And you will have two view Helpers:

class Zend_View_Helper_Menu{
   public function menu(){
       echo "<html.........>";
   }
}

AND

class Zend_View_Helper_Ads{
   public function ads(){
       echo "<html.........>";
   }
}

There is also a way which will result in exactly the syntax you gave. Not familiar with this way, try this link

Itay Moav
this is almost exactly what I'm looking for! My only question is because I would need to interact with the model (to pull the menus from the db) and I would be outputting HTML wouldn't this be going against MVC? Is there a way to do this following MVC?Thank you!
I tend to regard such "islands" as a package, But I guess you can use partials to accomplish this, and use the helpers to only load the data from the models.
Itay Moav
You can use have BaseController class extending Zend_Controller and having the model querying in predispatch() filled like $this->view->layoutMenu = array(...); and in helper you can get $menu = $this->_view->layoutMenu or push it via call argument $this->menu($this->layoutMenu);
Tomáš Fejfar
If it is not KISS I wouldn't do it, even if it "enforces" a certain design pattern.
Itay Moav
+1  A: 

Symfony can do what you are looking for using a mix of concepts.

  • Layout - This is the main structure used to decorate a page.
  • Template - This is the main view attached to a URL by the controller.
  • Fragments - Lightweight and uses data you pass to it.
  • Component - Used if you need access to the model, the code is split between presentation and logic.
  • Slot - used to replace a defined section of the layout.

In your case the layout would have the main content included using the template logic which is the core of the view layer and the other items would be either fragments or components depending on how much of the model they would need to access.

The Symfony documentation has a full explanation of this.

Colonel Sponsz
A: 

In Zend Framework you can create individual actions and views for each section of your layout by setting the ViewRenderer helper's responseSegment property like so:

class IndexController extends Zend_Controller_Action {

    public function menuAction() {

     //menu code goes here

     $this->_helper->viewRenderer->setResponseSegment('menu');
    }

    public function adsAction() {

     //ads code goes here

     $this->_helper->viewRenderer->setResponseSegment('ads');
    }
}

etc...

You can then call them in the layout file exactly the way you specified:

<?= $this->layout()->menu; ?>
<?= $this->layout()->ads; ?>
Thank you for the response. My question though how can I do this and set it up to use a menu controller and a menu view and the same with ads? I've read about this but I don't completely understand as I'm new to Zend. Can you explain with examples?Thanks!
The solution I posted was actually incomplete. I forgot that I had to create a controller plug-in to actually call the individual actions for each request. For a good example and explanation, check out Zend Framework in Action by Rob Allen at http://www.manning.com/allen/. Grab the source code and check out chapter 4, it covers what you are trying to do and it's where I originally learned the technique.
A: 

It's easy in DooPHP framework, just use <!-- include 'templatefilename' --> in your view templates. The view part of the framework is very flexible. There's a template engine demo on the site http://doophp.com/demos

+2  A: 

Actually, what you want to achieve here can be done with very little deviation from what you have already, using Zend Framework.

For the menu, you can use Zend_Navigation, which allows you to define the tree of the navigation of your site, and create simple menus. I find that populating the Zend_Navigation container in a Front Controller plugin allows you to cache the object easily, so you have little performance worries from traversing your sites tree,

For the ads, you simply use the placeholder view helper, and you can once again use a Front Controller plugin to populate this. Using a plugin has the advantage that the logic of counting impressions and rotating ads is kept seperate from your actions, and easily performs its task across every action.

dustin.cassiday's method of using the action stack is risky, and can lead to massive headaches debugging your apps. and Itay Moav's method is now really redundant due to Zend_Navigation

Bittarman
A: 

It's possible with actionStack in the controller:

$this->_helper->actionStack('menu','index'); $this->_helper->actionStack('ads','index');

troppo