Friendly URL's and extra text in URL before the controller ident

Hi!

Suppose I would like to create a blog site for millions of users :) I would like to use friendly urls and espacially friendly for the users. So, calling a specific blog by

http://blog.site.com/users_blog_ident

would be what I am lurking for. Indeed, users_blog_ident is somewhat virtual, as this is only the selection of the specific blog item - but all just one application. But every time a new user registers for his blog, this ident should be working out of magic. No configuration changes or adding of apache rewrites should be necessary.

My problem now is that I'm trying to convince the urlManager to create url's throughout the application by keeping that identifier, whatever it points to, i.e.

http://blog.site.com…ticle/read/id/3

Also, routes need to understand that the first item in the requestURI is a parameter already and the usual route/parameter stuff follows. Extra trick: I dont want to change the baseURL, as the images or assets folders will stay where they are.

Could this be done without changing the urlManager code? Maybe using behaviors?

Any ideas?

Cheers,

Hein

Exactly the same problem here ! I want to use www.mydomain.tld/username/controller/action(/id)

I have added two new routes at the end of my urlManager config :

It give me the ability to use $_GET["account"] to check the account but my biggest problem is that I need to add this var at the beginning of each of my URL. Maybe using a subdomain would be easier ?

Any help much appreciated !

Uh!

At least that is a start! I thought that patterns work in both ways, so help to figure out the route and the other way round do something when you call createUrl. I will have a deeper look on that, maybe there is a way towards a solution.

Cheers,

Hein

I have another problem with this URL system because I don't understand how I can scope auth to the account :frowning:

Hi!

I also see another problem - I dont know where to put general initialisation stuff in my application.

For now, I added a preloaded component AppInit, that registers a handler for Yii::app()->onbeginRequest. Here, I would load the configuration requested by the virtual user ident.

The problem is that the urlManager parses the request uri after onbeginRequest was fired. So while the handler is working, no $_GET parameters are available. Only the controller knows about them, but thats too late.

Is there a better place, sometimes after the urlManager did its work, where I could put the application init code?

Would it be possible to force the urlManager to parse the uri before onbeginRequest is fired?

Cheers,

Hein

Hi !

For the moment I have an AppController which check the $_GET["account"] and also add security (another problem !) to all the controller which inherit this AppController.

It's a design pattern that I was using in a subdomain account rails based app and which works pretty well.

Security is really a big deal because I need my user session to be scoped to the account and I don't know how to manage this.

Regards,

Raphael

Hi!

Using your AppController approach seems to be a nice and only way out of this.

I was digging into replacing the urlManager by a derived and extended version of it, so I could at least leave the original untouched.

But I think CWebApplication->registerCoreComponents does it the hard way and you cannot make it load another object without hacking the code. So define urlManager as a component in the config will not help, as the config is read after registerCoreComponents was called.

Please, correct me if I'm wrong - I want to be wrong here :wink:

Cheers,

Hein

@HeinMuck: You should put those code in the init() method of your base controller class. Also, if you want to replace urlManager with your own, you can do so by configuring it in app config.

@raphael: So your problem is to prefix every rule with an account parameter? How many rules do you have?

@qiang : I may have many controllers and actions available under account. With the rules I wrote above I'm able to get this running but I need to pass the account ID to each of my call to link or other. Maybe using subdomain would be easier. Another problem is the security because the auth should be scoped to the account.

You can override createUrl() and inside of it, set $params['user']=current user id.

Good but I need two different CreateUrl because all my app isn't under a specific user. Can I override it only for some controllers ?

What about session/auth ?

Hi!

Cool! Sometimes it’s good to give it a second try :) So, putting this into the app config

'urlManager'=>array(

 'class'=>'AppUrlManager',

        'urlFormat'=>'path',

        'showScriptName'=> false

),

AND removing the second urlManager definition a few lines below (stupid, stupid, stupid :)) ) now calls my derived urlManager. This gives me a good hook to fiddle with the stuff.

I created a base controller for the app in components and made all my controllers extend this class, which looks much nicer than the pretty isolated init component I had before. Good one.

Obvious now: the urlmanager parses the uri before the stuff in the base controller gets called. So now I should be able to turn the new 2 screws I got and make that work.

raphael, maybe that works for you, too. You can just override the createUrl in your manager, calling the parent method and then decide by configuration for which controllers additional information needs to be added.

Thanks,

Hein

Hi!

I made it work, using a private urlManager class and the configuration information above. Target was to have different directories with different items in it. Make the user see everything for him and give him the impression that he is using his own app all the time.

Maybe this is a help for someone else.

cheers,

Hein

Hi !

Thanks for sharing your code. I'll have a look to it soon. Do you have handled the auth ?

Regards,

Raphael

Hi Raphael,

for my solution, I dont need authentication. But I guess I would try to put that into the init of the base controller. You can check if the authenticated user has access to the item he’s accessing. Or using a filter? This would be a nice one :)

Cheers,

Hein