Question

I've been working on creating my own MVC app in PHP and I've seen a lot of differing opinions online about how exactly this should be set up. Sure, I understand there seems to be a general "It's MVC, it is what you make of it" approach, but I'm running into 2 seemingly conflicting viewpoints.

A little background on my app: I'm using smarty as my presenter and an object-oriented approach. Seems simple enough, but I'm trying to figure out the ubiquitous "what is a model" question.

If I take a look at some tutorials and frameworks, they seem to view the model as strictly a class that inherits DAL methods from an abstract class, with a little bit extra defined in the class itself as your data needs differ from object to object. For example, I might see something like $productModel->get(5) that returns an array of 5 products from the database. So what if I need to query multiple models? Do I store all of the data in the controller or an array and pass that to the view? Then if I'm dynamically calling my controller, how can I persist the data unique to the controller necessary to render the view? This seems bad, especially because I then have to pass in things like "controllerName", "controllerData", and my View::render() method gets hugely bloated with parameters, unless I pass in the controller itself. Maybe I'm missing something here.

Let's say I want to make a login that queries a users table. Login is a model or a controller, depending on certain implementations I've seen online. Some implementations (I'll call this method 1) make a LoginController with method login() that might do a comparison of $_POST and what's returned from the user model instance $user->get(1) to see if a user is validated. Or maybe login() might be a method in a default controller. On the flipside, an implementation (implementation method 2) that resembles more of a Joomla approach would make a Login model and declare all of the actions inside of that. Then any data that needs to get assigned to the view would get returned from those methods. So login->login() would actually check post, see if there's a match, etc. Also the User model would probably be instantiated inside that model method.

My feelings about 1: The controller is fat. Additionally the controller is storing data pulled from models or passing in ten thousand variables. It doesn't seem to jibe with the idea that the model should be passing data to the view that the controller should be blind to. Also, let's say I want to wrap everything that is in a specific model handled by a specific controller in an outer template. I'd have to copy this template-setting code all across my controller functions that interface with this model. It seems grossly inefficient.

My feelings about 2: It doesn't make for having actions that aren't model methods. If I want to go to my site root, I have to make an index model or something that seems like overkill in order to have a model that passes data to the view. Also, this doesn't seem to be a very popular approach. However, I do like it more because I can just do View::render(mymodel->func()) and ensure that the data is going to be passed back just the way I like it without having to crap up my controller with code merging a thousand query results together.

I've waded through far too many religious arguments about this and want to know what you guys think.

Was it helpful?

Solution

I've built my own framework in the past too so I know what you're going through. I've heard the saying "build fat models" and I agree with that -- as long as the main goal is to return data. I considered the controller to be "The Overlord" as it manipulated data and directed where it should go.

For a login controller i might create something it like...

Post URI: http://example.com/login/authenticate

LoginController extends ParentController {
  public function authenticate() {
    $credential_model = $this->getModel('credentials');
    // Obviously you should sanitize the $_POST values.
    $is_valid = $credential_model->isValid($_POST['user'], $_POST['email']);
    $view = $is_valid ? 'login_fail.php' : 'login_success.php';
    $data = array();
    $data['a'] = $a;
    // .. more vars
    $this->view->render($view, $data);
  }
}

In my opinion data should always flow from the model -> controller -> view as it makes the most sense (data, manipulation, output). The View should only have access to what it has been given by the controller.

As for this...

Then if I'm dynamically calling my controller, how can I persist the data unique to the controller necessary to render the view?

Well I would imagine you're building a 'base' or 'parent' controller that gets extended off of by your dynamically called controllers. Those child controllers can have properties that are needed for for the view to render -- honestly I'd need an example to go further.

Hopefully this helps a bit. If you ask more specific questions I might be able to give a better thought out opinion.

OTHER TIPS

If you're writing your own app, I think the best solution is to do it yourself and find out.

Ultimately, whatever makes the most sense to you, and whatever makes it easier for you to conceptualize your app and quickly add to or change it, is going to be your best option.

If one way is "wrong", then you'll find out through experience, rather than someone else telling you. And you'll know the entire situation that much better, and know EXACTLY why one way is better.

What helped me when I was writing my own framework in PHP was, strangely enough, CherryPy. It made the concept of an object-oriented web app so simple and obvious, and I enjoyed using it so much, that I modeled the basic structure of my PHP framework to imitate CherryPy.

I don't mean to imply you should learn CherryPy. I mean that simplicity, clarity, and enjoying developing with your own web app go a LONG way.


If I were to give one piece of specific advice, I'd say try to avoid retyping code; write your code to be reusable in as many situations as possible. This will not only be good for your app, but for future apps you may write or work on.

You might check out Eric S. Raymond's Rules for Unix Programming. I think they're definitely applicable here.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top