Cli-Config Helper -Multiple Entity Managers - doctrine-orm

I am using Doctrine 2.5 with Slim 3. I got two Entity Managers Master and Slave.
In the Cli-Config.php file when I am creating the helpers and passing the entity Managers and their connections as below,
$helpers = new Symfony\Component\Console\Helper\HelperSet([
'db' => new \Doctrine\DBAL\Tools\Console\Helper\ConnectionHelper($defaultEntityManager->getConnection()),
'em' => new \Doctrine\ORM\Tools\Console\Helper\EntityManagerHelper($defaultEntityManager),
'db_customer' => new \Doctrine\DBAL\Tools\Console\Helper\ConnectionHelper($customerEntityManager->getConnection()),
'em_customer' => new \Doctrine\ORM\Tools\Console\Helper\EntityManagerHelper($customerEntityManager),
]);
return $helpers;
Now in the console when I try the command
php vendor/doctrine/orm/bin/doctrine orm:schema-tool:create
the schema relating to $defaultEntityManager EntityManager is only getting created the schema relating to $customerEntityManager Entity Manager is not created.
Any idea/suggestions which I can try?

doctrine `s cli script expects 'em' to be defined in the HelperSet returned. That will be used to create the schema.
You can see it here
To solve this, one way is to create 2 directories like:
configA
configB
and place 2 different cli-config.php scripts in each:
$helpers = new Symfony\Component\Console\Helper\HelperSet([
'db' => new \Doctrine\DBAL\Tools\Console\Helper\ConnectionHelper($defaultEntityManager->getConnection()),
'em' => new \Doctrine\ORM\Tools\Console\Helper\EntityManagerHelper($defaultEntityManager),
]);
and
$helpers = new Symfony\Component\Console\Helper\HelperSet([
'db' => new \Doctrine\DBAL\Tools\Console\Helper\ConnectionHelper($customerEntityManager->getConnection()),
'em' => new \Doctrine\ORM\Tools\Console\Helper\EntityManagerHelper($customerEntityManager),
]);
Finally, run:
php ../vendor/doctrine/orm/bin/doctrine orm:schema-tool:create
from each directory
Creating own script
Alternatively, you could create your own script based on doctrine `s cli script, eg name it "doctrine.php":
#!/usr/bin/env php
<?php
use Symfony\Component\Console\Helper\HelperSet;
use Doctrine\ORM\Tools\Console\ConsoleRunner;
require_once __DIR__ . '/vendor/autoload.php';
$commands = [];
$helper1 = new Symfony\Component\Console\Helper\HelperSet([
'db' => new \Doctrine\DBAL\Tools\Console\Helper\ConnectionHelper($defaultEntityManager->getConnection()),
'em' => new \Doctrine\ORM\Tools\Console\Helper\EntityManagerHelper($defaultEntityManager),
]);
$helper2 = new Symfony\Component\Console\Helper\HelperSet([
'db' => new \Doctrine\DBAL\Tools\Console\Helper\ConnectionHelper($customerEntityManager->getConnection()),
'em' => new \Doctrine\ORM\Tools\Console\Helper\EntityManagerHelper($customerEntityManager),
]);
ConsoleRunner::run($helper1, $commands);
ConsoleRunner::run($helper2, $commands);
Place it on your project s root and run it as:
php doctrine.php orm:schema-tool:create

My solution is:
#!/usr/bin/env php
<?php
use Doctrine\ORM\Tools\Console\ConsoleRunner;
$commands = [];
$emList = [
$emFoo,
$emBar,
$emZoo
];
foreach ($emList as $em) {
$acpApp = ConsoleRunner::createApplication(ConsoleRunner::createHelperSet($em, $commands));
$acpApp->setAutoExit(false);
$acpApp->run();
}

Related

Laravel 5.5 - Notifications are not being queued?

I have the following notification class:
use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Notification;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
class ConfirmEmailNotification extends Notification implements ShouldQueue
{
use Queueable;
public function __construct()
{
//
}
public function via($notifiable)
{
return ['mail'];
}
public function toMail($notifiable)
{
$user = $notifiable;
$url = url('/register/confirm/'. $user->confirmation_token);
return (new MailMessage)
->subject('Confirm Email')
->markdown('emails.confirm', ['user' => $user, 'url' => $url]);
}
public function toArray($notifiable)
{
return [
//
];
}
}
In my controller I have the following:
$when = now()->addSeconds(30);
$user->notify((new ConfirmEmailNotification())->delay($when));
But nothing is getting added to the queue table - the emails is being fired instantly?
I configured the queue as follows.
In my env file:
QUEUE_DRIVER=database
In my config/queue.php I have renamed the table as follows:
'database' => [
'driver' => 'database',
'table' => 'queued_jobs',
'queue' => 'default',
'retry_after' => 90,
],
Run the following:
php artisan queue:table
php artisan migrate
php artisan queue:work
I've tried php artisan config:clear but no difference.
Any ideas chaps?
Fixed by restarting php artisan serve
In my case, i forgot to update the QUEUE_CONNECTION property in .env file.
After updating the QUEUE_CONNECTION to database it worked as intended.

Facebook PHP SDK 5.0 in Yii 2.0 framework (config file)

