6

Yii-ジェダイ!

私はいくつかの古い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列を追加しました。したがって、新しい記事のために、ここに人間が読める形式のURLを保存します。次に、テスト用にtexturlを使用して1つの記事を更新しました。

ステップ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を2回 実行し、ページを2回表示します。これで何ができますか?私は完全に混乱しました。問題を解決する正しい方法を選択しましたか?

簡単に言うと、アクションを実行する前にID(GET-parameter)を処理してから、IDパラメーターのみを変更して要求されたアクションを(1回!)実行できますか?

4

2 に答える 2

13

最後の行は次のとおりです。

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);
}
于 2012-08-08T06:28:10.770 に答える
2

申し訳ありませんが、すべてを注意深く読んだわけではありませんが、この拡張機能の使用を検討しましたか?

于 2012-08-08T07:23:27.390 に答える