Reputation: 225
Where should a breadcrumbs path be declared (in other words, in which letter of MVC)? So far I've been declaring it in Controllers, but I've recently started to work with CakePHP, where it is all made in Views and it surprised me.
Upvotes: 3
Views: 3954
Reputation: 26624
I'm going to throw an answer out here, because there's a lot of confusion about what should and shouldn't be done with breadcrumbs.
The Model is a layer that contains your business logic consisting of domain objects, data mappers and services. You can read more about the model here.
Remember: fat model, skinny controllers. Your controller / method is accessed from your routing mechanism. Once you're in the controller, you want to get your model object, perform whatever logic is required in the model, have the result of this returned to a variable in your controller, and then you use this to display data in your view.
That being said, your breadcrumbs need different parts to work. Let's think about this:
Breaking those down:
class=current
if found.Note: untested
/**
* So we're in the home controller, and index action
*
* @route localhost/home or localhost/home/index
* (depending on .htaccess, routing mechanism etc)
*/
class Home extends Controller
{
public function index()
{
// Get current class name, so we have the current page
$class = __CLASS__;
// Let's say the page heirachy is tied to the model, so get pages for current method, or however you want to implement it
$pages = $model->getPages($class);
// So the TEMPLATE handles the breadcrumbs creation, and the controller passes it the data that it needs, retrieved from the model
// (new Template) is PHP 5.4's constructor dereferencing, also included is some lovely method chaining
// setBreadcrumbs() would assign variables to the view
// Render would do just that
(new Template)->setBreadcrumbs($currentPage, $pages)->render();
}
}
And now, the view... note, I use PHP 5.4, so I can use short echos...
<body>
<?php foreach($breadcrumbs as $b) { ?>
<li <?=($b['current'])?'class="current"':''?>>
<a href="<?=$b['page']['url']?>">
<?=$b['page']['title']?>
</a>
</li>
<?php } ?>
</body>
And that's how I would do it. Some of this is down to personal preference, but I hope this shows one way of doing it and is at least a little useful.
I actually came across this answer googling "php mvc breadcrumbs", and writing out my brain has really helped me to figure this out too. So thanks!
Upvotes: 4
Reputation: 917
$this->Html->addCrumb('Home', '/pages/home');
$this->Html->addCrumb('Contacts', '/pages/contacts');
echo $this->Html->getCrumbs('»', 'StartText');
Upvotes: 0
Reputation: 639
Whenever you see words "logic" and "view" together you should start worrying. My vote is for Controller because breadcrumbs is typical example of application-level logic, so putting it to the view violates MVC in my opinion.
Upvotes: 1
Reputation: 532615
IMO, the breadcrumb relates to the set of controller actions taken to get to the current page or the action's place in the hierarchy of the site, depending on your interpretation. From that perspective, the controller seems the natural place to construct the data for it, though the rendering should occur in the view. In order for it to be completely generated in the view, you would need to either expose details about what controller action is being invoked by the view or have a fixed view-per-action model so that the breadcrumb for each could be precalculated. Moving the logic for computing the breadcrumb to the view itself seems to violate the separation of concerns in MVC and may preclude reusing views for different actions, which would violate DRY>
In my opinion, generating data for the breadcrumb is a cross-cutting concern in the controller, i.e., you have some shared code that runs regardless of the action that uses the url to construct the breadcrumb data. There is also some shared view code that takes the controller-supplied data and renders it consistent with the design.
Note that I'm speaking from a purely architectural perspective. I'm not familiar enough with CakePHP (or other PHP frameworks, for that matter) to even judge whether your observation about it is correct. From a pattern perspective, putting it in the controller seems like the right thing to do. In a given implementation, though, it might make sense to violate the pattern.
Upvotes: 0
Reputation: 28893
Breadcrumbs should be in the controller. I use CodeIgniter and do something like
$data['breadcrumb'][0] = array("title" => "Home", "alt" => "Home Page", "path" => "home/");
$data['breadcrumb'][1] = array("title" => "About", "alt" => "About Me", "path" => "home/about");
And then in the view loop through and display them as a list.
<ul class="breadcrumbs">
foreach($breadcrumb as $b)
{
?>
<li><a href="<?php echo base_url(); ?>index.php/<?php echo $b['path'];?>" alt="<?php echo $b['alt']; ?>"><?php echo $b['title']; ?></a></li>
<?php
}
</ul>
You can then also declare simple things like classes, current pages, etc. The only downside is you have to set the breadcrumbs in every page.
ALL logic should be in the controller. Access databases through the models, perform logic in the controller, and pass it to the view.
Simple stuff like
<?php echo ($loggedin)?"Logged in as" . $user->firstname:"Not logged in";?>
can be in the view. But you shouldn't be setting up complex flow patterns. Leave that to the controller. Views are cheap. You can have a half dozen slightly different views and no one will care. It's not like static HTML where you would have to maintain a half dozen pages.
Include common things in the views (like headers, footers, script files, javascript files, etc) and then let them be.
Upvotes: 0