I was following this tutorial for setting up Facebook PHP SDK 5.0 extension in my Yii 2.0 project. And it works as expected, but every time (in any of the controllers) I need to use some of the features from here this, I need to make an instance like this:
$fb = new Facebook\Facebook([
'app_id' => '{app-id}',
'app_secret' => '{app-secret}',
'default_graph_version' => 'v2.5',
// . . .
]);
and later use it:
// Send a GET request
$response = $fb->get('/me');
// Send a POST request
$response = $fb->post('/me/feed', ['message' => 'Foo message']);
// Send a DELETE request
$response = $fb->delete('/{node-id}');
but I'm not sure how practical is this, to make an instance of an object in every action/controller where I need to use it. I want to add this data as a general data in the config file. So I tried something like this:
'components' => [
.
.
'facebook' => [
'class' => 'Facebook\Facebook',
'app_id' => '{app-id}',
'app_secret' => '{app-secret}',
'default_graph_version' => 'v2.5'
],
.
.
and later in the actions I want to take this value like:
$fb = Yii::$app->facebook;
and after that do all the operations mentioned above. So I want to generalize the values in the config file like all other extensions, but I keep getting the error:
Facebook\Exceptions\FacebookSDKException
Required "app_id" key not supplied in config and could not find fallback environment variable "FACEBOOK_APP_ID"
Is it possible this to be entered in web config file, and with that, to avoid creating the object with same credentials before each Facebook call?
EDIT 1:
Reply to #machour response:
I followed your suggestion and It was still throwing the same error. Then I found it working as follows:
<?php
namespace your\namespace;
use Facebook\Facebook;
class MyFacebook extends Facebook {
public $app_id = '{app-id}';
public $app_secret = '{app-secret}';
public $default_graph_version = 'v2.5';
public function __construct()
{
parent::__construct([
'app_id' => $this->app_id,
'app_secret' => $this->app_secret,
'default_graph_version' => $this->default_graph_version
]);
}
}
And then:
'components' => [
.
.
'facebook' => [
'class' => 'your\namespace\MyFacebook'
]
At some point this is acceptable solution, since the redundancy is eliminated. The keys are not only at one place.
But do you have any idea how to transfer all the keys to the config file instead of the MyFacebook class?
The problem is that Facebook\Facebook doesn't implement $app_id, $app_secret and $default_graph_version as public properties, so your parameters are not taken in account when Yii builds the object declared in your component.
One way to fix that is to create your own class that extends Facebook, with those public properties, and to correctly call Facebook\Facebook constructor from it's own constructor. And then point your configuration to that new class instead :
<?php
namespace your\namespace;
use Facebook\Facebook;
class MyFacebook extends Facebook {
public $app_id;
public $app_secret;
public $default_graph_version;
public function __construct()
{
parent::__construct([
'app_id' => $this->app_id,
'app_secret' => $this->app_secret,
'default_graph_version' => $this->default_graph_version
]);
}
}
And then:
'components' => [
.
.
'facebook' => [
'class' => 'your\namespace\MyFacebook',
'app_id' => '{app-id}',
'app_secret' => '{app-secret}',
'default_graph_version' => 'v2.5'
],
That should do the trick.

Silex and Doctrine - ORMException: Unknown Entity namespace alias [semi fixed]

I'm trying to use the Doctrine components in my app built using silex. I was able to get it to work - well almost.
I have my "User" entity and the corresponding repository
When doing
$app['em']->getRepository('Foo\Entity\User')->findAll()
works as expected, however when trying to make a custom query
$this->getEntityManager()
->createQuery(
'SELECT
u
FROM
Foo:User u
WHERE c.id = :x'
)
->setParameter('x',$in)
->getResult();
I get this exception
ORMException: Unknown Entity namespace alias 'Foo'
Please ignore the fact that I can make a select with findById() or findBy(array('id'=>$in)) the problem is with the custom query
This are my configs
$app['orm.em.options'] = array(
'mappings' => array(
array(
'type' => 'annotation',
'namespace' => 'Foo\Entity',
'alias' => 'core',
'path' => '%app.path%/src/Foo/Entity',
'use_simple_annotation_reader' => false,
)
));
and
$config = Setup::createAnnotationMetadataConfiguration(array(__DIR__."/src/Foo/Entity"));
$params = $app['db.options'];
$app['em'] = EntityManager::create($params, $config);
After some research possible solutions:
auto_mapping: true => tried, no success
registering the namespace => tried, not sure if right was done so may be the solution, please advice how to do it right
besides all this I have tried to search for git repos with similar 'usage' but didn't get it :(
UPDATE
for the moment I use the following line in my query and it works
FROM
InstaLikes\Entity\User u
When you create custom queries, you should use the fully namespace, in this case:
Foo\Entity\User
I am assuming you have checked the alias you have given in the mappings options?
$app['orm.em.options'] = array(
'mappings' => array(
array(
'type' => 'annotation',
'namespace' => 'Foo\Entity',
'alias' => 'core',
'path' => '%app.path%/src/Foo/Entity',
'use_simple_annotation_reader' => false,
)
));
Should that alias option not be set to Foo instead?

zf2 doctrine2 and Zend\Db\Adapter\Adapter using one db connection

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.

Zend 2 + doctrine 2 Auth Adapter

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.