Search code examples
databasemodelzend-framework2service-locatortablegateway

Zend framework 2 model for database, separate model for each table?


I looked through the manual of Zend Framework 2 about creating model to managing operations on table. Is the class with method exchangeArray() is necessary? It's only copy data :/ Can i create one model to manage a few tables?

I created two classes:

namespace Application\Model;
use Zend\Db\Adapter\Adapter;
use Zend\Db\Adapter\AdapterAwareInterface;

    abstract class AbstractAdapterAware implements AdapterAwareInterface
    {
        protected $db;

        public function setDbAdapter(Adapter $adapter)
        {
            $this->db = $adapter;
        }
    }

and:

namespace Application\Model;

class ExampleModel extends AbstractAdapterAware
{

    public function fetchAllStudents()
    {

        $result = $this->db->query('select * from Student')->execute();

        return $result;
    }

}

I also add entries in Module.php:

'initializers' => [
                'Application\Model\Initializer' => function($instance, \Zend\ServiceManager\ServiceLocatorInterface $serviceLocator){
                    if ($instance instanceof AdapterAwareInterface)
                    {
                        $instance->setDbAdapter($serviceLocator->get('Zend\Db\Adapter\Adapter'));
                    }
                }

            ],
    'invokables' => [
        'ExampleModel' => 'Application\Model\ExampleModel'
    ],

I execute methods from model by:

$this->getServiceLocator()->get('ExampleModel')->fetchAllStudents();

Solution

  • You should do 2 things with your code. First, implement AdapterAwareInterface properly. Second, create an initializer which injects the adapter into your model. Consider the code below:

    ...
    
    'initializers' => [
        function($instance, ServiceLocatorInterface $serviceLocator){
                if ($instance instanceof AdapterAwareInterface) {
                    $instance->setDbAdapter($serviceLocator->get('Zend\Db\Adapter\Adapter'));
                }
        }
    ]
    
    ...
    
    abstract class AbstractModel implements AdapterAwareInterface
    {
        protected $db;
    
        public function setDbAdapter(Adapter $adapter)
        {
            $this->db = adapter;
        }
    }
    
    ...
    
    'invokables' => [
        'ExampleModel' => 'Application\Model\ExampleModel'
    ]
    

    As you can see from above, after all, you don't need a factory for each your model. You can either register invokables or create an Abstract Factory to instantiate your models. See an example below:

    ...
    
    'abstract_factories' => [
        'Application\Model\AbstractFactory'
    ]
    
    ...
    
    class AbstractFactory implements AbstractFactoryInterface
    {
        public function canCreateServiceWithName(ServiceLocatorInterface $serviceLocator, $name, $requestedName)
        {
            return class_exists('Application\Model\'.$requestedName);
        }
    
        public function createServiceWithName(\Zend\ServiceManager\ServiceLocatorInterface $serviceLocator, $name, $requestedName)
        {
            $class = 'Application\Model\'.$requestedName();
    
            return new $class
        }
    }
    

    Hope this helps