MVC 应用程序中的面包屑逻辑

发布于 2024-09-06 02:21:05 字数 94 浏览 4 评论 0原文

面包屑路径应该在哪里声明(换句话说,在 MVC 的哪个字母中)?到目前为止,我一直在控制器中声明它,但我最近开始使用 CakePHP,它全部是在视图中制作的,这让我感到惊讶。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

尹雨沫 2024-09-13 02:21:05

我要在这里给出一个答案,因为对于面包屑应该做什么和不应该做什么存在很多困惑。

模型 模型

是一个,其中包含由域对象、数据映射器和服务组成的业务逻辑。您可以在此处了解有关该模型的更多信息。

控制器

记住:胖模型,瘦控制器。您的控制器/方法是从您的路由机制访问的。进入控制器后,您需要获取模型对象,执行模型中所需的任何逻辑,将结果返回到控制器中的变量,然后使用它在视图中显示数据。

面包屑

话虽如此,面包屑需要不同的部分才能发挥作用。让我们考虑一下:

  • 他们需要当前页面
  • 他们需要页面列表
  • 他们(可能)需要添加自定义“class=current”

分解这些:

  • 在我的框架中,当前控制器也是页面名称(登录控制器映射到/登录)。所以,我们已经有了当前页面。
  • 页面列表。
    • 如果页面的父/子关系直接与数据模型相关,则在控制器中从模型中提取页面列表。因此,如果面包屑可以自动生成,请使用该模型。
    • 如果您使用的框架允许完全由用户选择创建面包屑,那么您只需手动选择要放入面包屑中的内容即可。 无论哪种方式,您都可以在控制器中声明您的面包屑,如果您需要从某个地方获取它们,请使用模型。
  • 最后,“class=current”。尽管您认为实际上不应该包含重要的“逻辑”,但像循环或 if 语句这样的小东西是相当标准的。在这里,您将检查面包屑中是否有等于当前控制器名称的标题(作为变量传递到视图),如果找到,则添加一个 class=current

代码示例

注意:未经测试

/**
 * 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 breadcrumbs”时发现了这个答案,写出我的大脑也确实帮助我弄清楚了这一点。所以谢谢!

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

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.

The Controller

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.

The Breadcrumbs

That being said, your breadcrumbs need different parts to work. Let's think about this:

  • They need the current page
  • They need a list of pages
  • They (may) need a custom "class=current" added

Breaking those down:

  • In my framework, the current controller is also the page name (login controller maps to /login). So, we already have the current page.
  • The list of pages.
    • If your parent/child relationship of the pages are tied directly to the datamodel, then in your controller you pull the list of pages from the model. So use the model if the breadcrumbs can be automatically generated.
    • If the framework you're using allows breadcrumbs created entirely by user choice, then you are just choosing what to put in the breadcrumbs manually. Either way, you state your breadcrumbs in the controller, and if you need to get them from somewhere, use the model.
  • Finally, the "class=current". Although you shouldn't really contain significant 'logic' in your view, small things like loops or if statements are pretty standard. Here, you would check your breadcrumbs for the title equalling the current controller name (passed through as a variable to the view), and add a class=current if found.

Code Example

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!

养猫人 2024-09-13 02:21:05

每当你看到“逻辑”和“观点”这两个词在一起时,你就应该开始担心。我投票支持 Controller,因为面包屑是应用程序级逻辑的典型示例,因此在我看来将其放入视图违反了 MVC。

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.

杀お生予夺 2024-09-13 02:21:05

面包屑应该位于控制器中。我使用 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 文件等),然后就随它们去吧。

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.

恰似旧人归 2024-09-13 02:21:05

IMO,面包屑与访问当前页面或操作在站点层次结构中的位置所采取的一组控制器操作相关,具体取决于您的解释。从这个角度来看,控制器似乎是为其构造数据的自然位置,尽管渲染应该发生在视图中。为了使其在视图中完全生成,您需要公开有关视图正在调用哪些控制器操作的详细信息,或者拥有固定的每个操作视图模型,以便可以预先计算每个操作的面包屑。将计算面包屑的逻辑移至视图本身似乎违反了 MVC 中的关注点分离,并且可能会妨碍对不同操作重用视图,这将违反 DRY> 原则。

在我看来,为面包屑生成数据是控制器中的一个横切关注点,即,无论使用 url 构造面包屑数据的操作如何,您都有一些共享代码运行。还有一些共享视图代码,它们获取控制器提供的数据并将其呈现为与设计一致。

请注意,我是从纯粹的架构角度来讲的。我对 CakePHP(或其他 PHP 框架)不够熟悉,甚至无法判断您对它的观察是否正确。从模式的角度来看,将其放入控制器似乎是正确的做法。然而,在给定的实现中,违反该模式可能是有意义的。

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.

小女人ら 2024-09-13 02:21:05
$this->Html->addCrumb('Home', '/pages/home');
$this->Html->addCrumb('Contacts', '/pages/contacts');

echo $this->Html->getCrumbs('»', 'StartText');
$this->Html->addCrumb('Home', '/pages/home');
$this->Html->addCrumb('Contacts', '/pages/contacts');

echo $this->Html->getCrumbs('»', 'StartText');
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文