Welcome Guest, Not a member yet? Register   Sign In
Best MVC design practice?
#1

[eluser]Fred Riley[/eluser]
I'm new to CI in particular and MVC in general, but I like the MVC approach very much and it's generating far tidier code than my previous PHP which mixed queries, application logic and presentation in documents. CI's not hard to learn and is well documented (thank to all those who've done that thankless task)

I'm designing my first CI application and am trying to implement MVC. Before I go too far down the road I'd be interested to know if there's a MVC 'best practice' guide available online anywhere? I don't want to be unlearning bad practice later. Things that have already occurred to me:

1. Is it ok to call model methods from views, or should a view only call controller methods?
2. Should there be only one controller per application? It could get pretty damn big. OTOH, multiple controllers would make for a messy application.
3. Should there be only one model per application?
4. Should I use custom-written function libraries, as I used to do? If so, where should I stash them, and should I call them with includes or load()? If not, should all functions be put in the controller?

(As a for instance, I've got a tag_cloud() function, and my feeling is that generating a tag cloud is more view than controller, so it might be good to call it from views which include a function library. )

And so on. Questions like these would be taken care of by a best practice guide, if there is one.

I did try to search the fora but got null results for all searches, even for obvious terms like "email" and "codeigniter" - I just got the advanced search form presented, no results. Is there a current problem with the search?

I did look at the few approaches that are currently on the wiki but they didn't seem to answer my questions and provide a 'style guide'.

TIA for tips :o)

Cheers

Fred
#2

[eluser]mddd[/eluser]
Welcome to Codeigniter and to the forums.
My first tip would be to read the user guide entirely (at least the General Topics area).

Then, on to your questions:

1. Personally I think calling models from views is ok, but only if you do it to check properties from the model. For instance, if you have a model that deals with user information, you could have if ($user_model->is_logged_in()) { // show something } in the view. Of course you could get that information in the controller and then send it to the model, but for this kind of 'read only' operation I would say it's ok to call the method from a view. But it would be more strict MVC to use the controller as a 'middle man'.

2. No. The controllers are meant to give structure. They split up the application into manageable parts! And in CI, there is a large part of automation in the controller phase: depending on the called url, a certain method in a certain controller is loaded. So the question 'where are we in the application' is answered in this phase.

3. No. Why would there be? Models are meant to be split up by subject. If you have a site with users, posts, news articles etc., you could make a model for each of those. Then you would call a model using $this->user_model->add() or $this->blog_model->list_recent() etc. Again: the whole point is to make things managable. If you put everything on one pile, you might as well build your entire application by including a file containing 100 functions!

4. Using libraries is a good practice. In CI, we have models which are libraries of functions around a part of your application, and libraries which are more generic. They usually contain a group of functions that take care of some task that relates to the application but is not the core of it. Libraries could be re-used in other applications.

Generally: try to only do output in a view. Use the controller as the 'general manager' of the project. Use the model as the 'data collector' that gets all the needed information. Use the view only to output things. Use libraries as 'specialists' that do specific tasks.
#3

[eluser]gyo[/eluser]
Hi, here is some feedback from my point of view:

1- It's fine to call model methods in views and never call controller methods, since they are (generically) intended to be accessibles via URI. You might consider helpers to call in views.

2- If you put everything in one controller you would end up with a HUGE file that has to be loaded everytime, even if some features are not needed. This is IMHO totally wrong, and against the principles of CI, MVC, DRY, KISS etc... you can (for example) have one controller for articles, one for blog, and one for a contact page, each one with its own model with specific methods.

3- In general one controller has one model, so that all the 'dirty' code goes to the model, keeping the controller clean and just 'controlling' the actions.

4- If it's not classes, you can create 'helpers' and load them via $this->load->helper('tag_cloud');
If it's a class, you can put it in the 'libraries' folder and load it via $this->load->library('tag_cloud');

Have a look at the user guide, it explains everything more in detail.

Btw I have no problems with the search function of the forum, that's kind of weird actually. Smile


Welcome to CodeIgniter, enjoy!
#4

[eluser]oldblueday[/eluser]
Fred, as a newbie myself, I've found the forums to be quite welcoming and people tend to answer without arrogance I've found on other forums. We learn from each other, right?

1. From what I read, models should be separate from views, however you don't have to do that. CI is pretty flexible that you can do it if you want. Being a newbie, I decided to follow this rule (while I'm learning) before I learn when to break it. It's actually forced me to better ways of doing things.

