Yii-Jedis!
I am working on an old Yii project and should add some features to them. Yii is a pretty logical structure, but I have some things that I could not understand. Perhaps I have not understood Yii-way yet. Therefore, I will describe my problem step by step. For impatience - a short question at the end.
Introduction: I want to add human-readable URLs to my project. The urls now look like this: www.site.com/article/359
And I want them to look like this: www.site.com/article/how-to-make-pretty-urls
Very important: old articles should be available on old format URLs, and new ones on new URLs.
Step 1: First, I updated the rewrite rules in config / main.php:
'<controller:\w+>/<id:\S+>' => '<controller>/view',
And I added a new texturl column to the article table. Thus, we will store here the human-readable parts of the URL for new articles. Then I updated one article with text for tests.
Step 2: The application displays the articles in the actionView of the ArticleController control, so I added this code there for the preproccessing ID parameter:
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 ; }
And then run the legacy code:
$model = $this->loadModel($id);
It works great! But...
Step 3: But we have a lot of actions with the ID parameter! What should we do? Refresh all actions with this code? I find this ugly. I found the CController :: beforeAction method . Looks good! So I declare preAccess and place the preprocess ID there:
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))); }
Yes, it works with both URL formats, but it executes actionView TWICE and shows the page twice! What can i do with this? I am completely confused. Have I decided to solve my problem correctly?
In short: Can I request an identifier (GET parameter) before performing any action, and then run the requested action (once!) With only the ID parameter changed?