I want to use doctrine db config to access to DBAL layer in doctrine, I have the following configuration in my doctrine db file config:
database.local.php
return array(
'doctrine' => array(
'connection' => array(
'orm_default' => array(
'driverClass' => 'Doctrine\DBAL\Driver\PDOPgSql\Driver',
'params' => array(
'host' => 'localhost',
'port' => '5432',
'user' => 'postgres',
'password' => '123456',
'dbname' => 'test'
)
)
)
)
);
and in my controller
IndexController.php
use Doctrine\DBAL\DriverManager;
public function testAction(){
$conn = DriverManager::getConnection($params, $config);
}
I want to use db config above in the getConnection function, is this possible?
If you've a db configuration in your local.php, so why don't you access it through the EntityManager ? Just like this :
public function testAction(){
$em = ->getServiceLocator()
->get('Doctrine\ORM\EntityManager');
$conn = $em->getConnection();
}
If you want to get it through the DriverManager :
$config = new \Doctrine\DBAL\Configuration();
$connectionParams = array(
'host' => 'localhost',
'port' => '5432',
'user' => 'postgres',
'password' => '123456',
'dbname' => 'test'
'driver' => 'pdo_pgsql',
);
$conn = DriverManager::getConnection($connectionParams, $config);
EDIT :
You can also get directly an instance of Doctrine\DBAL\Connection using the Registered Service names provided by Doctrine with your actual db configuration :
$conn = $this->getServiceLocator()->get('doctrine.connection.orm_default');
As the DriverManager::getConnection() method, this will return a Doctrine\DBAL\Connection which wraps the underlying driver connection.
Sure.
First of all you should use ServiceLocator
ServiceLocator are auto injected into classes that implements \Zend\ServiceManager\ServiceLocatorAwareInterface
AbstractActionController, of your zf2 controllers already implements this interface.
To use into a class (model by example) you should declare implements and two methods that are designed by interface, setServiceLocator and getServiceLocator.
<?php
namespace Security\Repository;
use Zend\ServiceManager\ServiceLocatorInterface;
use Zend\ServiceManager\ServiceLocatorAwareInterface;
class Repository implements ServiceLocatorAwareInterface
{
protected $serviceLocator;
public function setServiceLocator(ServiceLocatorInterface $serviceLocator)
{
$this->serviceLocator = $serviceLocator;
}
public function getServiceLocator()
{
return $this->serviceLocator;
}
}
Using ServiceLocator are easy to do anything on ZF2. Try To understand how it works to get the fully power of zf2.
$configArray = $this->getServiceLocator()->get('config');
$config = new \Doctrine\DBAL\Configuration();
$connectionParams = $configArray['doctrine']['connection']['orm_default']['params']
$conn = DriverManager::getConnection($connectionParams, $config);
Related
I'am building application on Silex, and I'am having some problems on very basic stuff. I used example from official documentation for using doctrine service provider, but no matter what i do $app[ 'db' ]->isConnected() returns false. Here is the code
$app = new Application();
$app->register(new DoctrineServiceProvider(), array(
'dbs.options' => array (
'mysql' => array(
'driver' => 'pdo_mysql',
'host' => 'localhost',
'dbname' => 'sevenbet',
'user' => 'root',
'password' => '',
'charset' => 'utf8',
)
),
));
Don't use multi dimension array, if you have one db config to provide, just use :
$app['db.options'] = array (
'driver' => 'pdo_mysql',
'host' => 'localhost',
'dbname' => 'mydb',
'user' => 'root',
'password' => 'root',
'charset' => 'utf8'
);
I`m trying to do unit-testing with CakePhP 2.3 and PHPUnit 2.7. I want to test the index function in my customer’s controller.
In my controller I have:
public function index() {
$this->Customer->recursive = -1;
$data = $this->paginate('Customer', array( 'Customer.status'=>'active'));
$this->set('customers', $data);
}
I tried to follow the examples in book.cakephp.org, so I created Fixture class in which I`m importing the Customer schema and all the records.
class CustomerFixture extends CakeTestFixture{
public $import = array('model' => 'Customer', 'records' => true);
}
And finally my test class looks like this:
class CustomersControllerTest extends ControllerTestCase {
public $fixtures = array('app.customer');
public function testIndex() {
$result = $this->testAction('/customers/index');
debug($result);
}
}
When I run my test I have the following error:
Database Error
Error: SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '8' for key 'PRIMARY'
Do you have any ideas what can be the problem?
In your database.php in app/Config folder you have to add a $test variable.
For example
class DATABASE_CONFIG {
public $default = array(
'datasource' => 'Database/Mysql',
'persistent' => true,
'host' => 'localhost',
'port' => 3306,
'login' => 'root',
'password' => 'xxxx',
'database' => 'mydatabase',
'encoding' => 'utf8'
);
public $test = array(
'datasource' => 'Database/Mysql',
'persistent' => false,
'host' => 'localhost',
'port' => 3306,
'login' => 'root',
'password' => 'xxxx',
'database' => 'mydatabase_test',
'encoding' => 'utf8'
);
}
Then your unit testing will use the mydatabase_test for testing your code. Because now it uses the default database.
I use doctrine2 with ZF2, some of my libraries work with Zend\Db\Adapter\Adapter, others with doctrine2. Now, they connect to database twice. Is it possible to use one db connection in doctrine and standard ZF2 db adapter?
The DoctrineORM module accepts a PDO resource or a service name where the instance can be located in the service manager instead of the usual connection params.
First step is to create a service factory which retrieves the PDO resource from the Zend\Db\Adapter\Adapter service
<?php
namespace Application\Db\Service;
use Zend\ServiceManager\FactoryInterface;
use Zend\ServiceManager\ServiceLocatorInterface;
use Zend\ServiceManager\Exception\ServiceNotCreatedException;
class PdoResourceFactory implements FactoryInterface
{
/**
* #param ServiceLocatorInterface $serviceLocator
* #return \PDO resource
*/
public function createService(ServiceLocatorInterface $services)
{
$dbAdapter = $services->get('Zend\Db\Adapter\Adapter');
$pdo = $dbAdapter->getDriver()->getConnection()->getResource();
if (!$pdo instanceof \PDO) {
throw new ServiceNotCreatedException('Connection resource must be an instance of PDO');
}
return $pdo;
}
}
Once you have the factory, it's just a case of adding it to the service manager, configuring the db params for Zend\Db\Adapter\Adapter and telling doctrine to use the existing PdoResource from the service manager to connect.
Assuming you did this all in one file, let's say dbconn.local.php...
<?php
return array (
'service_manager' => array(
'factories' => array(
'Zend\Db\Adapter\Adapter' => 'Zend\Db\Adapter\AdapterServiceFactory',
// include the pdo resource factory
'PdoResource' => 'Application\Db\Service\PdoResourceFactory',
),
),
// db adapter config
'db' => array(
'driver' => 'pdo',
'dsn' => 'mysql:dbname=database;host=127.0.0.1',
'username' => 'username',
'password' => 'password',
),
'doctrine' => array (
'connection' => array (
'orm_default' => array (
'driverClass' => 'Doctrine\DBAL\Driver\PDOMySql\Driver',
// use the resource from the zend adapter
'pdo' => 'PdoResource',
),
),
),
);
Sorry for posting this as new answer but I am not able to add a comment to Crisp's answer since my reputation is too low because I only registered to stackoverflow for writing this comment:
In the dbconn.local.php that Crisp posted be sure to set dbname to null like in the following snippet:
Addition to Crisp's answer:
<?php
return array(
'service_manager' => array(
'factories' => array(
'Zend\Db\Adapter\Adapter' => 'Zend\Db\Adapter\AdapterServiceFactory',
// the lazy way of Crisp's PdoResourceFactory:
'PdoResource' => function (ServiceLocatorInterface $services) {
$dbAdapter = $services->get('Zend\Db\Adapter\Adapter');
$pdo = $dbAdapter->getDriver()->getConnection()->getResource();
if (!$pdo instanceof \PDO) {
throw new ServiceNotCreatedException('Connection resource must be an instance of PDO');
}
return $pdo;
},
),
),
// db adapter config
'db' => array(
'driver' => 'pdo',
'dsn' => 'mysql:dbname=database;host=127.0.0.1',
'username' => 'username',
'password' => 'password',
),
'doctrine' => array (
'connection' => array (
'orm_default' => array (
'driverClass' => 'Doctrine\DBAL\Driver\PDOMySql\Driver',
// use the resource from the zend adapter
'pdo' => 'PdoResource',
// important addition to Crisp's answer:
'params' => array(
'dbname' => null,
),
),
),
),
);
And now here is why this is important:
When calling
$em->getConnection()->getDatabase();
on your EntityManager without having set the dbname to null you will get "database" as the name of your database because this is the default value which is set by the module.config.php of the DoctrineORMModule as you can see here. Setting the dbname to null will cause your Doctrine\DBAL\Driver\PDOMySql\Driver which extends Doctrine\DBAL\Driver\AbstractMySQLDriver to load the name of the database via SELECT DATABASE() from the database itself as you can see here.
Also not setting the dbname to null (or to the correct database name) will cause the schemaInSyncWithMetadata() function of the Doctrine\ORM\Tools\SchemaValidator to always return false since it cannot load the current database setup because it uses the Doctrine\ORM\Tools\SchemaTool which uses the EntityManager's Connection which thinks that the database being used is called "database".
So I hope someone can use this information to save some time. I wasted half the day to figure that out.
And many thanks to Crisp again for his answer that saved me a lot of time.
I have the following in one of my routes
$rules = array(
'name' => 'Required',
'subject' => 'Required',
'message' => 'Required',
'email' => 'Required|Email',
'recaptcha_response_field' => 'required|recaptcha'
);
$validator = Validator::make(Input::all(), $rules);
if($validator->fails()){
return Redirect::to('contact')->withInput()->withErrors($validator);
}else{
$data = array('name' => Input::get('name'),
'email' => Input::get('email'),
'text' => Input::get('message'),
'subject' => Input::get('subject'));
Queue::push('ContactQueue', $data);
return Redirect::to('contact')->with('success', 'Message sent successfully');
}
I am trying to write a unit test for the success scenario, I have the following:
public function testSuccess(){
Validator::shouldReceive('make')->once()->andReturn(Mockery::mock(['fails' => false]));
Queue::shouldReceive('push')->once();
$this->call('POST', '/contact');
$this->assertRedirectedTo('/contact');
}
But I keep receiving the following error when trying to run phpunit:
BadMethodCallException: Method Illuminate\Queue\QueueManager::connected() does not exist on this mock object
Any ideas?
Putting Queue::shouldReceive('connected')->once();
after Queue::shouldReceive('push')->once();
solved this.
I'm looking for a tutorial on authentication with Zend 2 and Doctrine 2.
In particular the creation of the controller and adapter.
The official documentation is too global not help me enough.
thank you
EDIT:
i use "Doctrine Entity" (namespace User\Entity;)
The Entity is register in module.config.php file :
'doctrine' => array(
'driver' => array(
__NAMESPACE__ . '_driver' => array(
'class' => 'Doctrine\ORM\Mapping\Driver\AnnotationDriver',
'cache' => 'array',
'paths' => array(__DIR__ . '/../src/' . __NAMESPACE__ . '/Entity')
),
'orm_default' => array(
'drivers' => array(
__NAMESPACE__ . '\Entity' => __NAMESPACE__ . '_driver'
)
)
),
)
But now, how can i point my identityClass key to my adapter ?
Controller :
use Zend\Mvc\Controller\AbstractActionController,
Zend\View\Model\ViewModel,
Zend\Authentication\AuthenticationService,
Doctrine\ORM\EntityManager,
DoctrineModule\Authentication\Adapter\ObjectRepository as DoctrineAdapter,
User\Entity\User,
User\Form\UserForm;
class UserController extends AbstractActionController
{
protected $em;
public function setEntityManager(EntityManager $em)
{
$this->em = $em;
}
public function getEntityManager()
{
if (null === $this->em)
$this->em = $this->getServiceLocator()->get('Doctrine\ORM\EntityManager');
return $this->em;
}
public function getRepository()
{
if (null === $this->em)
$this->em = $this->getEntityManager()->getRepository('User\Entity\User');
return $this->em;
}
public function loginAction()
{
....
????????????
$adapter = new DoctrineAdapter();
$adapter->setIdentityValue($username);
$adapter->setCredentialValue($password);
$auth = new AuthenticationService();
$result=$auth->authenticate($adapter);
????????????
}
}
I've got this error : Call to a member function getRepository() on a non-object in ...doctrine\doctrine-module\src\DoctrineModule\Options\AuthenticationAdapter.php on line 132
line 123 : return $this->objectManager->getRepository($this->identityClass);
There are lots of ways to do it, but DoctrineModule for zf2 ships with a doctrine based authentication adapter (DoctrineModule\Authentication\Adapter\ObjectRepository). There is also a factory to create the adapter (DoctrineModule\Service\AuthenticationAdapterFactory). DoctrineMongoODMModule has it's module.config.php set up to use these services. (Note that the factory and adapter will work with ORM, but I'm not sure if the config keys have been added to DoctrineORMModule yet - perhaps someone who reads this would like create a PR for that?) These are the relevant config keys:
'authenticationadapter' => array(
'odm_default' => array(
'objectManager' => 'doctrine.documentmanager.odm_default',
'identityClass' => 'Application\Model\User',
'identityProperty' => 'username',
'credentialProperty' => 'password',
'credentialCallable' => 'Application\Model\User::hashPassword'
),
),
The identityClass is the doctrine document that represents your authenticated user. The identityProperty is the normally the username. getUsername will be called by the adapter to access this. credentialProperty is normally the password. getPassword will be called by the adapter to access this. credentialCallable is optional. It should be a callable (method, static method, closure) that will hash the credentialProperty - you don't need to do this, but it's normally a good idea. The adapter will expect the callable to have the following form: function hashPassword($identity, $plaintext).
To get the authentication adapter use:
$serviceLocator->get('doctrine.authenticationadapter.odm_default');
Note that all this only gives you an authetication adapter, it doesn't actually do the authentication. Authentication is done something like this:
$adapter = $serviceLocator->get('doctrine.authenticationadapter.odm_default');
$adapter->setIdentityValue($username);
$adapter->setCredentialValue($password);
$authService = new Zend\Authentication\AuthenticationService
$result = $authService->authenticate($adapter);
This will store the whole doctrine document of the authenticated user in the session object. If you want to store only the document ID in the session object, and retrieve the rest of the authetnicated user document form the DB each request, then take a look at DoctrineModule\Authentication\Storage\ObjectRepository. This provides a new StorageInterface for the Zend\Authentication\AuthenticationService.