Welcome Guest, Not a member yet? Register   Sign In
multiple controllers / what makes sense
#1

Hi everybody,

I have recently started developing with Code Igniter. In the past, I have coded a lot in Office (VB), and I have played around with ASP.NET but I don't really like it. So basically, MVC and web frameworks are still somewhat new and I could use some advice. 

I am currently working on making a calendar application, but I am not 100% sure about how to properly implement this in MVC. For simplicity's sake, let's assume I have two tables:

- Event
- Location

An event is held at a location (Event.LocationID = Location.LocationID). 

When a user enters an event they can choose an existing location, or they can fill out a bunch of fields to create a new location. The form is then submitted to the event creation function in the event controller. Currently, in this function I stary by inspecting whether an existing location was choosen of if the fields for creating a new location are filled. If it appears to be a new location I call the location controller, create a location and get the locationID back from the new controller (using $this->db->insert_id(). Next, I continue to create the event entry using this new locationID for the location field.

This works, but I use the post data from the original request in the second controller (both the Event and Location controller use the $this->input->post(fieldname) function to get the fields they need. Somehow, this all does not feel right (relying on the insert_id(), using the post() data on multiple places. 

I have thought about creating a library for creating a location, and call the library function both from the event controller (instead of calling the location controller) and from the location controller. Would this make more sense, or should I take another approach.

I really want to make it as easy as possible for users to contribute to the event calendar, so I really want to do everything in one form.

Any advice would be appreciated. :-)
Reply
#2

(This post was last modified: 05-23-2016, 05:07 PM by cartalot.)

Just refactor to Models. So your controller calls a Locations Model and an Events Model. Alot of this is style based and personal opinion but for me Controllers should be based on the access level and what they are doing. So if you have the public "visitors" and logged in "users" and logged in "admins" with even more power - don't mix them in the same controller.

So in this example - in your constructor check if they are a logged in "user" - if they are not then they get redirected before going to any of the methods. If they are then return $this->user so its immediately available for all your methods. All of the methods in that controller are for a "user" and especially all of the views that you call are for a logged in "user". This greatly simplifies security and the class is focused. Your methods don't have to confirm access level, your views aren't having to check whether someone is logged in or not.

Whereas you could have methods in your Events model - that are for public webpages AND logged in users.
Reply
#3

Thanks.

I made a mistake in my post above (showing that MVC is not fully clear for me yet). Currently, I already call multiple models from my single controller (I don't call a second controller from the first controller). Still, it feels wrong to send my post variables to multiple models at the same time. On the other hand, if I use a library to create the "Location" first  then why bother with a Location_model.php anyway ? 

At the moment I am not concerned with whether the user is logged in, all new entries must be approved by an administrator before they become visible.
Reply
#4

In the controller, validate the form, then extract the post data you need and pass it to your models. If the models are not tied to the form, they become much easier to re-use in other areas.

For instance, your location model can have a method which accepts the location data as an argument (or multiple arguments), determines whether the data refers to an existing location or is a new one, then returns an ID (either for the existing location or the newly-inserted location) to the controller.

Then the controller can take that ID, along with the form data for the event, and pass it to the event model to create the event.

Even though I can access $this->input->post() (or worse, $_POST[]) in my model, I try not to do so. After all, I may want to do the same thing from the command line, from some other form, or from some context in which $this->input->post() isn't valid. In your own example, the event might be getting the location ID from the form if the user selects an existing location, but if they entered a location the controller would get the ID from the location model. If the location ID does come from the form, you still might want to have the location model verify that it's a valid location ID before using it in the event model. Either way, your event model shouldn't have to know (or care) where the location ID comes from.

I also usually store my data validation rules in the model and use a base model which includes a method to return those rules, so my controller can retrieve them for use in form validation. Since your form has data for two different models, you will probably need rules from both models to validate the form. Of course, one thing that could cause issues is that the location ID may be required for the event model, but won't be available until it has been retrieved from the location model, so any rule(s) for the location ID wouldn't be used in validating the form (unless the form returns a location ID when selecting an existing location).
Reply
#5

So this is the point where the code /application flow starts becoming personal. I disagree with mwhitney - but he's also way smarter then i am so i would never argue any of his points Wink

A huge part of coding is refactoring. Try a pattern, try something else, and see what makes the most sense. Use an IDE like PHPstorm.  And keep learning. Many of the best coding lessons are not written for PHP. I always recommend watching robert martin (uncle bob) clean code lectures on youtube. Uncle Bob never mentions php - he probably doesn't consider it a programming language. But his examples look almost exactly the same as codeigniter because its arrow notation $this->model->something() ;
Reply
#6

I have no problem with disagreement on this front. There are many ways to do the same thing, and one of the reasons I like CI is that it allows you to do things in whatever manner makes sense for you (within the limitations of CI, which are primarily imposed by the loader and router).

In the end, part of it is refactoring, and part of it is knowing how to make it easier on yourself to refactor the code later. If you isolate the data access within the controller, it becomes easier to move that access to one or more models later. So, I might make a private method in my controller which returns data to the other methods, then later replace that code with the code to load a model and retrieve the data from that model. If I have to create, update, and delete data (in addition to reading it), I might have a private method for each, but at least all of the data access is easy to track down and isolated from the other code. If I move that information into one model now and decide later that it should be two (or three), maybe I'll just use the existing model as an interface to the new model(s).

I definitely agree regarding learning about coding without regard to the language used in the lesson. I've only been coding full-time in PHP for 4 years, but I'm constantly applying lessons I learned in other languages, both in the last 4 years and the previous 15.
Reply
#7

Yes, thank you, this makes sense. Also a good suggestion to check the validity of the data in the Location model, even when a location is selected. Didn't occur to me yet to do that. :-)

Regarding PHP Storm: I am actually using it as my IDE because it catches all my boneheaded typo's, but as far as I can tell, it does not give me any hinting on what parameters I have to enter when calling a method from a model (or at least I haven't figured out how), so I fell back to just using $this->input->post['x'] to get the data that I want. But that gets messy.

Going to start some rewriting tonight. But that is part of the fun.
Reply
#8

(This post was last modified: 05-25-2016, 02:30 PM by cartalot.)

Phpstorm - in application/config folder - make a file called autocomplete.php
i have a sample file here -
http://forum.codeigniter.com/thread-6364...#pid325791
you have to include your model names. and notice that the code repeats,
first is for ci controller, the second is for ci model. so you include your model names in both places.
once you have this file autocomplete works automatically - its really great, although i'm sure someone is going to come up with
an even better way.
Reply
#9

That will be helpfull. I am going to check it out!
Reply
#10

Get it to work first then do all the refactoring and bell & whistles.
What did you Try? What did you Get? What did you Expect?

Joined CodeIgniter Community 2009.  ( Skype: insitfx )
Reply




Theme © iAndrew 2016 - Forum software by © MyBB