UrlManager rules for static pages in subdirectories

Hi,

I try to create URL rules to match static pages located in subdirectories of /site/pages.

For example, I have protected\views\site\pages\subdir1 with php scripts inside.

I want to create a rule to match any file inside that dir.

I can’t find out.

This rule works:


'subdir1/script1'=>array('site/page', 'defaultParams'=>array('view'=>'subdir1.script1')),

but I’d like a general rule because there will be many files so I would not have to write a rule for each file.

Thanks a lot.

I’ve finally found the solution:


'subdir/<scriptname>:[-\w]+>'=>'site/page/view/subdir.<scriptname>',

If We have such files:

/protected/views/site/pages/subdir/bla-bla.php

/protected/views/site/pages/subdir/whatever.php

calls to

http://mysite/subdir/bla-bla will route to site/page/view/subdir.bla-bla

http://mysite/subdir/whatever will route to site/page/view/subdir.whatever

and so on

The next step would be to find something completely generic for anything inside /protected/views/site/pages/ because with this solution, we need one rule by subdir, which is already better than one rule for each file in each subdir…

One solution that my co-worker and I came up with is that we used the missing action method within the CController and overridden it in the "protected/components/Controller.php" to intercept static pages and dynamically load static pages after the action. I.E. "url/module/controller/action".


 public function missingAction($actionID) {

        $views = $this->getViewPath();

        if (Yii::app()->file->set($views . "/" . $actionID . ".php")->exists) {

            $this->render($actionID);

        } else {

            throw new CHttpException(404, Yii::t('yii', 'The system is unable to find the requested action "{action}".', array('{action}' => $actionID == '' ? $this->defaultAction : $actionID)));

        }

    }

The


Yii::app()->file->set($views . "/" . $actionID . ".php")->exists

is from the Cfile extension.

The url rules that we used were:


'rules' => array(

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

                '<controller:\w+>/<action:\w+>/<id:\d+>' => '<controller>/<action>',

                '<controller:\w+>/<action:\w+>' => '<controller>/<action>',

                'site/page/<view:\w+>' => 'site/page',

            ),

We decided to do this because we felt that adding more and more rules for the web site would create a performance issue.

I hope this helped.

Thanks for your answser.

That’s interesting but I wanted to achieve that with a CUrlRule because it seemed “cleaner” to me.

In case I can’t find a rule and to save some time, I might use your solution, replacing


if(Yii::app()->file->set($views . "/" . $actionID . ".php")->exists)

with the good old file_exists


if(file_exists($views . "/" . $actionID . ".php"))

And this:




'rules' => array(

                'site/page/<view:\w+>' => 'site/page',

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

                '<controller:\w+>/<action:\w+>/<id:\d+>' => '<controller>/<action>',

                '<controller:\w+>/<action:\w+>' => '<controller>/<action>',

            ),



instead of




'rules' => array(

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

                '<controller:\w+>/<action:\w+>/<id:\d+>' => '<controller>/<action>',

                '<controller:\w+>/<action:\w+>' => '<controller>/<action>',

                'site/page/<view:\w+>' => 'site/page',

            ),



How do you create the link to the subdirectories?

When I use CHtml::link to build it like this…

CHtml::link(“test”, array(’/site/page’, ‘view’=>‘subdir/whatever’))

I get a link like this…

/site/page/subdir%2Fwhatever

instead of the following, which works

/site/page/subdir/whatever

I would prefer to use ::link and ::normalizeUrl so that if I change the paths, the links won’t break.

This is for any who still have issues with static pages in subdirectories.

First, go to your controller actions & add an action to render static pages from subdirectory, like illustrated below.


	

        public function actions()

	{

		return array(

			

			// page action renders "static" pages stored under 'protected/views/site/pages'

			// They can be accessed via: index.php?r=site/page&view=FileName

			'page'=>array(

				'class'=>'CViewAction',

			),


			'directory1'=>array(

				'class'=>'CViewAction',

				'basePath' => 'pages/directory1'

			),

			

			'directory2'=>array(

				'class'=>'CViewAction',

				'basePath' => 'pages/directory2'

			),

		);

	}



Then head over to views/site/pages & create the two directories under the pages folder

eg /views/site/pages/directory1 …

create you scripts & places them here. You can create you urls like so


 array('label'=>'Page Title', 'url'=>array('/site/directory1', 'view'=>'file-name-of-static-page')),

For URL Rules you do something like this




    'urlManager'=>array(

			'urlFormat'=>'path',

			'appendParams'=>true,

			'rules'=>array(

				'/'=>'site/index',	

			   	'<view:[\w\-]+>'=>'site/page',

			   	'/directory1/<view:[\w\-]+>'=>'site/directory1',

			   	'/directory2/<view:[\w\-]+>'=>'site/directory2',

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

				'<controller:\w+>/<action:\w+>/<id:\d+>'=>'<controller>/<action>',

				'<controller:\w+>/<action:\w+>'=>'<controller>/<action>',

			),

			'showScriptName' => FALSE,

			'caseSensitive'=>false, 

		), 



in the end you will have the following link -


http://www.example.com/directory1/static-page-name