3

I was just wondering what the best practice approach is for deciding where to create an action/view in certain situations.

If User hasMany Video

where is the best place to create the action/view to show user videos?

So within the Users account page 'My Videos' link do you

  1. just create a users/my_videos action and view.
  2. create videos/my_videos action and view.
  3. or as is most likely you would already have a Controller/Action of videos/index which would have search functionality. Simply use this passing in a user id.

Any thoughts/advice greatly appreciated

Thanks

Leo

Dunhamzzz
  • 14,682
  • 4
  • 50
  • 74
Leo
  • 1,521
  • 12
  • 18
  • I am in exactly the same situation, part of me wants to put it in the users controller, but it's not specifically tied to editing the user, although I would like for it to appear in the users' "dashboard". – Dunhamzzz May 23 '11 at 11:57
  • See my answer dunhamzzz - once you have the action working you can pull it in via requestAction for the dashboard. This is one of the most common uses for requestAction - you can evn have the action handle caching and fetching it's own data via preset pagination params in the call to the element that uses the requestAction call. http://bakery.cakephp.org/articles/gwoo/2007/04/12/creating-reusable-elements-with-requestaction – Abba Bryant May 25 '11 at 14:26

5 Answers5

3

One potential option is to do the following:

Since the videos likely have much more code around them than a simple which user has which videos lookup the video list action should be in the VideosController.

In past projects I have (in CakePHP 1.3) used prefix routing to address some of this.

In config/core.php make sure you enable routing.prefixes to include a 'user' prefix.

<?php
    ... in routes.php ...
    Routing.prefixes = array( 'user' );
?>

In the videos controller make an action with the following signature:

<?php
    ...
    public function user_index( $userID = null ){
        ...
    }
?>

and in the views where you link to the list of users videos the html::link call should look similar to the following:

<?php
    ...
    echo $this->Html->link( 'User\'s Videos', array(
        'controller' => 'videos',
        'action' => 'index',
        'prefix' => 'user',
        $this->Session->read( 'Auth.User.id' )
    ));
?>

Of course this assumes you are using the Auth component here to track the logged in user. The Session helper code to read the authenticated user id might need tweaking.

This lets you a) Not worry too much about routing aside from enabling prefix routing and b) will quickly let you have pretty links like so -- site.com/user/videos/index/419

Couple this with some Slug love ( this is the best link for this I have seen - no slug field required on the db layer - http://42pixels.com/blog/slugs-ugly-bugs-pretty-urls )

You could even end up with urls like so quite easily: site.com/user/videos/index/eben-roux

and with just a tiny bit of editing to app/config/routes.php you could eliminate the /index/ portion and the results would be SEO friendly and user friendly in the format: site.com/user/videos/eben-roux

http://book.cakephp.org/view/945/Routes-Configuration

Abba Bryant
  • 4,012
  • 22
  • 18
  • This looks like the best way so far, but I'm concerned the user prefix will clash with my other user actions? users/login, users/regitser etc – Dunhamzzz May 27 '11 at 09:34
  • just make sure you use either 'prefix' => false or 'user' => false in the links to the users controller that don't have a prefix to them. – Abba Bryant May 27 '11 at 16:08
0

As always with code you have the two extremes of:

1) Putting everything in a single controller

2) Having every action in a separate controller

The ideal approach will nearly always be somewhere between the two so how to decide what is grouped together and what is separated?

In MVC I tend to look at the Views and see what the commonalities are: as you point out Users have a ref to a collection of Videos in the Model, but would you want both sets of Data in any single View? i.e. In this example is it likely that you would be on a page that both managed user details, and displayed the list of vids? If not then I'd suggest separate controllers.

If either controller would then be extremely simple - e.g. one method, then may be worth considering merging the two.

BonyT
  • 10,750
  • 5
  • 31
  • 52
  • I would not recommend to put everything in a single controller because you break the Single Responsibility Principle ==> There should never be more than one reason for a class to change. – Mehmetali Shaqiri May 26 '11 at 14:22
  • Well - you may only have 2 actions that perform very similar tasks! But note I did state that these are the two "possible" extremes and the ideal will nearly always be somewhere between the two. I am not advocating either "extreme" as a solution! – BonyT May 26 '11 at 14:45
0

I like to keeps things separate.

What I'd do is an index action in videos controller, passing user's id as argument and then displaying only current users video.

public function index($id = null){
   $this->paginate = array( 'conditions'=> array('Video.user_id' => $id));
   $this->set('videos', $this->paginate());

}
kaklon
  • 2,422
  • 2
  • 26
  • 39
0

My take is that it depends on the responsibility you assign to the controllers.

I would say that something like a User or a Video controller should be concerned with only those entities.

You may want to consider something like a UserDashboard (or something similar but appropriately named) as alluded to by Dunhamzzz in the comments. This can aggegate all the functionality from an "entry" point-of-view. The same way a banner / shortcut / action menu would work.

Your UserDashboard would use whatever data layer / repository is required to get the relevant data (such as the IVideoRepository or IVideoQuery implementation).

Usually when something doesn't feel right it isn't. Try splitting it out and see how it works. You can alsways re-arrange / refactor again later.

Just a thought.

Eben Roux
  • 12,983
  • 2
  • 27
  • 48
0

I don't think there's a 'one-rule-fits-all' solution to this question, but I would try to take an approach in which you would determine what the main object is that you're dealing with, and adding the action/view to that object's controller.

In your example I'd say that your main object is a video and that the action you're requiring is a list of video's filtered by a specific property (in this case the user's id, but this could very well be a category, a location, etc.).

One thing I would not do is let your desired URL determine in which controller you put your functionality. URLs are trivially changed with routes.

vindia
  • 1,678
  • 10
  • 14