views:

47

answers:

1

Hi all,

I've a question related to Doctrine 2 and Zend Framework.

If you use Zend Framework without Doctrine by default you place business logic in the models. But as Doctrine 2 does have Entities where should the business logic be placed?

I first had created models where the entity manager did calls to the Entities. But when I wanted to write unit tests for my models without database calls. I needed to move the entity manager to the controllers. But I'm getting business logic in my controllers which is not good.

The code below shows a part of an controller action:

        $customerAddress = $this->_model->save($values, $id);

        $this->_em->persist($customerAddress);

        // Update default billing address
        $defaultBilling = $this->_model->saveDefaultBilling($values, $customerAddress);
        if ($defaultBilling != FALSE) {
            $this->_em->persist($defaultBilling);
        }

        // Update default shipping address
        $defaultShipping = $this->_model->saveDefaultShipping($values, $customerAddress);
        if ($defaultShipping != FALSE) {
            $this->_em->persist($defaultShipping);
        }

        $this->_em->flush();

Can somebody say what's the best practice for this issue? Thx

+1  A: 

I'm not sure there is an agreed upon best practice, but I see a lot of talk regarding Service Layers when discussing Doctrine or Zend Framework.

When I started my app with Doctrine, I tried to build as much functionality into my Entity objects as I could, but quickly realized that's almost impossible without injecting the Entity Manager, which totally breaks the idea of plain, non-persistence-aware objects that makes Doctrine 2 so nice.

If you're coming from an Active Record world, it's easy to think of your 'model' as single object that corresponds to a database table and that controllers have to talk to these objects. This is usually okay for very simple CRUD applications. But because of Doctrine's approach, doing it that way is weird and frustrating.

Instead, think of the different layers in your application. Doctrine is a layer that sits on top of the database, your Entities sit on top of Doctrine, and your Service Layer should sit on top of your Entities. That whole package is your M in MVC, and it comprises both data persistence and business logic.

I would suggest you check out this presentation on the topic.

UPDATE

I originally missed the part where you mentioned you had separate model objects making calls to the Entities. I think that would be an acceptable pattern to use. If you want to write tests without making database calls, you're probably going to want to to use a mock of the Entity Manager -- it's a dependency no matter which layer you put it in.

Bryan M.