I am used ZF2 for creating new applications.
We have some issue regarding db connection under controller and model file.
We have put all database credential in "global.php" and "db.local.php" and also fetch db adapter access in our "Module.php" file but we have not fetch database connectivity in controller and model files and don't run query under controller and model.
Here is my code :
**global.php :**
return array(
'db' => array(
'driver'=> 'Pdo',
'dsn'=> 'mysql:dbname=pick_fire;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',
),
),
);
**db.local.php :**
<?php
return array(
'db' => array(
'driver' => 'Pdo',
'dsn' => 'mysql:dbname=pick_fire;host=localhost',
'username' =>'root',
'password' =>'123456',
'driver_options'=> array(
PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES UTF8'
),
),
'service_manager' => array(
'aliases' => array(
'db' => 'Zend\Db\Adapter\Adapter',
),
),);
----------------------------------------------
**Module.php :**
public function getServiceConfig()
{
return array(
'factories' => array(
'mail.transport' => function (ServiceManager $serviceManager) {
$config = $serviceManager->get('Config');
$transport = new Smtp();
$transport->setOptions(new SmtpOptions($config['mail']['transport']['options']));
return $transport;
},
),
);
return array(
'factories' => array(
'adapter' => function($serviceManager) {
$config = $serviceManager->get('config');
$dbAdapter = new \Zend\Db\Adapter\Adapter($config['db']);
return $dbAdapter;
}
),
);
}
----------------------------------------------
Please suggest me, how we get fetch database connection and run queries in our controller and model files.
Thank You in Advanced.
In your getServiceConfig() you have two return statements ... the second is never called.
This should work :
**Module.php :**
public function getServiceConfig()
{
return array(
'factories' => array(
'mail.transport' => function (ServiceManager $serviceManager) {
$config = $serviceManager->get('Config');
$transport = new Smtp();
$transport->setOptions(new SmtpOptions($config['mail']['transport']['options']));
return $transport;
},
'adapter' => function($serviceManager) {
$config = $serviceManager->get('config');
$dbAdapter = new \Zend\Db\Adapter\Adapter($config['db']);
return $dbAdapter;
}
),
);
}
Related
Why i'm getting this error even i have added all the classes already?
Unable to resolve service "Zend\Db\Adapter\Adapter" to a factory; are
you certain you provided it during configuration?
Here is my Module.php:
namespace Album;
use Album\Model\Album;
use Album\Model\AlbumTable;
use Zend\Db\ResultSet\ResultSet;
use Zend\Db\TableGateway\TableGateway;
class Module {
public function getAutoloaderConfig()
{
return array(
'Zend\Loader\ClassMapAutoloader' => array(
__DIR__ . '/autoload_classmap.php',
),
'Zend\Loader\StandardAutoloader' => array(
'namespaces' => array(
__NAMESPACE__ => __DIR__ . '/src/' . __NAMESPACE__,
),
),
);
}
public function getServiceConfig()
{
return array(
'factories' => array(
'Album\Model\AlbumTable' => function($sm) {
$tableGateway = $sm->get('AlbumTableGateway');
$table = new AlbumTable($tableGateway);
return $table;
},
'AlbumTableGateway' => function ($sm) {
$dbAdapter = $sm->get('Zend\Db\Adapter\Adapter');
$resultSetPrototype = new ResultSet();
$resultSetPrototype->setArrayObjectPrototype(new Album());
return new TableGateway('album', $dbAdapter, null, $resultSetPrototype);
},
),
);
}
public function getConfig()
{
return include __DIR__ . '/config/module.config.php';
}
}
UPDATED:
FILES - application.config.php:
return [
// Retrieve list of modules used in this application.
'modules' => [
'Zend\Router',
'Zend\Validator',
'Application',
'Album',
'Blog',
],
// These are various options for the listeners attached to the ModuleManager
'module_listener_options' => [
'module_paths' => [
'./module',
'./vendor',
],
'config_glob_paths' => [
// realpath(__DIR__) . '/autoload/{{,*.}global,{,*.}local}.php',
realpath(__DIR__) . '/autoload/{,*.}{global,local}.php',
],
'config_cache_enabled' => false,
// The key used to create the configuration cache file name.
'config_cache_key' => 'application.config.cache',
'module_map_cache_enabled' => false,
// The key used to create the class map cache file name.
'module_map_cache_key' => 'application.module.cache',
// The path in which to cache merged configuration.
'cache_dir' => 'data/cache/',
// 'check_dependencies' => true,
],
];
You may have missed a step from the tutorial you are following.
in config/autoload/global.php add:
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',
),
),
);
Probaly because the $sm->get('Zend\Db\Adapter\Adapter') is not a service but is a class to set up an Adapter and is not registered within the ServiceManager yet.
Create a factory which builds the Adapter class for you by injecting the Config into it. Then register this AdapterFactory, which returns your adapter, within your serviceConfig. Or you could use the default AdapterFactory of Zend, which uses the 'db' key within your configuration to setup the database adapter.
Registering the Adapter within your Application Module.php:
public function getServiceConfig()
{
return [
'factories' => [
\Zend\Db\Adapter\Adapter::class => \Zend\Db\Adapter\AdapterServiceFactory::class,
]
// rest of your configuration
];
}
See the documentation of ZF2 v2.4 - Setting up a database adapter
I'm getting the following error message with zend framework 2 application:
Missing instance/object for parameter driver for
Zend\Db\Adapter\Adapter::__construct (File:
C:\xampp\zendfw2\ZendSkeletonApplication\vendor\zendframework\zendframework\library\Zend\Di\Di.php:856)
My code is the following:
autoload/local.php:
return array(
'di' => array(
'instance' => array(
'Zend\Db\Adapter\Adapter' => array(
'parameters' => array(
'driver' => 'Zend\Db\Adapter\Driver\Pdo\Pdo',
),
),
'Zend\Db\Adapter\Driver\Pdo\Pdo' => array(
'parameters' => array(
'connection' => 'Zend\Db\Adapter\Driver\Pdo\Connection',
),
),
'Zend\Db\Adapter\Driver\Pdo\Connection' => array(
'parameters' => array(
'connectionInfo' => array(
'dsn' => "mysql:dbname=zendtest;host=localhost",
'username' => 'root',
'password' => '',
'driver_options' => array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'UTF8\''),
),
),
),
),
),
);
module.config.php:
return array(
'di' => array(
'Test2\Model\ManagerAbstract' => array(
'parameters' => array(
'adapter' => 'Zend\Db\Adapter\Adapter',
),
),
),
...);
ManagerAbstract.php:
namespace Test2\Model;
use Zend\Db\Adapter\Adapter;
use Zend\Db\Adapter\AdapterAwareInterface;
abstract class ManagerAbstract implements AdapterAwareInterface
{
protected $adapter;
public function setDbAdapter(Adapter $adapter)
{
$this->adapter = $adapter;
}
public function getUserList() {
$sql = new Sql($this->adapter);
$select = $sql->select();
$select->from(array('u'=>'tsrv_user'));
$select->where(array('username' => $username));
$statement = $sql->prepareStatementForSqlObject($select);
$results = $statement->execute();
return $results;
}
}
User.php:
namespace Test2\Model;
class User extends ManagerAbstract
{
public function __construct() {
}
}
And I call it in the Controller like:
$di = new Di();
$model = $di->get('Test2\Model\User');
$model->getUserList();
Can you please help me by pointing out what causes the error message?
I think the definition of the Zend\Db\Adapter\Adapter in your Di configuration isn't correct.
You can find here a correct way how to do that : Zend\Db Adapter instantiation through Zend Framework 2 Di.
I'm trying to create a ZF2 application with multiple databases. Based on a user, the database should be dynamically set.
Right now I've the following:
database.local.php
return array(
'db' => array(
'adapters' => array (
'master_db' => array(
'driver' => 'Pdo',
'dsn' => 'mysql:dbname=master_db;host=localhost',
'driver_options' => array(
PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'UTF8\''
),
'username' => 'USERNAME',
'password' => 'PASSWORD'
),
'tentant_db' => array(
'driver' => 'Pdo',
'dsn' => 'mysql:dbname=tenant_db;host=localhost',
'driver_options' => array(
PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'UTF8\''
),
'username' => 'USERNAME',
'password' => 'PASSWORD'
),
)
),
'service_manager' => array(
'abstract_factories' => array(
'Zend\Db\Adapter\AdapterAbstractServiceFactory',
)
),
);
For test purposes I've created a form that has a method to fetch some data and put it in a select box. The code to get the database connection is shown in the code below.
MyController.php (in some module)
//... some code
public function someAction(){
$dbAdapter = $this->getServiceLocator()->get('tentant_db');
$form = new AddEolConnectorForm($dbAdapter);
$viewModel = new ViewModel(array(
'form' => $form
));
return $viewModel;
}
//... some more code
My question is, how can I dynamically set the dbname for the tentant_db adapter in my controller (or module)?
Thanks for your help.
The config merge event is one of zend newer event's I believe. It triggers when zend is mergin the config array's which is perfect for the problem you are facing since you can override some array key's dynamically.
public function onMergeConfig(ModuleEvent $e)
{
$configListener = $e->getConfigListener();
$config = $configListener->getMergedConfig(false);
// I'm actually not sure if you have the route match here otherwise you may have to
// use some other method to retrieve the url.
$match = $e->getRouteMatch();
switch ($match) {
case 'first-dependency':
$config['db']['adapter'] => array(
'driver' => 'Pdo',
'dsn' => 'mysql:dbname=master_db;host=localhost',
'driver_options' => array(
PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'UTF8\''
),
'username' => 'USERNAME',
'password' => 'PASSWORD',
),
break;
case 'second-dependency':
$config['db']['adapter'] => array(
'driver' => 'Pdo',
'dsn' => 'mysql:dbname=tenant_db;host=localhost',
'driver_options' => array(
PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'UTF8\''
),
'username' => 'USERNAME',
'password' => 'PASSWORD',
),
break;
// Pass the changed configuration back to the listener:
$configListener->setMergedConfig($config);
}
Based on the above answer I've created to following:
Module.php
class Module implements AutoloaderProviderInterface
{
public function init(ModuleManager $moduleManager)
{
$events = $moduleManager->getEventManager();
// Registering a listener at default priority, 1, which will trigger
// after the ConfigListener merges config.
$events->attach(ModuleEvent::EVENT_MERGE_CONFIG, array($this, 'onMergeConfig'));
}
public function onMergeConfig(ModuleEvent $e)
{
$db = $this->getTentantDb();
$configListener = $e->getConfigListener();
$config = $configListener->getMergedConfig(false);
$config['db']['adapters']['tenant_db']['dsn'] = 'mysql:dbname='. $db .';host=localhost';
$configListener->setMergedConfig($config);
}
// Some more code
public function getTenantDb(){
$tenant_db = 'tenant_12345'
return $tenant_db;
}
}
I don't know if it is the best solution, but the above code is working. I think the next steps should be to put the code in a generic module or something so I can access it from all my modules.
i'm following this tutorial but got error Zend\ServiceManager\ServiceManager::get was unable to fetch or create an instance for Zend\Db\Adapter\Adapter
i've googling and tried all solution but no luck. please helppppp i'm depressed :|
FYI : i'm using this skeleton https://github.com/zendframework/ZendSkeletonApplication and go. i didn't install zend.
module.php
namespace Album;
// Add these import statements:
use Album\Model\Album;
use Album\Model\AlbumTable;
use Zend\Db\ResultSet\ResultSet;
use Zend\Db\TableGateway\Tabl`enter code here`eGateway;
class Module
{
public function getAutoloaderConfig()
{
return array(
'Zend\Loader\ClassMapAutoloader' => array(
__DIR__ . '/autoload_classmap.php',
),
'Zend\Loader\StandardAutoloader' => array(
'namespaces' => array(
__NAMESPACE__ => __DIR__ . '/src/' . __NAMESPACE__,
),
),
);
}
public function getConfig()
{
return include __DIR__ . '/config/module.config.php';
}
public function getServiceConfig()
{
return array(
'factories' => array(
'Album\Model\AlbumTable' => function($sm) {
$tableGateway = $sm->get('AlbumTableGateway');
$table = new AlbumTable($tableGateway);
return $table;
},
'AlbumTableGateway' => function ($sm) {
$dbAdapter = $sm->get('Zend\Db\Adapter\Adapter');
$resultSetPrototype = new ResultSet();
$resultSetPrototype->setArrayObjectPrototype(new Album());
return new TableGateway('album', $dbAdapter, null, $resultSetPrototype);
},
),
);
}
}
global.php
return array(
'db' => array(
'driver' => 'Pdo',
'dsn' => 'mysql:dbname=aaa;host=aaa',
'driver_options' => array(
PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'UTF8\''
),
),
'service_manager' => array(
'factories' => array(
'Zend\Db\Adapter\Adapter' => 'Zend\Db\Adapter\AdapterServiceFactory',
),
),
);
i read & tried these :
ZF2 - get was unable to fetch or create an instance for getAlbumTable
ServiceNotFoundException in ZendFramework 2, example from Rob Allen
always end up without clarity
This is because of DB configuration error, to solve this you have to configure DB in global.php in main config folder.Code is given below, Copy paste and Just change the db name and password,
return array(
'db' => array(
'driver' => 'Pdo',
'dsn' => 'mysql:dbname=zf2tutorial;host=localhost',
'driver_options' => array(
PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'UTF8\''
),
'username' => 'root',
'password' => ''
),
'service_manager' => array(
'factories' => array(
'Zend\Db\Adapter\Adapter'
=> 'Zend\Db\Adapter\AdapterServiceFactory',
),
),
);
The problem is with the following line in your module.php
$dbAdapter = $sm->get('Zend\Db\Adapter\Adapter');
The db configuration information in your global.php can not recognized by your program. As a resolve, you can transfer the configuration you have written on global.php to module.config.php.
My module.config.php is as follows:
<?php
return array(
'controllers' => array(
'invokables' => array(
'Album\Controller\Album' => 'Album\Controller\AlbumController',
),
),
'db' => array(
'driver' => 'Pdo',
'dsn' => 'mysql:dbname=zend;host=localhost',
'driver_options' => array(
PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'UTF8\''
),
),
// The following section is new and should be added to your file
'router' => array(
'routes' => array(
'album' => array(
'type' => 'segment',
'options' => array(
'route' => '/album[/:action][/:id]',
'constraints' => array(
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
'id' => '[0-9]+',
),
'defaults' => array(
'controller' => 'Album\Controller\Album',
'action' => 'index',
),
),
),
),
),
'view_manager' => array(
'template_path_stack' => array(
'album' => __DIR__ . '/../view',
),
),
);
And my getServiceConfig() under Module.php is as below:
public function getServiceConfig()
{
return array(
'factories' => array(
'db' => function($sm) {
echo PHP_EOL . "SM db-adapter executed." . PHP_EOL;
$config = $sm->get('config');
$config = $config['db'];
//print_r($config);
//exit();
$dbAdapter = new Adapter($config);
return $dbAdapter;
},
'Album\Model\AlbumTable' => function($sm) {
$tableGateway = $sm->get('AlbumTableGateway');
$table = new AlbumTable($tableGateway);
return $table;
},
'AlbumTableGateway' => function ($sm) {
$dbAdapter = $sm->get('db');
//print_r($dbAdapter);
//exit();
$resultSetPrototype = new ResultSet();
$resultSetPrototype->setArrayObjectPrototype(new Album());
return new TableGateway('album', $dbAdapter, null, $resultSetPrototype);
},
),
);
}
After that everything was working.
Note:
For some reason global.php was not read by Zend2 in my case.(Somebody needs to research further with that I suggest)local.php was still read. So I am still keeping my username and password information in local.php. Hope this will help you to get rid of this uncomfortable error.
This will work if you are getting problem on Ibm I series Server.
The cause of the problem is that IBMi cannot handle relative paths in the config.
I resolved it on my machine with the following
'config_glob_paths' => array( '/www/local/zf2/config/autoload/{,*.}{global,local}.php', ),
ie set 'config_glob_paths' to the full path instead of the relative path in application.config.php.
Note: if you are getting the error on local then pls check configruation file.
I just added the code below in "my_project / config / autoload / global.php" and it worked perfectly.
'service_manager' => array(
'factories' => array(
'Zend\Db\Adapter\Adapter' => 'Zend\Db\Adapter\AdapterServiceFactory',
),
I am using Oracle and let "username / password" in "local.php".
Thank you!
I have ZF2 tried following, but it does not give any query results with ZF1 works, ZF2 not workings. Is ZF2 database adapters incomplete, left as bug not resolved by ZF2 itself? Cause documentation tells to do so but it simply not working. Does ZF2 adapter works ever?
TestController.php
<?php
namespace Application\Controller;
//namespace Application\Model;
use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;
use Zend\Db\Adapter\Adapter;
use Zend\Debug\Debug;
class TestController extends AbstractActionController {
public function indexAction() {
$sql = "SELECT * FROM stackoverflow";
$statement = $this->adapter->query($sql);
$res = $statement->execute();
Debug::dump( $res );
exit;
}
}
Module.php
<?php
namespace Application;
use Zend\Mvc\ModuleRouteListener;
use Zend\Mvc\MvcEvent;
use Zend\Mvc\Router\Http;
class Module {
public function getServiceConfiguration()
{
return array(
'factories' => array(
'adapter' => function($sm) {
$config = $sm->get('config');
$dbAdapter = new \Zend\Db\Adapter\Adapter($config['db']);
return $dbAdapter;
}
),
);
}
}
global.php
<?php
return array(
// 'di' =>array(
// 'instance' =>array(
// 'PDO' => array(
// 'parameters' => array(
// 'dsn' => 'mysql:dbname=mydb;host=localhost',
// 'username' => 'mydb',
// 'password' => '',
// )
// ),
//
// 'User' => array(
// 'parameters' => array(
// 'pdo' => 'PDO'
// )
// )
// )
// ),
'db' => array(
'driver' => 'Pdo',
'dsn' => 'mysql:dbname=mydb;host=localhost',
'username' => 'mydb',
'password' => '',
// 'driver_options' => array(
// PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'UTF8\''
// ),
),
// 'service_manager' => array(
// 'factories' => array(
// 'Zend\Db\Adapter\Adapter' => 'Zend\Db\Adapter\AdapterServiceFactory',
// ),
// ),
);
The $res is a result set. You can read more about how to extract data from a result set in the ZF manual.
//I just started zf2 myself,but it seems like you can retrieve the data like this.
public function fetchAll()
{
$resultSet = $this->tableGateway->select();
return $resultSet;
}