Marian Zburlea
Marian Zburlea

Reputation: 9407

Yii advanced url rewrite

pay attention to that ANYTHING_ELSE So, I have my controllers and actions that I want to behave as normal in response to examples like this:

// for UserContoller with actionList and actionEdit
user/list
user/edit/25

But for everything that doesn't fall under specific controllers and actions i want them to fall under one default controller and action like: BlogController and actionView. That is where ANYTHING_ELSE comes.

// ANYTHING_ELSE can be:
this-is-a-test-page
this/is/another/page/with/lots/of/slashes
this-has-extension.html


'urlManager' => array(
  'urlFormat' => 'path',
  'showScriptName' => false,
  'rules' => array(
    '<controller:\w+>/<id:\d+>' => '<controller>/view',
    '<controller:\w+>/<action:\w+>/<id:\d+>' => '<controller>/<action>',
    '<controller:\w+>/<action:\w+>' => '<controller>/<action>',
    'ANYTHING_ELSE' => 'blog/view',
   ),
),

Upvotes: 9

Views: 11607

Answers (3)

Marian Zburlea
Marian Zburlea

Reputation: 9407

I shall explain step by step how to get this working.

Step 1 - Create an Yii web app

Navigate to your Yii framework path in your console and create a new webapp. In my case I used this in my console:

cd c:\zeus\yii-1.1.10.r3566\framework
yiic webapp c:\zeus\www\yiiblog

where c:\zeus\yii-1.1.10.r3566\framework is my path to Yii php framework and c:\zeus\www\yiiblog is the path to my Yii webapp test folder

Stept 2 - fake my domain to dev.yiiblog.com

Go to C:\Windows\System32\drivers\etc and edit your hosts file by adding this line:

127.0.0.1 dev.yiiblog.com

Step 3 - alter apache httpd.conf file

<VirtualHost *:80>
    DocumentRoot "c:/zeus/www/yiiblog"
    ServerName dev.yiiblog.com
    ErrorLog "logs/dev.yiiblog.com-error.log"
    CustomLog "logs/dev.yiiblog.com-access.log" common
</VirtualHost>

and restart apache service. I used in my windows console:

net stop apache
net start apache

where my Apache 2 service is named "apache" not "apache2.2" like the default one.

Step 4 - create a database and configure a database connection into Yii

I've created a database yiitest and a user yiitest. Then I opened my Yii configuration file located ad /protected/config/main.php and edited the connection to MySQL:

'db'=>array(
  'connectionString' => 'mysql:host=localhost;dbname=yiitest',
  'emulatePrepare' => true,
  'username' => 'yiitest',
  'password' => 'password',
  'charset' => 'utf8',
),

Step 5 - download dburlmanager Yii extension

Go to Yii dburlmanager, download the Yii dburlmanager extension http://www.yiiframework.com/extension/dburlmanager/ and extract it to your /protected/extensions folder

Step 6 - Create MySQL database tables and add dummy data

CREATE TABLE IF NOT EXISTS `articles` (
  `seoURL` varchar(100) NOT NULL
) ENGINE=InnoDB;

INSERT INTO `articles` (`seoURL`) VALUES
('first-post'),
('another-post'),
('post/value'),
('website/page1');

CREATE TABLE IF NOT EXISTS `pages` (
  `seoURL` varchar(100) NOT NULL
) ENGINE=InnoDB;

INSERT INTO `pages` (`seoURL`) VALUES
('page-first-post'),
('page-another-post'),
('page/post/value.html'),
('page-website/page1');

Step 7 - Create your Yii custom Controllers

Create under /protected/controllers folder two php files named ArticleController.php and PageController.php:

ArticleController.php content:

<?php
/**
 * @filename ArticleController.php
 */

class ArticleController extends CController {
  public function actionView() {
    $this->render('view', array(
      'article' => isset($_GET['article'])?$_GET['article']:'',
    ));
  }
}

PageController.php content:

<?php
/**
 * @filename PageController.php
 */
class PageController extends CController {
  public function actionView() {
    $this->render('view', array(
      'page' => isset($_GET['page'])?$_GET['page']:'',
    ));
  }
}

Step 8 - create your custom Yii views

Create your view files corresponding to those controllers above with the path /protected/views/article/view.php and /protected/views/page/view.php:

Article view content:

<h1>Article View Test</h1>
<br />
<?php
    if (isset ($article)) echo "article: $article";
?>

Page view content:

<h1>Page View Test</h1>
<br />
<?php
    if (isset ($page)) echo "page: $page";
?>

Step 9 - add custom Yii url rules

Open again your main.php Yii config file and set your urlManager to something similar to:

'urlManager'=>array(
  'urlFormat'=>'path',
  'class'=>'ext.DbUrlManager.EDbUrlManager',
  'connectionID'=>'db',
  'rules'=>array(
    '<article:[\w\/.-]+>'=>array(
      'article/view',
      'type'=>'db',
      'fields'=>array(
        'article'=>array(
          'table'=>'articles',
          'field'=>'seoURL'
        ),
      ),
    ),

    '<page:[\w\/.-]+>'=>array(
      'page/view',
      'type'=>'db',
      'fields'=>array(
        'page'=>array(
          'table'=>'pages',
          'field'=>'seoURL'
        ),
      ),
    ),

    '<controller:\w+>/<id:\d+>' => '<controller>/view',
    '<controller:\w+>/<action:\w+>/<id:\d+>' => '<controller>/<action>',
    '<controller:\w+>/<action:\w+>' => '<controller>/<action>',
  ),
  'showScriptName'=>false,
),

Step 10 - create .htaccess file

Create a .htaccess file under your web app root and etid its content to:

Options +FollowSymLinks
IndexIgnore */*
RewriteEngine on

# if a directory or a file exists, use it directly
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d

# otherwise forward it to index.php
RewriteRule . index.php

Step 11 - test your SEO Friendly URLs

dev.yiiblog.com/first-post
dev.yiiblog.com/page-first-post

etc

Have fun creating awesome blogs or other web apps with complete url managing power.

Upvotes: 11

Alexander Palamarchuk
Alexander Palamarchuk

Reputation: 879

If I've realized you correctly, you may use something like this:

  'rules' => array(
    //You should define all the controllers exactly:
    '<controller:user|archive|office>/<action:\w+>' => '<controller>/<action>',
    //Or more complicated rule:
    '<lang:(es|it|en)>/(turismo|visita|travel)/<slug:>' => array('visit/page', 'urlSuffix' => '.html'),

    //After that you can process all remaining urls as you want:
    '<alias:[\w\d\-_\/]+>' => array('blog/view', 'urlSuffix' => '.html'),
  ),

And the controller:

class BlogController extends Controller
{
    public function actionView($alias)
    {
        echo $alias;
    }
}

Upvotes: 3

acorncom
acorncom

Reputation: 5955

Read my article on how to handle that specific scenario (plus other things) with Wordpress: http://www.yiiframework.com/wiki/322/integrating-wordpress-and-yii-still-another-approach-using-yii-as-the-router-controller/

In essence, in order to handle a default like that (and hand it off to a different system), tr easiest way to do it is to override Yii's exception handling system, catch 404 errors and hand those to your blog controller.

If you send people to your blog controller by setting your controller action as an error handler, Yii sends a 404 error header (even if your properly handle the error). Yes, I've dug into this a lot. No, I don't believe there is a simpler answer :-). I'd love to know if you do find something simpler ...

Upvotes: 2

Related Questions