0

In my effort to understand MVC in a simple way (I'm trying to make a demo application of my own), I've followed Symfony2's Symfony2 versus Flat PHP material, I've changed some stuff along the way trying to "improve" the code adding some OOP practices, I made a DB class and changed their model from this:

<?php
// model.php
function open_database_connection()
{
    $link = mysql_connect('localhost', 'myuser', 'mypassword');
    mysql_select_db('blog_db', $link);

    return $link;
}

function close_database_connection($link)
{
    mysql_close($link);
}

function get_all_posts()
{
    $link = open_database_connection();

    $result = mysql_query('SELECT id, title FROM post', $link);
    $posts = array();
    while ($row = mysql_fetch_assoc($result)) {
        $posts[] = $row;
    }
    close_database_connection($link);

    return $posts;
}

to this (ignore the spanish please):

<?php
/**
 * @author Me
 * 
 */
/**
 * post.php: clase post, elemento de texto básico del blog
 */
class Post
{
    /**
     * titulo del post
     * @var string
     */
    private $title;

    /**
     * Constructor de la clase Post
     * @param string $title
     */
    function __construct($title)
    {
       $this->title = $title;
    }

    /**
     * Get para titulo del post.
     * @return string
     */
    public function getTitle()
    {
        return $this->title;
    }

    /**
     * Set para titulo del post.
     * @param  string $title
     * @return self
     */
    public function setTitle($title)
    {
        $this->title = $title;
        return $this;
    }

    public function getAllPosts()
    {
        //Ummm what?
    }
}

My problem is, where does this getAllPosts() method fit in my model post.php?, what am I doing wrong? the only thing that came to mind was creating the method as static but that would make no sense and I kNOW it should not be done like that...

Thanks in advance guys, seems like understanding this whole MVC, MVC-like structures in web development is giving me quite some trouble hehe...

NOTE: This has nothing to do with Symfony at all, I'm just trying to follow their simple MVC-like implementation (incluiding the way they create the Views (which apparently is not the "pure" way MVC should be implemented)).

Eduardo Naveda
  • 1,880
  • 3
  • 15
  • 30
  • Application logic is aspect of model **layer**, that deals with interaction between domain entities and storage abstractions. It is usually contained in [services](http://books.google.lv/books?id=vqTfNFDzzdIC&lpg=PP1&pg=PT479#v=onepage&q&f=false). – tereško May 17 '13 at 09:58

3 Answers3

0

You have to make two objects.

  • Entity object - the one you made, representing the Post in database.
    • getTitle()
    • setTitle(title)
  • Data access object - class managing the Post entities in database (createPost).
    • getAllPosts()
    • savePost(post)
StaNov
  • 332
  • 1
  • 4
  • 17
  • Thanks for your answer, now this data access object could you give me an example? How would I access those methods from say.. My controller? As in the controller used in the tutorial. – Eduardo Naveda May 17 '13 at 07:28
  • You are saying these methods that interact with the database should go ina different class are these methods static then? – Eduardo Naveda May 17 '13 at 07:47
  • 1
    Avoid using static methods in general. While they have their uses, it's much to easy to fall into the trap of making everything static and transforming your code into fake OOP i.e procedural code wrapped in classes. – MikeSW May 17 '13 at 08:05
  • I'm using CodeIgniter for developing PHP applications. Take a look at [this question](http://stackoverflow.com/questions/15693867/cast-codeigniter-database-result-object-to-custom-object), it may give you some help. Also try to read the preface of the CodeIgniter documentation. There is nicely described the MVC architecture. In their words, "model" is the data access object, which is manipulating with entity object, they say "custom object" in the question. – StaNov May 17 '13 at 10:14
0

You just need to remember that MVC is an architectural pattern which separates the Business Layer (Model), UI (View), Coordonator(Controller). Note that the Model is polymoprhic i.e it is more than just the database.

MVC is itself an implemntation of the Separation of Concerns (SoC) prinicple. What flat php does (or any language actually) is called Transaction Script and it's suitable only for simplistic (scripting) tasks.

When you want to have an application, a virtual product which provides many (complex) features, where requierements change over the time, you need a proper architecture that can help you modify things without breaking others.

In your code, the getAllPosts method is a violation of separation of concerns and also of the Single Responsability Principle (SRP) becasue the Post, besides modeling a Post has also the task to handle persistence.

MVC says to separate the Model and the View and to use the Controller to coordinate those two. This also means that the Controller should do only managing work i.e selecting the model and selecting the view (or another result). Don't put the data access into Controller unles it's a trivial, homework, prototype app. Keep you Controllers thin doing only what they need to do. If youre controller has more than 10 lines of code, it's a high probability that it's doing too much.

MVC is a very simple pattern, it's much harder to maintain the discipline to respect it.

MikeSW
  • 16,140
  • 3
  • 39
  • 53
  • Model is not "polymorphic". Model is a layer. Classes can be polymorphic, not layers. – tereško May 17 '13 at 10:00
  • Model is polymorphic because it may mean different things (poly morph = multiple forms). It has nothing to do with OOP polymorphism. The Model can be a layer, but the concept isn't used ONLY as a layer. I can tell you that a lot of devs using asp.net mvc mistaken the View Model as the MVC Model, which can be or not the same depending on the app. With the word Model flying around is vey useful to know the multiple meanings of it. And pretty much everyone on the web uses MVC by default. – MikeSW May 17 '13 at 10:14
  • Seems that you think, that MVC stands fro "my very code". Then again, you also seem to think that MVC is a "very simple pattern", which might explain it. – tereško May 17 '13 at 10:45
  • MVC is a very simple pattern, but when people talk about Model everyone understands other things. For example, you understand it as a layer which is neither Controller nor View, while others understand it as an alias for the database. And since everyone uses MVC by default, it's important to know what M we are talking about. Btw the View Model is part of the View layer or the Model layer? – MikeSW May 17 '13 at 10:57
  • "ViewModel" is concept of MVVM design pattern, which ASP.NET MVC has butchered. In MVC there "[presentation models](http://martinfowler.com/eaaDev/PresentationModel.html)" (i actually prefer name "presentation objects). And they should be used within the views. Also, please read [this](http://st-www.cs.illinois.edu/users/smarch/st-docs/mvc.html) and [this](http://martinfowler.com/eaaDev/uiArchs.html). – tereško May 17 '13 at 11:17
  • The View Model does belong to the View but it isn't restricted to MVVM. It's the Model (data) for the View. I don't know how Asp.Net mvc butchered MVVM, as we there is a Model, a Controller and a View. Each layer is separated, but even the View can be organized in layers as well: the Template containing presentation Logic and the Model containing View data. And unlike MVVM, the ViewModel doesn't act as a Controller in a web setting, since it's almost a dumb object. I like that you prefer the name "Presentation Objects" because well, Presentation Models contain the M word. – MikeSW May 17 '13 at 11:30
  • It's pretty obvious that we'll continue to disagree, so let's end it here. – MikeSW May 17 '13 at 11:35
  • Then if that method is a violation where should it be implemented? – Eduardo Naveda May 17 '13 at 15:39
  • That is the part of the Data access layer which handles everything persistence (database). When you want to get all posts, you ask a Repository or a Dao (depending on application complexity) to getAllPosts(). There are a lot of concepts you need to understand but it's best to take it very easy, one at the time. I can tell you to keep in mind that there are no hard rules and recipes. Some approaches are suitable for some cases and the wrong solutions for others. Do simple apps and in the mean time try to learn about good practices. – MikeSW May 17 '13 at 16:38
-2

You only implemented the "M" (the model) part of the MVC structure. Functionality concerning several entities is best left to the Controller that gets your brower's request. So you can go on to add a class like this (using the excellent Doctrine DBAL access layer):

class PostController {
  private $myDb;

  public function __construct(Doctrine\DBAL\Connection $db) {
    $this->myDb = $db;
  }

  public function get() {
    if (!isset($_REQUEST['id'])) {
      $allPosts = $this->myDb->fetchAll('SELECT * FROM Post');
    }
    // pass $allPosts to the view layer...
  }
}

Since the Doctrine guide explicitly warns about adding business logic to the controller: in my personal opinion simple code like fetching all records can go into the controller just fine. You can then wrap the data in model instances by using a Post constructor that accepts an array of column values. All the logic can then use your entity as recommended.

If your database access code gets more sophisticated and you find yourself constantly copying the same code snippets, you can start with StaNov's suggestion of building a separate data access layer. Until then, I really recommend

  1. Stick with a library to do the low level database access
  2. Use the most simple code possible that gets the job done. Complexity will haunt you soon enough.
mabi
  • 5,279
  • 2
  • 43
  • 78
  • Thanks for your answer, I understand, it's just that everywhere I've read everyone keep their stance on something they call ''skinny controllers, fat models'' I assumed this kind of logic would be implemented in models that's why I'm curious on StaNov's point of view. – Eduardo Naveda May 17 '13 at 07:32
  • 1
    No database/datastore/persistence code goes into the controller, at all. Fetching all posts from the database is an important part of the model, not the controller. MVC is there to keep an application modular and extensible; the V and C parts are meant to be *interchangeable* with alternative versions. I.e. you have one HTTP controller and view, one CLI controller and view etc, all interacting with the same model. Once you understand that, it should be obvious that you do not want any database specific logic in any controller. – deceze May 17 '13 at 07:52
  • Come to think of it, I probably used the controller as a cheap data access layer in this case. My main goal was to keep the db access out of the model since that's where I put all the real logic and I hate that being cluttered by DBAL code. – mabi May 17 '13 at 10:39