6

I am working on an MVC application in PHP that is not using any frameworks. I am using RedBean for my ORM, which implements the datamapper pattern and works quite similiar to doctrine.

As per this question, I understand that the model is NOT the ORM object. In my project I have the following scenarios:

  • "Complicated" Models which need to talk with a lot of tables in the database:

    • One of these models can be something like the RBAC permissions system. A controller should be able to call something like $permission->isAllowed($controller, $action, $resource) to determine if the user is allowed to perform the requested action. In addition, he might call $permission->getPermissions() to get a list of permissions the user has.
  • "Simple" models where the model can generally be represented by 1 table in the database:

    • One such model would be the User model. For example $user->changeRank(), $user->addPoints() and so on.

The problem I am facing now is that looking at most documentation for various frameworks, I can see that in the examples, the controller talks with the ORM directly. For example, here's an example controller from symfony2:

public function createAction()
{
    $product = new Product();
    $product->setName('A Foo Bar');
    $product->setPrice('19.99');
    $product->setDescription('Lorem ipsum dolor');

    $em = $this->getDoctrine()->getEntityManager();
    $em->persist($product);
    $em->flush();

    return new Response('Created product id '.$product->getId());
}

If an ORM is NOT the model, why is the controller allowed to interact directly with it? Shouldn't it interact with a Model that looks like this?

class ProductModel{
   public function newProduct($name, $price, $description){
        $product = new Product();
        $product->setName('A Foo Bar');
        $product->setPrice('19.99');
        $product->setDescription('Lorem ipsum dolor');

        $em = $this->getDoctrine()->getEntityManager();
        $em->persist($product);
        $em->flush();
   }
}

Finally, I outlined the permissions model earlier. Is this considered to be a model in the context of MVC? This class will be used across the whole application, as most abctions will need to check for access permissions.

Community
  • 1
  • 1
F21
  • 32,163
  • 26
  • 99
  • 170

1 Answers1

2

An ORM (Object Relational Mapper) is used to generate model files. Model files are used to communicate between the application and database (model). It seems you are versed in the ORM processes, but a quick re-cap (using doctrine as an example), for those who may not be, and I might get lucky and answer your question.

You use the ORM to introspect your database schema, which generates a schema file. Now with this schema file you can alter it to suit your application needs. For example, you can add actAs: { Timestampable ~}, or actAs: NestedSet: hasManyRoots: true. Also, you will want to use this schema file to setup how you want relations between objects to behave (i.e. 1:M, M:M using a refClass, etc.)

Once your schema file is ready to go, you issue the command to generate the model files. The model files are classes which you can use within your application to gain access to the database. So the controller is actually communicating with the model (your database) through the files generated by the ORM.

The example you gave is a good one, in that you can offload much of the business logic out of your action (page controller) and into your model. This way the same logic can be accessed from other code-points without having to deal with any controller level logic. What doctrine does (and propel does too), is allow you to create 'Table' (or 'Peer') classes. These classes act as containers for dealing with multiple objects. It's within these classes you should add your business logic as you demonstrated in your second example.

The ultimate goal is to keep your actions as lightweight as possible, just dealing with request params and form handling, then push the values to your model via 'Table' or custom classes you design. Following this paradigm you can have a feature rich application with trim actions and centralized business logic.

Edit ---

Sorry I missed your last question regarding your permission API. From what you posted, it does appear to follow the MVC paradigm in that you have a permission object and are using as a API between the controller and database.

Mike Purcell
  • 19,847
  • 10
  • 52
  • 89
  • Is it acceptable that some models require an entitymanager (models that need persistence) to manage them, while other models (which might not need persistence), do not need an entitymanager? Having 2 ways to instantiate and manage models doesn't seem very clean to me. – F21 Nov 20 '11 at 05:34
  • @phpdev: Are you referring to Doctrine specifically? – Mike Purcell Nov 20 '11 at 21:17
  • Yes. I have some models that do not interact with the database at all, so they would not require the entity manager at all. – F21 Nov 20 '11 at 22:10
  • @phpdev: It appears `entitymanager` is a new API introduced in doctrine 2.0. Unfortunately I haven't shifted from 1.2 yet so I cannot answer your question about `entitymanager`. It seems though, that entitymanager is within the doctrine layer and not your model layer, so you are not incurring the overhead of entitymanager if you don't want it. Check one of your base model files which needs database access and see if it differs from the base model file which does not. Chances are the only differences will be the actual member vars and few other setup options. – Mike Purcell Nov 21 '11 at 00:27