【问题标题】:CakePHP 2.2.4: Working with Multiple Slugs In RouteCakePHP 2.2.4:在路由中使用多个 Slug
【发布时间】:2013-03-25 20:28:23
【问题描述】:

我没有看到涉及路线中多个 slug 的问题。

我有一个名为“教师”、“课程”和“科目”的表格。每个都有一个名为“快捷方式”的字段。

如何从如下网址中路由和提取正确的 Teacher.id、Course.id 和 Subject.id:

http://www.domain.com/bowlerae/grade-5/math

其中“bowlerae”是 Teacher.shortcut,“grade-5”是 Course.shortcut,“math”是 Subject.shortcut。

我不确定最初如何路由,如何提取每 3 个元素的 ID(我会在 AppController 中执行此操作还是在我需要的每个单独的控制器中执行此操作?)以及如何构建与反向路由兼容的链接和分页。另外,“shortcut”字段是否需要为每个表具有唯一的名称,例如“teacher_slug”、“course_slug”、“subject_slug”?

现在,我正在将 3 个模型中的每一个加载到我的 routes.php 中并查询以获取每个模型的相应 ID(如果 URL 的该部分存在),然后将这些值传递给控制器​​。但正如你可以想象的那样,它会耗费大量资源。

其他问题/疑虑(针对 AD7six 和其他人)

如果我想要这样的网址

http://www.domain.com/bowlerae

指向教师的主页,或类似这样的 URL

http://www.domain.com/bowlerae/grade-5

要指向课程的主页,我会有如下路径

Router::connect(
    '/:teacher', 
    array('controller' => 'teachers', 'action' => 'view'),
    array(
        'teacher'   => '[a-z0-9]{1}([a-z0-9\-]{2,}[a-z0-9]{1})?',
        'pass' => array('teacher')
));

对于教师,以下对于课程

Router::connect(
    '/:teacher/:course', 
    array('controller' => 'courses', 'action' => 'view'),
    array(
        'teacher'   => '[a-z0-9]{1}([a-z0-9\-]{2,}[a-z0-9]{1})?',
        'course'   => '[a-z0-9]{1}([a-z0-9\-]{2,}[a-z0-9]{1})?',
        'pass' => array('teacher', 'course')
));

我担心的是,如果有人导航到类似的 URL 会怎样?

http://www.domain.com/account 其中 account 是有效的控制器,但不是有效的教师

http://www.domain.com/bowlerae/students 其中学生是有效的控制者,但不是有效的课程

我将如何处理这些情况?我尝试使用这样的重定向方法...

TeachersController.php

public function view($tSlug = null) {
    $this->Teacher->id = $this->Teacher->findByShortcut($tSlug);

    if (!$this->Teacher->exists()) {
                  $this->Session->setFlash('This teacher does not exist');
                  $this->redirect(array('controller' => $tSlug));
    }
            else{
            // do this
            } // end else if teacher exists
    } 

我希望它路由以下 URL

http://www.domain.com/account 到帐户控制器,但将其路由到

http://www.domain.com/account/index,正确的帐户控制器和正确的索引操作,但它在 URL 的末尾附加了“/index”。

以我现在的路由方式,它正在尝试访问课程控制器,所以我向课程控制器添加了相同的重定向方法,就像这样......

CoursesController.php

public function view($tSlug = null, $cSlug = null) {
    $this->Teacher->id = $this->Teacher->findByShortcut($tSlug);
    $this->Course->id = $this->Course->findByShortcut($cSlug);


    if (!$this->Teacher->exists()) {
                  $this->Session->setFlash('This teacher does not exist');
                  $this->redirect(array('controller' => $tSlug, 'action' => $cSlug));
    }
    elseif (!$this->Course->exists()) {
                  $this->Session->setFlash('This course does not exist');
                  $this->redirect(array('controller' => $tSlug, 'action' => $cSlug));
    }
            else{
            // do this
            } // end else if everything is fine
    } 

很遗憾,我收到一条错误消息,指出重定向永远不会结束。

另外,我已经为这样的 URL 创建了路由(如果没有教师、课程或主题),但它们可能不正确。

【问题讨论】:

    标签: cakephp routing routes


    【解决方案1】:

    针对 db 测试所有请求以查看它们是否匹配路由是一个非常糟糕的主意。

    将逻辑放入控制器中

    一个简单的方法是创建一个路由ala:

    Router::connect('/*', array('controller' => 'x', 'action' => 'y'));
    

    或者更具体一点:

    Router::connect(
        '/:teacher/:course/:subject', 
        array('controller' => 'x', 'action' => 'y'),
        array('pass' => array('teacher', 'course', 'subject')
    );
    

    并确保首先声明您使用的所有其他路由。然后像这样简单地创建一个控制器动作:

    XController extends AppController {
    
        public $uses = array('Teacher');
    
        public function y($tSlug, $cSlug, $sSlug) {
            $teacher = $this->Teacher->findBySlug($tSlug);
            ...
        }
    
    }
    

    限制路由元素

    使用route validation,您可以限制匹配给定路由元素的内容,例如,如果只有 5 位教师,您可以通过确保以他们的 slug 开头来阻止任何其他 url:

    Router::connect(
        '/:teacher/:course/:subject', 
        array('controller' => 'x', 'action' => 'y'),
        array(
            'teacher' => 'rita|sue|bob|larry|mo',
            'pass' => array('teacher', 'course', 'subject')
    );
    

    如果您想从 db 中读取教师的 slug - 缓存 db 查询,请不要在所有请求中从您的路由文件中的 db 中读取。

    在你的路线中放置一些固定的东西

    使用没有固定字符串的路由意味着任何带有 3 个路径段的 url 都将匹配该路由 - 在路由中放置一些固定的东西可能不太容易出错,这样您就可以确定请求实际上是对于教师、课程、科目组合

    Router::connect('/anything/*', array('controller' => 'x', 'action' => 'y'));
    

    这避免了对任何“此 url 是否与此路由匹配?”的需要。逻辑 - 有或没有。

    【讨论】:

    • 尝试实施您的建议,我有一个问题/疑虑,更新了原始问题。
    • 现在检查 :) 我要写的东西比我想象的要多得多。 (另外我在工作,所以当有人路过时我会不断最小化屏幕哈哈)
    • How would I handle these instances? - 显然您的问题不是您最初提出的问题 - 您需要查看路线的顺序,最后让您的老师包罗万象,如有必要,首先为所有其他网址定义明确的路线。对于您之前实现的 all 请求,需要与 db 交谈是一个非常糟糕的主意。
    猜你喜欢
    • 2012-02-09
    • 2011-09-07
    • 2016-05-11
    • 2011-07-03
    • 1970-01-01
    • 2011-10-06
    • 2020-12-03
    • 2011-07-23
    • 2012-02-22
    相关资源
    最近更新 更多