正在路由中映射数据库中的数据块


Mapping slugs from database in routing

我必须支持项目的url友好结构。

有多个带有段塞列的表,在cakepp中,我如何才能以最有效的方式将段塞路由到控制器。

起初,我在检查表中是否存在鼻涕虫,如果鼻涕虫存在,请使用以下路线:

    $c = TableRegistry::get('cateogories');
    $result= $c->find()->select(['id'])->where(['url'=>$slug])->toArray();
    if(count($result) > 0) {
        $routes->connect(
            '/:slug',
            ['controller' => 'Categories', 'action' => 'index', 'id' => $result[0]['id']]
        );
    }

问题是,我有多个像上面这样的检查,即使路由之前匹配,每个检查都在运行(不需要运行,所以会调用额外的查询)。

那么,我如何添加某种条件语句,以便它只检查路由是否匹配(如果之前的路由都不匹配)。

我建议使用一个处理此问题的自定义路由类。虽然你可以查询路线文件中的数据,但这是

  • 对测试不太友好
  • 不太干燥
  • 反向路由不安全

后一点意味着,当没有连接所有路由时,试图从路由数组中为未连接的路由生成URL可能会触发异常,或者匹配错误的路由。

使用自定义路由类,您只需在连接路由时在选项中传递模型,在解析URL后的路由类中,查询给定段塞的模型,并相应地返回false或解析的数据。这真的很简单,只要看看现有的路由类是做什么的。

这是一个非常基本的例子,应该是非常自我解释的。

src/Routing/Route/SlugRoute.php

namespace App'Routing'Route;
use Cake'Routing'Route'Route;
use Cake'ORM'Locator'LocatorAwareTrait;
class SlugRoute extends Route
{
    use LocatorAwareTrait;
    public function parse($url)
    {
        $params = parent::parse($url);
        if (!$params ||
            !isset($this->options['model'])
        ) {
            return false;
        }
        $count = $this
            ->tableLocator()
            ->get($this->options['model'])
            ->find()
            ->where([
                'slug' => $params['slug']
            ])
            ->count();
        if ($count !== 1) {
            return false;
        }
        return $params;
    }
}

本例假设在控制器中,您将使用段塞来检索记录。如果您想要传递ID,那么您可以获取ID并将其传递到解析的数据中,而不是使用count(),例如:

$params['pass'][] = $id;

然后,它将作为控制器操作的第二个参数传递。

routes.php

$routes->connect(
    '/:slug',
    ['controller' => 'Articles', 'action' => 'view'],
    [
        'pass' => ['slug'],
        'routeClass' => 'SlugRoute',
        'model' => 'Articles'
    ]
);
$routes->connect(
    '/:slug',
    ['controller' => 'Categories', 'action' => 'view'],
    [
        'pass' => ['slug'],
        'routeClass' => 'SlugRoute',
        'model' => 'Categories'
    ]
);
// ...

这将首先检查Articles模型,然后检查Categories模型等,并在其中一条路由找到给定段塞的记录后停止。


另请参见

  • 食谱>路线>自定义路线类别
  • API>''Cake''Routing''Route::parse()
  • 源>''Cake''Routing''Route