7

The last few days, I have extensively read books and web pages about OOP and MVC in PHP, so that I can become a better programmer. I've come upon a little problem in my understanding of MVC:

Where do I put a mysql_query?

Should I put it in the controller and call a method on a model that returns data based on the provided query? Or should I put it in the model itself? Are both of the options I'm providing total garbage?

jaco0646
  • 11,033
  • 7
  • 47
  • 64
iceteea
  • 1,144
  • 2
  • 19
  • 34
  • 5
    "Where to put a `mysql_query`?" You dont: Please stop writing new code with the ancient `mysql_*` functions. They are no longer maintained and community has begun the [deprecation process](http://goo.gl/KJveJ) . Instead you should learn about [prepared statements](http://goo.gl/vn8zQ) and use either [PDO](http://php.net/pdo) or [MySQLi](http://php.net/mysqli). If you cannot decide, [this article](http://goo.gl/3gqF9) will help to choose. If you care to learn, [here is a quite good PDO-related tutorial](http://goo.gl/vFWnC). – PeeHaa May 20 '12 at 17:20
  • 1
    I would do the query (either `mysqli_*` or `PDO`) in the model. And **no** the model isn't only repsonisble for accessing the database. – PeeHaa May 20 '12 at 17:21
  • Since I'm still yet not a good programmer I wasn't aware of this. However, I anyways wanted to settle on ORM-Style which seems to be based on PDO. But the question concerning mvc is still unclear: Where do I ask for data from the Database? One generic Model for Read-Access to the DB or a Model for each table/any specific action? In the second case: how would I save code? Is THAT the case where I would create a 'helper'? – iceteea May 20 '12 at 17:23

5 Answers5

15

Materials on the subject of MVC

You could have listed the books you were reading, because most (if not all) php books, which touch on MVC, are wrong.

If you want to become a better developer, i would recommend for you to start with article by Marting Fowler - GUI Architectures. Followed by book from same author - "Patterns of Enterprise Application Architecture". Then the next step would be for you to research SOLID principles and understand how to write code which follows Law of Demeter. This should cover the basics =]

Can I use MVC with PHP ?

Not really. At least not the classical MVC as it was defined for Smalltalk.

Instead in PHP you have 4 other patterns which aim for the same goal: MVC Model2, MVP, MVVM and HMVC. Again, I am too lazy to write about differences one more time, so I'll just link to an old comment of mine.

What is Model ?

First thing you must understand is that Model in MVC is not a class or an object. It is a layer which contains multitude of classes. Basically model layer is all of the layers combined (though, the second layer there should be called "Domain Object Layer", because it contains "Domain Model Objects"). If you care to read quick summary on what is contained in each part of Model layer, you can try reading this old comment (skip to "side note" section).

                            Model layer consists of all the 3 concentric circles
The image is taken from Service Layer article on Fowler's site.

What does the Controllers do ?