2. Ditto what everyone said. Have as many controllers as you need.

3. I've been using one model per database table. For example I have tables called 'students', 'rotations', 'questions', 'quizzes', etc. So I have models named 'student', 'rotation', 'question', 'quiz', etc.

The other thing I learned is to put as much database functionality into your models as you can. You can process the data in there and output what needs to be used. This is the concept of "fat models, skinny controllers."

4. Ditto.
#5

[eluser]Fred Riley[/eluser]
Thanks to all for the replies, which have given me plenty to reflect on. I did RTFM, honestly, and on reflection the answers to 2, 3 and 4 were present in the pages on models, controllers and helpers, though by implication rather than directly. The trick is to internalise the CI model and 'modus operandi' which will come with practice.

[quote author="oldblueday" date="1282681747"]

3. I've been using one model per database table. For example I have tables called 'students', 'rotations', 'questions', 'quizzes', etc. So I have models named 'student', 'rotation', 'question', 'quiz', etc. [/quote]

I can see the logic in that, but where do you put your multi-table joins? If you want to find out what quizzes a student's done, in which model do you put your query?

[quote author="mddd" date="1282681747"]
2. No. The controllers are meant to give structure. They split up the application into manageable parts! And in CI, there is a large part of automation in the controller phase: depending on the called url, a certain method in a certain controller is loaded. So the question ‘where are we in the application’ is answered in this phase.[/quote]

This is where I've already been involved in bad practice, then. I'm coding a database of online resources, so my URLs (with mod_rewrite) are of the form:

http://localhost/PHP/codeigniter/resourcedb/browse/

where the application root is "http://localhost/PHP/codeigniter/" with one controller - resourcedb - containing various methods (browse, search, insert, etc). I should be thinking one step up, and having controllers for browse, search, insert, etc. What I need to get my head around is how to tie all the controllers into a coherent whole...

Cheers

Fred

PS: The search still returns null, and now I find that submitting this reply returns an empty 'reply to' form and doesn't submit. I also had the devil's own time registering for this forum, with the captcha giving me real grief. Maybe rats have been nibbling at the network cables... Anyway, I'll try with IE instead of FF, which logically shouldn't make a difference but who knows.
#6

[eluser]oldblueday[/eluser]
Fred,

When I want to do a multi-table query, I usually will do that in the controller. It will call one model and get information and feed that to another model.

Code:
$this_rotation = $this->rotation->what_rotation_is_this();
$student_array = $this->student->get_students_by_rotation_id($this_rotation);

You can refer to one model from within another, however. I do that rarely when I just want to check something in the other model.

Break up your controller into whatever pieces seem appropriate to you. If your site is big, I think this would pay. For example, I have my student's lessons being displayed from one controller, I have their testing from another, I have my admin functions from yet another, etc.

Honestly, RTFM does help but I had to buy another book (Packt press) and watch the videos (found on the wiki page) to really get an idea. I'm not a developer, so perhaps I needed an extra kick in the pants to get moving.

- Rahul
#7

[eluser]mddd[/eluser]
oldblueday's message describes exactly why it is not the most handy way to use a model per table. Sure, it is very clear and separated. But it also makes things harder then necessary.

If you want to keep a model per table, you should use a ORM system like Datamapper (Google it or find it in the forums).

I like to take the pragmatic approach: don't make it a point to have a model per table. Use models for logical units of information. Example: you have users and each user has their contact data in the 'contact' table, login info in 'login' table and their access right in the 'access' table. I would just make a model 'users'. That model would have methods like: add, remove, set_rights. But also like 'get_users_with_right()' that would give you all the admins, for instance.
Everything in the model deals with users. That is a logical bit of information. Even if it comes from multiple tables.
#8

[eluser]oldblueday[/eluser]
Good point. I had read that this was the way to do it (either in some book or on some site). Learn so much on the forums.
#9

[eluser]mddd[/eluser]
Your way is also perfectly valid. There is no one true solution. Separation also has its advantages.

I try to combine related things because they are often queried together. In your example, you would first have to load the rotation info : $this->rotation->get($id) which takes a database query and then you look up the students like you showed.. that's another query. If you do that a lot it is less efficient.
#10

[eluser]WanWizard[/eluser]
And don't forget you can do both.

You can use Datamapper (DMZ) which provides you with models per table, which will also contain all custom methods and validation rules directly relating to that table. And still use 'normal' CI models for the complex stuff that needs to interact with lots of tables (DMZ models).




Theme © iAndrew 2016 - Forum software by © MyBB