How to direct dynamic URLs to a specific controller

Hi everyone,

Have another couple questions so any help would be appreciated. Im building an app for a small business and its employees and each employee will have its own page in which I would like it to format as such:

www.domain.com/employeename

where the employee name would go to a specific controller/action. I have two questions:

  1. How can I do this such that it does not conflict with any other controllers (if for example an employees name just happens to be the name of a existing controller or even future controller)? The obvious choice is to do a check beforehand but this doesnt prove to be future proof

  2. How can I build the route for this? Im thinking some type of hook where if the controller is not found, it would automatically send it to the default controller where it would search for the employee’s name and if not found then redirect to a 404 message. Or maybe use the magic _call method if the controller is not found

Thanks in advance for any responses

I think better solution is to use one single user controller. Something like this:


'rules' => array(

   '<username:[A-z]+>' => 'user/view',

),

Then in your controller you can load the user data from db with help of $_GET[‘username’]. Also if the username can not be found in db, you may redirect like you noted.

  1. Why do you think that’s not future proof? You just need to take care to create another rule (or a small set of rules) for each new controller you might add later. Worst thing that can happen is, that the route for the new controller will be used as username instead. You’ll find this error pretty fast when developing i think.

  2. Maybe i misunderstand your question. Do you mean, every employee should have it’s own controller/action? If so: why?

Thanks for the responses so far.

@Mike

An employee’s home page will be processed through the following controller/action: user/index. So basically, the process would flow as so if I typed in www.domain.com/firstNameLastName

  1. Yii looks for the following controller: firstNamelastName

  2. No controller is found which would usually lead to a 404 error, however, I would like to add a hook so the request is sent to actionIndex of the UserController

  3. The index method would search the DB for the user firstNamelastName and if found, would create the home page for that employee. Otherwise, it would continue with a 404.

From my understanding, Y!!'s recommendation follows a similar process except the actionIndex of the UserController would be requested first with the the employee’s name contained within a GET variable (after configuring the rule using the URLManager).

Ive just been wondering what approaches are recommended.

Y!!'s approach is fine. I’d also do it that way. You only need to make sure to add any other URL rules before this catch-all rule.

If you have something like

www.domain.com/anyletters

how would you or your program know if "anyletters" is a firstlastname or something else like a model, a static page…

In my opinion you have to set some rule for the firstlastletter… there are many options but it has to be uniqe so that you can make a rule of it in the urlmanager.

for example: firstname.lastname (if there is a dot that represents users)

                   user/firstnamelastname (this way you know that all after user/ is the username)

or if you just want the firstnamelastname to be after the domain… then you have to ensure that all other URLs have some different format

and you can use something like:




        'urlManager'=>array(

            'urlFormat'=>'path',

            'showScriptName'=>false,

            'rules'=>array(

                '<uname:>'=>'user/index',

            )

        ),



not tested, but now in the user/index action you have the GET parameter uname.

@mdomba:

You don’t need a rule for the names, if you have a strict schema for all other pages. As long as these rules come first, everything’s fine.


'articles/<id:\d+>' => 'article/view',

'category/<name:\w+>' => 'category/list',

//...more rules

'<username:\w+>' => 'user/index',



This reads like: "If nothing else matches, it must be a username". In your UserController you then can look for that user and as a last fallback show some not found message if no user was found by that name.

If you read my post you will see that I have written just that for the last option :)

Oh sorry, misunderstood that. :)

Did you ever get this working? I’m trying to do something similar but it’s unclear the steps that I would go through and the code needed for it to work. If the index method is always called, what’s the code you would use to capture the UserName and routing it?

I got this working using a number of different methods. I’m going to do some benchmarking later this week to see if one performs better than the others. The easiest method to do this without even touching the URLManager is to:

  1. Override the createController function in CWebApplication (extend it so you do not have to touch the core) where the app defaults to the user controller if no controller is found.

  2. In your UserController, override the missingAction function to implement the logic to look up the username in the DB. The function will pass in one parameter that will be the requested username. If found, I create an instance of the appropriate Action class that contains my logic for creating the profile page for the user by using the createComponent function (more specifically, something like Yii::createComponent($par1, $par2, $par3)->run()). If nothing is found, I just redirect it to a 404 page.

That is a general idea of one way to do it.

Thanks for the reply. I was able to get this working using the missingAction override at the main site level. However, now I have a module called blog. yii recognizes the route “blog” and sends me to the default page in the blog module. If I access any of the valid actions/view they all work. I need to be able to use the missingAction override in my module DefaultController but whenever I put in an incorrect route that doesn’t exist the missingAction overried in the DefaultController never fires. It automatically falls back to the SiteController for my main site. How can I get the missingAction override in the module to fire?