views:

104

answers:

3

Hello.

I have recently started using the CodeIgniter framework for my PHP development.

I was just curious as to correct usage.

Essentially I have the following situation.

I have a controller entitled 'items'

I want it so if the user goes to items/index they get a list of caetgories, if they go to items/category-name they get a list of items.

To achieve this, I have the one controller with an if/elseif statement which loads different views. Is this the correct approach?

If i am on a items/category-name page, I load a view entitled 'items-list' I pass a variable entitled $type to this view.

In the view it detects this type (again with an if statement) and outputs the category title (also passed). Simple.

As well as this I have a completely different controller for a recently sold items list (dont ask :)). As the format of the list to display is essentially the same I utilize the same view, but pass a different $type var. The view detects this, outputs various 'extra' links, images etc and of course does not output a 'categories' title.

Essentially I have 2 controllers utilizing one view. With various if/elseif statements in both the controllers and the view to get the right output.

Is this the correct approach?

Thanks

+3  A: 

In short...

there is no single right or wrong way to structure your controllers/views/models/libraries/helpers.

I too use CI, and I've found that controllers with the smallest amount of code in each controller method are the easiest to go back to and edit/maintain/upgrade/read. If too much logic is placed in my controller methods, clarity and understanding gets lost. I try to place most of my 'logic' in library or helper methods, so my controller methods are simple and easy to read.

I like to have the controller accept arguments/data, send it to models and/or library and helper methods, which return modified or new data. The returned data might get sent to other methods before finally being sent to a view.

This technique does tend to send you chasing around multiple files when writing an app or site, but achieves a clear separation of views and logic. Hopefully, it helps you write re-usable code too, even if it is only re-usable in the single app.

Whatever works for you and your team, is okay.

kevtrout
Most of my logic isif x show this otherwise show this so in my controller i have lots of php.. if form validated load view x otherwise load view y etcbut little things, like i pass a $title var to my header but this means in my controller i have numerous calls to the header view sending different titles depending on the if statements..it is simple , but cluttered.Could you elaborate on your usage of custom helpers/libraries?Thx
Thomas Clowes
I might define a function in a helper or library that contains all the if/else statements. I would feed the function the 'x' you mentioned, and return the output determined by the if/else logic. That way, you set up something in your controller like `$title = return_my_title($x);`. Your helper or library then contains then contains `function return_my_title($x);`. Load the view in your controller with the returned value: `$this->load->view('header_view',$title);`. This removes the long if/else conditional logic (clutter) from your controller.
kevtrout
But is that not what models are for? Thanks
Thomas Clowes
To me, models are for interacting with the database. The functions I'm speaking of are functions that manipulate data, format html, and work with conditional statements. Most of the time, I use controllers to 'route' information to functions, models, and views. If the manipulation or conditional is small and clear, I will include it in the controller since it might be more work to create a separate function to do the same thing. So, I guess, on the last part of my comment, it depends!
kevtrout
+1  A: 

For the first part of your question, you should look at CI's routing class:

http://codeigniter.com/user_guide/general/routing.html

There's nothing fundamentally wrong with this approach, but you really don't need two controllers. Presumably you're doing this so that your URIs show up properly in the browser? If so, let's say you currently have controllers called items and solditems. You could set up a route like this:

$route['solditems/(:any)'] = "items/solditems/$1";

That way, when someone types in mysite.com/solditems/category the script will run at the controller at mysite.com/items/solditems/category.

Edit: I should also add something about models since it was in your title. In essence, you want to have controllers be the "access" layer for your applications...essentially exactly how you have it now. View, obviously, contain the visual presentation of your site. Models handle all things data. If you want to get a list of all products, you will want a "products" model and a function in there called "getProducts" or something. Then another called "getProductById" or something like that. If you're smart, you'll come up with a standard data formatting method so that you always know what to expect from your data calls, and thus can pass return values directly from your model to your view through your controller. So if you want to get all sold items, you can have a controller that does handles the request and makes the call to the model, the model will run the database query and spit the data back to the controller in any manner you like, and your controller will be entirely agnostic as to what comes back, but simply passes that variable to the view to be processed visually. You could also handle some of the presentation logic in your controller if you have a large number of views (e.g. if you have one view that is a "list item" for a single one of your sold items...you can use your controller to iterate through the variable returned from the model passing them one by one to the "list item" view, concatenating that string (see: the optional third parameter for $this->load->view()), and then pasting that string into a "list" view.

You can get as creative as you want as long as you remember that the point of all this is to logically separate the access layer from the presentation layer from the data layer. Beyond that abstract separation, there are no "best practices", just what's best for you.

treeface
Thanks. Well for example, I have recently been working with user location.I have a 'location' model which selects the nearest points of interest. These are returned to the controller in an array and then passed to the view.I then have an 'hotels' model which has functions to get details on hotels.Is the correct way to approach this to call the location model, and find the nearest points of interest. Pass this back to the controller, which then passes the data the hotel model OR is it better to have everything in one model with functions calling other functions? Thx
Thomas Clowes
You can split up the models logically in any way you like down to any level of detail. I would honestly put a hotel finding function into a model called "location" because that word fairly accurately describes the type of function that "findHotels()" is. But maybe you have a separate area of the site that searches for hotels based on price...in this case maybe a "hotels" model where you can store all of these functions. Then you can call findHotelsByLocation() in your hotels model from you location controller and findHotelsByPrice in your hotels model from controller pricefinder (or whatever).
treeface
A: 

Like others have stated, there's not a really clear-cut "right" way. Whatever works for you. For me, I generally use about one view per action. (I use more if that action handles a form or something).

For example I might have:

'items/view/7'

which has a view for a specific product

'category/view/3'

which has a view for a category

You'll find as you use codeigniter more, you'll find things that are more organized (and therefore more "maintainable" to you). And with some small applications, I've even reorganized everything later on (I mean literally, rearranged classes and functions and folders containing views) just to make it more logical.

I don't see anything that's "wrong" with what you're doing. Though the way it sounds with the last part of your post, where you use the same view and just have variables that process what the view is going to do, I would probably avoid this (though it depends on other things too). I would probably just have a view for "recent sold products" that was independent of the "category" view. Having the view do very much logic isn't usually a good idea.

Matthew
I mean there is nothing 'wrong' - everything works.. but i want to get the most from MVC :)So is a setup like this considered correct.In a login script for example would you have in the controller- if logged in - load 'already logged in view' (which literally just says 'already logged in')-else - load form viewOR- load login view (passing login status) and have the view decide what is displayed..Thx
Thomas Clowes
I find myself re-organizing my code and classes on every project. You learn a lot about the design of the code as you go.
kevtrout