Zend Framework can be daunting. Zend\Db even more so. Here is a recap. Start simple. Start from a controller. First objective: get hold of a database driver:


$config = $this->getServiceLocator()->get('Config');
$driver = $config['db'];

The site configuration is available as a service and the driver is nothing more than an array with the key database settings. The driver part in the driver in this recap is PDO. The dsn (data source name) part of the driver details what database type to choose: in this recap it is mysql. The file database.local.php in the autoload folder looks like this:


return array(
    'db' => array(
        'driver' => 'pdo',
        'dsn' => 'mysql:dbname=database-name;host=localhost',
        'username' => 'user-name',
        'password' => 'xxxxxxxx',
    ),
);

For a quick start look no further than the Zend\Db\Adapter\Adapter adapter:


$dbAdapter = new \Zend\Db\Adapter\Adapter($driver);

This adapter can also be accessed via \Zend\Db\Adapter\AdapterServiceFactory as a service if defined in the configuration file:


return array(
    'service_manager' => array(
        'factories' => array(
            'dbAdapter' => 'Zend\Db\Adapter\AdapterServiceFactory',
        ),
    ),   
);

Calling the service is now as easy as:


$dbAdapter = $this->getServiceLocator()->get('dbAdapter');

No need to inject the driver now, the factory method calls the configuration service by magic:


class AdapterServiceFactory implements FactoryInterface
{
    public function createService(ServiceLocatorInterface $serviceLocator)
    {
        $config = $serviceLocator->get('Config');
        return new Adapter($config['db']);
    }
}

The database adapter is nothing more than a container with configuration data and some basic methods such as query()


$sql = 'select * from customer';
$dbAdapter = new \Zend\Db\Adapter\Adapter($driver);
$results = $dbAdapter->query($sql);

$results is a \Zend\Db\Adapter\Driver\Pdo\Statement Object as in a prepared statement. To actually execute the query, perform:


$sql = 'select * from customer';
$dbAdapter = new \Zend\Db\Adapter\Adapter($driver);
$results = $dbAdapter->query($sql, 
\Zend\Db\Adapter\Adapter::QUERY_MODE_EXECUTE);

and now $results is a \Zend\Db\ResultSet\ResultSet Object. This object implements the Iterator interface so the first result is available via current() as an ArrayObject:


$result  = $results->current();
$customerName = $result->customer_name;

Ideally the results of a database query are custom objects and this is where hydration comes in:


$resultSetPrototype = new \Zend\Db\ResultSet\HydratingResultSet;
$resultSetPrototype->setObjectPrototype(new \Application\Model\Customer);
$dbAdapter = new \Zend\Db\Adapter\Adapter($driver, null, $resultSetPrototype);

A $resultSetPrototype is a special resultSet that allows the injection of a prototype, in this case a Customer object:


namespace Application\Model;

class Customer {
    public $customer_name;

    public function exchangeArray($data) {      
        $this->customer_name =  $data['customer_name'] ;
    }

    public function getCustomerName()  {
        return $this->customer_name;
    }
}

Note the presence of an exchangeArray method, it is used by the resultSet object to inject the row results into the object:


public function current() { 
    $data = parent::current();
    // the prototype gets cloned: typical prototype pattern
    $ao = clone $this->arrayObjectPrototype;
    if ($ao instanceof ArrayObject || method_exists($ao, 'exchangeArray')) {
           $ao->exchangeArray($data);
    }
    return $ao;     
}

The row result from the query is now available as a Customer object:


$result  = $results->current();
$customerName = $result->getCustomerName();
Advertisements