简体   繁体   中英

Easiest way to access MySQL Database in Zend Framework 2 Models

I am a little confused with how things work in ZF2. I need my model file to access the db, run a query and return the results to the controller.

So, I configured things this way:

/config/autoload/global.php

return array(
'db' => array(
    'driver'         => 'Pdo',
    'dsn'            => 'mysql:dbname=zf2tutorial;host=localhost',
    'driver_options' => array(
        PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'UTF8\''
    ),
),
'service_manager' => array(
    'factories' => array(
        'Zend\Db\Adapter\Adapter'
                => 'Zend\Db\Adapter\AdapterServiceFactory',
    ),
    'aliases' => array(
        'db' => 'Zend\Db\Adapter\Adapter',
    ),
),

);

/config/autoload/local.php

return array(
    'db' => array(
        'username' => 'YOUR USERNAME HERE',
        'password' => 'YOUR PASSWORD HERE',
    ),
);

/module/MyModule/src/MyModule/Controller/MyController.php

    //Trying to access the DB service in controller.
    $db = $this->getServiceLocator()->get('db');

I think I am able to access it in the controller, but when I try to find it in the MyModel.php file, it fails.

/module/MyModule/src/MyModule/Model/MyModel.php

   //Trying to access the DB service in Model -> Results in FATAL error. ServiceLocator not found.
    $db = $this->getServiceLocator()->get('db');

What is the best and easiest way for all my models and controllers in a Module to have access to the database?

Thanks

You can access any service from the service manager within a controller using $this->getServiceManager() ; providing the controller class extends Zend\\Mvc\\Controller\\AbstractActionController

For example

class FooController extends AbstractActionController {
  public function barAction() {
    $serviceManager = $this->getServiceLocator();
  }
}

The reason this works is AbstractActionController implements ServiceLocatorAwareInterface (and therefore has the methods called set/getServiceLocator() ). By default the service manager is injected into the controller when it is created.

In order to inject the service manager into any other service you will need to also follow a similar process, but inject it manually.

First implement the interface

use Zend\ServiceManager\ServiceLocatorAwareInterface;
use Zend\ServiceManager\ServiceLocatorInterface;

class MyClass implements ServiceLocatorAwareInterface {

  protected $serviceLocator;      

  public function setServiceLocator(ServiceLocatorInterface $serviceLocator) {
    $this->serviceLocator = $serviceLocator; 
  }
  //...
}

Then create a factory to inject it (there are a few ways to do so)

Module.php

public function getServiceConfig() {
   return array(
     'factories' = array(
        'MyClass' => function($serviceManager) {
           $myClass = new MyClass();
           $myclass->setServiceLocator($serviceManager);

           return $myClass;
        }
     ),
   );
}

A few things to mention :

  • Its generally a bad idea to inject the service manager into a class as it is more than likely you will only need other instances that the service manager should supply. It would make more sense to fetch these (such as your database adapter) in the factory and then inject them into the class. Anyone using your adapter will then know that it depends on these services rather than the service manager.

  • It is considered bad design to have you "models" or "entities" aware of anything but their own properties. I would suggest reading up on the single responsibility principle and known design patterns for persisting your domain models (like an object relational mapper (ORM) or the data mapper pattern)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM