如何使用之前在 Yii 或鼻涕虫麻烦中操作


How to use beforeAction in Yii or slug troubles

Yii-jedis!

我正在做一些旧的Yii项目,必须为它们添加一些功能。Yii 是相当合乎逻辑的框架,但它有一些我无法理解的东西。也许我还没听懂怡威。所以我将逐步描述我的问题。对于不耐烦 - 最后简要提问。

简介:我想在我的项目中添加人类可读的 URL。现在,网址如下所示:www.site.com/article/359
我希望它们看起来像这样:www.site.com/article/how-to-make-pretty-urls
非常重要:旧文章必须在旧格式的URL上可用,而新文章必须在新URL上可用。

第 1 步:首先,我更新了 config/main 中的重写规则.php:

'<controller:'w+>/<id:'S+>' => '<controller>/view',

我已经在文章表中添加了新的文本网址列。因此,我们将在此处存储新文章的人类可读部分网址。然后我用文本网址更新了一篇文章进行测试。

第 2 步:应用程序在行动中显示文章文章控制器视图,所以我在那里添加了以下代码来预处理 ID 参数:

if (is_numeric($id)) {
    // User try to get /article/359
    $model = $this->loadModel($id); // Article::model()->findByPk($id);
    if ($model->text_url !== null) {
        // If article with ID=359 have text url -> redirect to /article/text-url
        $this->redirect(array('view', 'id' => $model->text_url), true, 301);
    }
} else {
    // User try to get /article/text-url
    $model = Article::model()->findByAttributes(array('text_url' => $id));
    $id = ($model !== null) ? $model->id : null ;
}

然后开始遗留代码:

$model = $this->loadModel($id); // Load article by numeric ID
// etc

工作得很好!但。。。

第 3 步:但是我们有很多使用 ID 参数的操作!我们要做什么?使用该代码更新所有操作?我觉得这很丑陋。我找到了CController::beforeAction方法。看起来不错!所以我声明 beforeAction 并将 ID 预处理放在那里:

protected function beforeAction($action) {
    $actionToRun = $action->getId(); 
    $id = Yii::app()->getRequest()->getQuery('id');
    if (is_numeric($id)) {
        $model = $this->loadModel($id);
        if ($model->text_url !== null) {
            $this->redirect(array('view', 'id' => $model->text_url), true, 301);
        } 
    } else {
        $model = Article::model()->findByAttributes(array('text_url' => $id));
        $id = ($model !== null) ? $model->id : null ;
    }
    return parent::beforeAction($action->runWithParams(array('id' => $id)));
}

是的,它适用于两种 URL 格式,但它执行 actionView 两次并显示页面两次!我能用这个做什么?我完全糊涂了。我是否选择了正确的方法来解决问题?

简而言之:我可以在执行任何操作之前处理 ID(GET 参数),然后仅使用修改的 ID 参数运行请求的操作(一次!

最后一行应该是:

return parent::beforeAction($action);

还要问你,我没有得到你的步骤:3。

正如你所说,你有很多控制器,你不需要

在每个文件中编写代码,所以你正在使用 beforeAction:但是您只有与所有控制器的文章相关的text_url??

$model = Article::model()->findByAttributes(array('text_url' => $id));

===== 更新的答案 ======

我已经更改了此功能,立即检查。

如果$id不是数字,那么我们将使用模型找到它的 id 并设置 $_GET['id'],因此在进一步的控制器中它将使用该数字 id。

protected function beforeAction($action) {          
    $id = Yii::app()->getRequest()->getQuery('id');
    if(!is_numeric($id)) // $id = how-to-make-pretty-urls
    {
        $model = Article::model()->findByAttributes(array('text_url' => $id));
        $_GET['id'] = $model->id ; 
    }
    return parent::beforeAction($action);
}

抱歉,我没有仔细阅读所有内容,但您是否考虑过使用此扩展程序?