【问题标题】:How to use beforeAction in Yii or slug troublesYii 中如何使用 beforeAction 或 slug 麻烦
【发布时间】:2012-08-05 04:53:46
【问题描述】:

绝地武士!

我正在开发一些旧的 Yii 项目,并且必须向它们添加一些功能。 Yii 是一个非常合乎逻辑的框架,但它有一些我无法理解的东西。也许我还没有理解 Yii-way。因此,我将逐步描述我的问题。对于不耐烦的人 - 最后简要提问。

简介:我想将人类可读的 URL 添加到我的项目中。 现在 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',

我在文章表中添加了新的 texturl 列。因此,我们将在 human-readable-part-of-url 中存储新文章。然后我用 texturl 更新了一篇文章进行测试。

第 2 步: 应用程序在 ArticleControlleractionView 中显示文章,因此我在此处添加了用于预处理 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 TWICE 并显示页面两次!我能用这个做什么?我完全糊涂了。我是否选择了正确的方法来解决我的问题?

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

【问题讨论】:

  • 你能用空白参数试试吗.. return parent::beforeAction();什么是输出?
  • @VibhaJ parent::beforeAction() 返回 404 和 parent::beforeAction($action) 返回 404

标签: php yii


【解决方案1】:

最后一行应该是:

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);
}

【讨论】:

  • 没有。我在一个控制器 (ArticleController) 中有许多带有 $id 参数的操作。现在,这些操作将数字 id 作为参数......我所需要的只是预处理这个 id(来自 GET),然后使用它运行操作。
  • 您是否检查了我在上面添加的更新答案和 beforeAction 函数?
  • 旧动作代码需要使用数字 $id 参数运行!因此,首先我们必须将 $id 从 slug 格式“转换”为数字(通过 slug 加载模型并返回 id)。如果我们使用:return parent::beforeAction($action); 操作将在 $id 参数不变的情况下执行。
  • 让你的 $id 是 'how-to-make-pretty-urls' 然后上面的代码将从数据库中获取依赖的文章 id 并覆盖 $id 值(这段代码会这样做:$_GET[' id'] = $model->id ;) 到文章 id。因此,在文章控制器中,即使您在 url 中有“how-to-make-pretty-urls”,您的控制器也会忽略它并使用覆盖的数字 ID。
  • 是的,您的代码有效,谢谢!最有用的是$_GET['id'] = $model-&gt;id ; - 我完全理解 beforeAction+action 的工作原理!
【解决方案2】:

抱歉,我没有仔细阅读,但您考虑过使用this extension吗?

【讨论】:

  • 如果我以前看过它,也许我会选择它来完成我的任务:)
  • 永远不会太晚。我知道扩展程序的作者 - 你应该“购买”它;-)
猜你喜欢
  • 1970-01-01
  • 2020-02-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-07-01
  • 2020-05-06
  • 2021-01-01
  • 1970-01-01
相关资源
最近更新 更多