Controller has one major responsibilities in MVC (I'm gonna talk about Model2 implementation here):

Execute commands on structures from model layer (services or domain objects), which change the state of said structures.

It usually have a secondary responsibility: to bind (or otherwise pass) structures from Model layer to the View, but it becomes a questionable practice, if you follow SRP

Where do I put SQL related code ?

The storage and retrieval of information is handled at the Data Source Layer, and is usually implemented as DataMapper (do not confuse with ORMs, which abuse that name).

Here is how a simplified use of it would look like:

$mapper = $this->mapperFactory->build(Model\Mappers\User::class);
$user = $this->entityFactory->build(Model\Entities\User::class);

$user->setId(42);
$mapper->fetch($user);

if ($user->isBanned() && $user->hasBannExpired()){
    $user->setStatus(Model\Mappers\User::STATUS_ACTIVE);
}

$mapper->store($user);

As you see, at no point the Domain Object is even aware, that the information from it was stored. And neither it cases about where you put the data. It could be stored in MySQL or PostgreSQL or some noSQL database. Or maybe pushed to remote REST API. Or maybe the mapper was a mock for testing. All you would need to do, to replace the mapper, is provide this method with different factory.

Also, please see these related posts:

Community
  • 1
  • 1
tereško
  • 56,151
  • 24
  • 92
  • 147
  • Your provided code should be implemented inside a service? – dios231 Feb 01 '16 at 20:30
  • @dios231 yes. Or at least the gist of it (note that the code there is almost 4 years old .. how's your 4 year old code holding up). These days I would be using DI container to supply they service with necessary dependencies instead of using factories. And **if** I still used a factories in this manner, the domain objects and data mappers would have separate factories, with `::class` used for inputting the desired product. – tereško Feb 02 '16 at 05:58
  • With the `::class` concept you mean that there will be a class with static methods (like `build Domain()`, `buildMapper()` ), and these methods will return `domain objects` or `data mappers` instances respectively? – dios231 Feb 02 '16 at 11:09
  • 1
    No, wiith `::class` I meant [this new feature](http://php.net/manual/en/migration55.new-features.php#migration55.new-features.class-name) in PHP 5.5. It works pretty well with namespaces and aliasing. When you write `foo(ClassName::class)`, the function receives are a full class name as a string. This way you do not have your code filled with hard-coded strings. – tereško Feb 02 '16 at 14:58
  • So basically, the distinction between view and controller in MVC is that between accessor and mutator of the model? Views are UI objects that present model data to the user, while controllers are objects that take user commands and use them to mutate the model. However, in many GUI apps these things seem kind of mixed together, e.g. we may have a set of buttons (command procurement) that is displayed which depends on the model state. What are these buttons? Are they part of a view or a controller, and what is determining which buttons get shown? I've often heard something like – The_Sympathizer Sep 09 '20 at 20:14
  • "controllers determine which views to use", but that seems like a second responsibility after "mutating the model", so it seems if anything there should be a fourth aspect here and that is some "meta-view" aspect which determines which views and controllers to present the user with for a given model state, or else it seems the view and controller must commingle in some way in this case because we have controller facility depending on model state and thus in part presents model state to the user (view responsibility). – The_Sympathizer Sep 09 '20 at 20:14
  • Or would that just be considered a view, even if it provides the user with a controller and not another sub-view, just so long as the controller-providing view does not _directly_ interact with the model layer's mutation facilities? – The_Sympathizer Sep 09 '20 at 20:19
7

Model and Entity Classes represents the data and the logic of an application, what many calls business logic. Usually, it’s responsible for:

  1. Storing, deleting, updating the application data. Generally it includes the database operations, but implementing the same operations invoking external web services or APIs is not an unusual at all.
  2. encapsulating the application logic. This is the layer that should implement all the logic of the application

Here is the MVC Sequence Diagram which shows the flow during a http request:

enter image description here

In this case Model is the best place to implement the code realted to access database.

AvkashChauhan
  • 20,192
  • 3
  • 31
  • 64
2

For one, don't use mysql_query() and family; they're being deprecated, so consider also learning about PDO and/or mysqli.

The model takes care of data handling; it provides an interface to the controller by which it retrieves and/or stores information. So this would be a primary place where database actions take place.

Update

To answer a question asked by the OP in the comments: "one generic model for the whole db or a model for each table/action?"

Models are meant to abstract away individual tables (although there are models that exclusively handle a single table); for instance, instead of asking for all articles and then query the usernames for the authors you would have one function like this:

function getArticles()
{
    // query article table and join with user table to get username
}

How many models you will create largely depends on how big the project is and how inter-related the data is. If you can identify independent groups of data, it's likely that you'd create a model for each group; but this is no hard & fast rule.

Data manipulation can be part of the same model, unless you want a clear separation between read-only and write-only models (I wouldn't know of a situation that warrants this, but who knows).

Ja͢ck
  • 161,074
  • 33
  • 239
  • 294
2

The model contains the domain objects or data structures that represent the application's state. [wikipedia]. So the model would be the place to make the database call.

In the 'classic' (lack of a better word atm) MVC pattern the view would get the current state from the model.

Don't make the mistake by saying that the model is for accessing the database. It's more than just accessing the database.

PeeHaa
  • 66,697
  • 53
  • 182
  • 254
1

To go even further, your model should not contain the database access code. This belongs to another layer outside the Model/View/Controller: this is called the persistence layer, which can be implemented using an Object-Relational Mapper such as the popular Doctrine 2 for PHP.

This way, you never touch any (my)SQL code. The persistence layer takes care of this for you. I really advise you to have a look at a Doctrine tutorial, this is a really professional way to create your applications.

Instead of working with raw data loaded from the database, you create objects that hold your data, and the behavior associated with it.

For example, you might have a User class, such as:

class User
{
    protected $id;
    protected $name;
    protected $privileges;

    public function setName($name) { ... }
    public function getName() { ... }

    public function addPrivilege(Privilege $privilege) { ... }
    public function getPrivileges() { ... }
}

You controller will only interact with objects:

class UserController
{
    public function testAction()
    {
        // ...

        $user = $em->getRepository('User')->find(123); // load User with id 123
        $user->setName('John'); // work with your objects,
        echo $user->getName();  // and don't worry about the db!
        $em->flush(); // persist your changes
    }
}

Behind the scenes, the ORM takes care of all the low-level work of issuing a SELECT query, instantiating your object, detecting modifications to your object, and issuing the necessary UPDATE statement!

BenMorel
  • 30,280
  • 40
  • 163
  • 285