应该在哪里声明面包屑路径(换句话说,在 MVC 的哪个字母中)?到目前为止,我一直在 Controllers 中声明它,但我最近开始使用 CakePHP,它都是在 Views 中制作的,这让我感到惊讶。
5 回答
我将在这里给出一个答案,因为对于应该和不应该用面包屑做什么有很多困惑。
该模型
模型是一个包含业务逻辑的层,由域对象、数据映射器和服务组成。您可以在此处阅读有关该模型的更多信息。
控制器
记住:胖模型,瘦控制器。您的控制器/方法是从您的路由机制访问的。进入控制器后,您需要获取模型对象,执行模型中所需的任何逻辑,将结果返回到控制器中的变量,然后使用它在视图中显示数据。
面包屑
话虽如此,您的面包屑需要不同的部分才能工作。让我们考虑一下:
- 他们需要当前页面
- 他们需要一个页面列表
- 他们(可能)需要添加一个自定义的“class=current”
分解那些:
- 在我的框架中,当前控制器也是页面名称(登录控制器映射到 /login)。所以,我们已经有了当前页面。
- 页面列表。
- 如果您的页面的父/子关系直接与数据模型相关联,那么在您的控制器中,您从模型中提取页面列表。因此,如果面包屑可以自动生成,请使用该模型。
- 如果您使用的框架允许完全由用户选择创建的面包屑,那么您只需手动选择要放入面包屑的内容。无论哪种方式,您都在控制器中声明您的面包屑,如果您需要从某个地方获取它们,请使用该模型。
- 最后,“class=current”。尽管您的观点中不应该真正包含重要的“逻辑”,但循环或 if 语句之类的小东西是相当标准的。在这里,您将检查与当前控制器名称相等的标题(作为变量传递给视图)的面包屑,并添加一个
class=current
if found。
代码示例
注:未经测试
/**
* 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();
}
}
现在,视图...注意,我使用 PHP 5.4,所以我可以使用短回声...
<body>
<?php foreach($breadcrumbs as $b) { ?>
<li <?=($b['current'])?'class="current"':''?>>
<a href="<?=$b['page']['url']?>">
<?=$b['page']['title']?>
</a>
</li>
<?php } ?>
</body>
我就是这样做的。其中一些取决于个人喜好,但我希望这显示了一种方法并且至少有点用处。
实际上,我在谷歌搜索“php mvc 面包屑”时遇到了这个答案,写出我的大脑确实也帮助我弄清楚了这一点。那谢谢啦!
每当您同时看到“逻辑”和“视图”这两个词时,您就应该开始担心了。我投票支持 Controller,因为面包屑是应用程序级逻辑的典型示例,因此在我看来,将其放到视图中违反了 MVC。
面包屑应该在控制器中。我使用 CodeIgniter 并做类似的事情
$data['breadcrumb'][0] = array("title" => "Home", "alt" => "Home Page", "path" => "home/");
$data['breadcrumb'][1] = array("title" => "About", "alt" => "About Me", "path" => "home/about");
然后在视图中循环并将它们显示为列表。
<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>
然后,您还可以声明类、当前页面等简单的东西。唯一的缺点是您必须在每个页面中设置面包屑。
所有逻辑都应该在控制器中。通过模型访问数据库,在控制器中执行逻辑,并将其传递给视图。
简单的东西,比如
<?php echo ($loggedin)?"Logged in as" . $user->firstname:"Not logged in";?>
可以在视图中。但是您不应该设置复杂的流模式。把它留给控制器。观点很便宜。你可以有六种略有不同的观点,没有人会在意。它不像静态 HTML,您必须维护六个页面。
在视图中包含常见的东西(如页眉、页脚、脚本文件、javascript 文件等),然后任其发展。
IMO,面包屑与为到达当前页面或操作在站点层次结构中的位置而采取的一组控制器操作有关,具体取决于您的解释。从这个角度来看,控制器似乎是为其构建数据的自然场所,尽管渲染应该发生在视图中。为了使其在视图中完全生成,您需要公开有关视图正在调用的控制器操作的详细信息,或者具有固定的视图每个操作模型,以便可以预先计算每个操作的面包屑。将计算面包屑的逻辑移到视图本身似乎违反了 MVC 中的关注点分离,并且可能会阻止将视图重用于不同的操作,这将违反 DRY>
在我看来,为面包屑生成数据是控制器中的一个横切关注点,即,无论使用 url 构造面包屑数据的操作如何,您都有一些共享代码运行。还有一些共享视图代码获取控制器提供的数据并使其与设计保持一致。
请注意,我是从纯粹的架构角度说的。我对 CakePHP(或其他 PHP 框架,就此而言)不够熟悉,甚至无法判断您对它的观察是否正确。从模式的角度来看,将其放入控制器中似乎是正确的做法。但是,在给定的实现中,违反该模式可能是有意义的。
$this->Html->addCrumb('Home', '/pages/home');
$this->Html->addCrumb('Contacts', '/pages/contacts');
echo $this->Html->getCrumbs('»', 'StartText');