Need some clarification between MVC and traditional website URL structures

I have a website using Yii and what’s confusing me is I am thinking of my website in terms of being structured like

mysite.com/about

mysite.com/member/

mysite.com/member/profile/

In reality, these directories don’t exist. The mysite.com/about page is a view, but what would the pages be? If I wasn’t using the MVC approach the member/ directory would contain an index.php file to display some information. member/profile/ would be a subdirectory to display a user’s profile information.

How does this fall into the MVC design? Would there be a member controller with the following action IDs: index,profile. index would display mysite.com/member/ and profile action would display mysite.com/member/profile/?

In Yii (and maybe in all other frameworks), the URL structure is constructed virtually.

Usually we have some directory structure in ‘protected’ directory, but it doesn’t necessarily define the URL structure of the app.

And, MVC design pattern and URL structure are different things.

MVC is a design pattern that you use to construct a page from data.

http://www.yiiframework.com/doc/guide/1.1/en/basics.mvc

And we can apply a variety of URL structures to the same application.

This is done by the url manager in Yii.

http://www.yiiframework.com/doc/guide/1.1/en/topics.url

For example, you can apply a totally flat URL structure to your site.




mysite.com/index.php?r=about

mysite.com/index.php?r=member/index

mysite.com/index.php?r=member/profile&id=1

...



These are the default.

And if you have configured your url manager with ‘urlFormat’ to ‘path’, then you will get:




mysite.com/index.php/about

mysite.com/index.php/member/index

mysite.com/index.php/member/profile/1

...



And you will further set ‘showScriptName’ to ‘false’ in order to get:




mysite.com/about

mysite.com/member/index

mysite.com/member/profile/1

...



This flexibility in URL structure is a result of “single front-end controller design pattern”(sorry, I don’t know the exact name) … this is something different from MVC.

Thanks for the overview.

Using my example above, am I right to say I would have a MembersController with actions on that such as profile, listings, etc…?

I think I am going to focus on building the website first, then visit the url structure to prettify them.

Yes, you are right. :)

Yes, I think it’s really a good idea.

It seems to me that many people tend to mess up the whole thing trying to achieve so-called SEO friendly url before they get a big picture of the framework. :)

I can see why. For me it’s not so much about creating SEO friendly URLs but about understanding visually how the site will be organized. Using my example, I would have a members/index.php file that, if user is not logged in, then display login page, else display links (tabs or a menu) to view their profile, listings. If they clicked on the profile link, it would take them to a page to display username, password, name and address information. The listings page would display items the user has saved into a Listings table.

Using the MVC pattern there would be a MemberController with index, profile and listings action IDs. The MemberController would have something like




  public function actionIndex()

  {

    // if user is logged in $this->actionLogin()

    // else $this->actionDashboard()

  }


  public function actionLogin()

  {

    $this->render('login-view');

  }


  public function actionDashboard()

  {

    $this->render('dashboard-view');

  }

 

  public function actionProfile()

  {

    $userModel = new Users(); //

    $this->render(‘profile-view’);

  }


  public function actionListings()

  {

    $listingsModel = new Listings();

    $this->render(‘listings-view’);

  }



A click on a link to mysite.com/index.php?r=member/listings would display the listings view.

mysite.com/index.php?r=member/profile displays a person’s name/address information and allows them to update. If I want a user to be able to update their profile, I would need to create a ProfileController to enable CRUD operations, or in this case, only Update?

Yes, if you use the default url format of "get", then a query string part of the url should be in the format of:




r=controller/action&param_a=value&param_b=value&...



So "index.php?r=member/listings" should be dispatched to "listings" action of "member" controller.

And, yes, you have to make ready the appropriate view for that action, and usually you will also need some model(s) if you want to deal with data in that action.

If you have created database tables for your application, then gii will automatically create the model classes for you. And if you want further, gii can create a skeleton controller or even a set of CRUD code for the specified model class.

Gii-generated CRUD includes a controller and some views. You may use them as they are, or modify them to suit your needs and taste. Or, you can also cut & paste those CRUD actions and views to another controller, if you want.

But, before you try to build your own project, I strongly recommend you to work out one of the tutorials … Larry Ullman’s tutorial or Yii blog tutorial. It’s the fastest way. :)

According to the Yii blog tutorial, they have the blog app installed to /wwwroot/blog/. Is it best practice to separate it like this instead of doing the entire website under one Yii app? For example, if I wanted to add a forum, I would create another Yii app called forum, at /wwwroot/forum/. Or would creating blog and forum as modules be better?

Um, I don’t know for sure, but using modules would be better when they share look-and-feel and functionality. But separate apps also might be OK. I’m sorry, I don’t have much idea on this. :D

I’m making some progress on my app, but I ran into some trouble.

I have a MemberController that has some of the actions listed above. One of the actions is ‘profile’ that is supposed to display user information. I have a UserController to control the actions of display the user information.

Is it perfectly reasonable to use $this->forward(’/user/<some-action>’), or is it better to redirect? I like using the forward because it masks the user/view in the url. So when I click on member/profile, it gets forwarded to user/view but the URL is shown as member/profile.

Are there any pitfalls for using this?




// inside MemberController

public function actionProfile()

{

  // calls UserController action

  $this->forward('/user/view');

}



That’s not the job of the forward() method, you should use url rules instead.

You don’t have to handle User model solely in UserController.

I would rather do the job directly in MemberController accessing User model in it. :)

So you’re saying doing something like?




public function actionProfile()

{

  $model = new User;

  $this->redirect('/member/profile', array('model'=>$model));

}



Yes, if you mean ‘render’ instead of ‘redirect’. :)

Oops, Yes I did. :)

The reason I wanted MemberController to call UserController is because the UserController is going to have that same action as well as other actions such as update. It seems kind of silly to write a profile view for the MemberController when the UserController is going to be doing the same thing.