Symfony3 - multiple Entity Managers and Connections - php

I tried to create an entity from a table in a pre-existing database :
php bin/console doctrine:mapping:import --force AppBundle yml --filter="someTable"
But a message showed up stating :
Table someTable has no primary key. Doctrine does not support reverse
engineering from tables that don't have a primary key.
I checked, and in the DB, there were some tables without any PK (and I cannot change that).
So I read this page : http://symfony.com/doc/current/doctrine/multiple_entity_managers.html
... and tried this solution on github :
https://github.com/doctrine/DoctrineBundle/issues/441
My config.yml is like this :
doctrine:
dbal:
default_connection: default
connections:
default:
driver: pdo_mysql
host: "%database_host%"
port: "%database_port%"
dbname: "%database_name%"
user: "%database_user%"
password: "%database_password%"
charset: UTF8
mapping_types:
enum: string
forMapping:
driver: pdo_mysql
host: "%database_host%"
port: "%database_port%"
dbname: "%database_name%"
user: "%database_user%"
password: "%database_password%"
charset: UTF8
schema_filter: someTable
orm:
auto_generate_proxy_classes: "%kernel.debug%"
naming_strategy: doctrine.orm.naming_strategy.underscore
auto_mapping: true
default_entity_manager: default
entity_managers:
default:
connection: default
mappings:
AppBundle:
type: yml
dir: Resources/config
forMapping:
connection: forMapping
mappings:
AppBundle:
type: yml
dir: Resources/config
But when I try :
php bin/console doctrine:mapping:import --em=forMapping --filter="someTable" AppBundle yml
I get :
[InvalidArgumentException] Doctrine ORM Manager named "forMapping" does not exist.
Emptied the cache, but nope. Any help appreciated.
MC

Sorry, I goofed on my previous answer.
How about you try the command like this instead:
php bin/console doctrine:mapping:import "AppBundle" yml --em=forMapping --filter="someTable"
Does it make a difference? I see from a command line using the --help, it show in that order.

[Solved] Was due to the "auto_mapping". Correct sequence seems to be :
orm:
default_entity_manager: default
entity_managers:
auto_mapping: true
default:
connection: default
mappings:
AppBundle:
type: yml
dir: Resources/config
# See https://github.com/doctrine/DoctrineBundle/issues/441
forMapping:
connection: forMapping
mappings:
AppBundle:
type: yml
dir: Resources/config
It works one step further to the next error message. When I try :
php bin/console doctrine:mapping:import "AppBundle" yml --em=forMapping
The following error message pops up :
[Symfony\Component\Debug\Exception\ContextErrorException]
Warning: preg_match(): Delimiter must not be alphanumeric or backslash
Ok, let's see to this. The schema_filter was wrong. Correct code is :
schema_filter: ~^spip_rubriques$~
My entity has been correctly generated. I thank you all for your help.
MC

It looks like your "forMapping" is not correct in
orm:
entity_managers:
#problem here
forMapping:
Try to find out what is going wrong here

Related

How to load doctrine fixtures if we have multiple databases and connections

I used this documentation : https://symfony.com/doc/4.4/doctrine/multiple_entity_managers.html
So now I can create new databases named legacy and Project like this
doctrince.yaml:
doctrine:
dbal:
default_connection: legacy
connections:
legacy:
driver: pdo_mysql
host: "%env(database_host)%"
port: "%env(database_port)%"
dbname: "%env(database_name)%"
user: "%env(database_user)%"
password: "%env(database_password)%"
charset: UTF8
project:
driver: pdo_mysql
host: "%env(database_host_project)%"
port: "%env(database_port_project)%"
dbname: "%env(database_name_project)%"
user: "%env(database_user_project)%"
password: "%env(database_password_project)%"
charset: UTF8
orm:
default_entity_manager: legacy
entity_managers:
legacy:
connection: legacy
mappings:
Legacy:
is_bundle: false
type: annotation
dir: "%kernel.project_dir%/..."
prefix: '...'
alias: Legacy
project:
connection: project
auto_mapping: true
mappings:
Project:
is_bundle: false
type: annotation
dir: "%kernel.project_dir%/src/Entity"
prefix: 'App\Entity'
alias: Project
Now I have several Fixture classes all of them depend on each other and also some will create fixture for legacy and some will create for project.
Now my question is when I do:
php bin/console doctrine:fixtures:load --em=legacy
It runs the appfixtures of the project but not the of the bundle.
and then i get this error:
The class .. was not found in the chain configured namespaces ....
My question is now how can I load fixtures on multiple databases with multiple connections.
Thanks in advance.
You should read this doc : https://symfony.com/doc/current/doctrine/multiple_entity_managers.html
I think it may solve your problem as this is exactly what you trying to do.
If you have to create a fixture for legacy just use :
$entityManager = $this->getDoctrine()->getManager('legacy');`
else if it is for project use
$entityManager = $this->getDoctrine()->getManager('project');`
Also, if you change doctrine.dbal.default_connection, entityManager will run against the defined connection.
So you can try to create group of fixtures.
And then run fixtures for project :
Edit config for test environment
#config/packages/test/doctrine.yaml
doctrine:
dbal:
default_connection: 'project'
Then run fixture for 'project' group
> php bin/console doctrine:fixtures:load --group=project
Then do the same thing for 'legacy'

Symfony 4, Doctrine and AWS RDS read replica usage

I'm about to embark on using RDS with a master read/write and slave read-only setup.
I've read about the Doctrine MasterSlaveConnection type.
However, there will be some endpoints I create that I would like to use the read-only replica (most of my GET endpoints) and some will need to write data (PUT, PATCH, DELETE endpoints).
I'm also using API Platform.
What is the best way of achieving this in Symfony 4 and Doctrine 2?
What I have done in the past is to just use different connections.
Something like:
doctrine:
dbal:
default_connection: default
connections:
default:
# This is your Master
url: '%env(DATABASE_URL)%'
driver: 'pdo_mysql'
server_version: '5.7'
charset: utf8mb4
slave:
# This would be the slave
url: '%env(DATABASE_SLAVE_URL)%'
driver: 'pdo_mysql'
server_version: '5.7'
charset: utf8mb4
orm:
default_entity_manager: default
entity_managers:
default:
connection: default
mappings:
Main:
is_bundle: false
type: annotation
dir: '%kernel.project_dir%/src/Entity'
prefix: 'App\Entity'
alias: Main
slave:
connection: slave
mappings:
Main:
is_bundle: false
type: annotation
dir: '%kernel.project_dir%/src/Entity'
prefix: 'App\Entity'
alias: Main
https://symfony.com/doc/current/doctrine/multiple_entity_managers.html
Then in your controllers or business logic you can either choose to use the default entity manager:
// Controller
$this->getDoctrine()->getEntityManager();
Or you can get the slave connection:
// Controller
$this->getDoctrine()->getEntityManager('slave');
If you need this to work just on all requests without having to create special actions for everything then your best bet is to decorate the Collection and Item DataProviders for doctrine.
https://symfony.com/doc/current/service_container/service_decoration.html
https://github.com/api-platform/core/blob/master/src/Bridge/Doctrine/Orm/CollectionDataProvider.php
https://github.com/api-platform/core/blob/master/src/Bridge/Doctrine/Orm/ItemDataProvider.php
So basically you need to change what manager is chosen based on the $opperationName something like:
if($opperationName === 'GET'){
$manager = $this->managerRegistry->getManager('slave');
} else {
$manager = $this->managerRegistry->getManager();
}
You actually don't need to setup multiple entity managers, nor is it preferable as handling one entity with multiple entity managers is hard.
Using Doctrine 2.2, you can setup slaves/replicas directly from configuration without needing an extra entity manager:
See the config reference here:
https://www.doctrine-project.org/projects/doctrine-bundle/en/2.2/configuration.html#configuration-overview
Example:
doctrine:
dbal:
default_connection: default
connections:
default:
dbname: '%env(DATABASE_DBNAME)%'
user: '%env(DATABASE_USER)%'
password: '%env(DATABASE_PASSWORD)%'
host: '%env(DATABASE_HOST)%'
driver: 'pdo_mysql'
server_version: '5.7'
charset: utf8mb4
default_table_options:
charset: utf8mb4
collate: utf8mb4_unicode_ci
slaves:
ro_replica:
dbname: '%env(REPLICA_DBNAME)%'
user: '%env(REPLICA_USER)%'
password: '%env(REPLICA_PASSWORD)%'
host: '%env(REPLICA_HOST)%'
charset: utf8mb4
Thank you #Chase for the solution. You have made my day. Although it works for me in 'dev' environment I had a problem when switched to 'prod'. I was getting an error that an Entity can not be found. The solution came from this post - thanks #xabbuh. Basically I had to add default_entity_manager: name_of_default_em to doctrine.yml. Here is the copy of the code:
# config/packages/prod/doctrine.yaml
doctrine:
orm:
default_entity_manager: BOE <- add this line to let know prod about default em
auto_generate_proxy_classes: false
metadata_cache_driver:
type: service
id: doctrine.system_cache_provider
query_cache_driver:
type: service
id: doctrine.system_cache_provider
result_cache_driver:
type: service
id: doctrine.result_cache_provider
# ...

Symfony 4 Doctrine 2, Mapping entity, error table has no primary key,

A symfony noob here. Been trying since morning to map entity/s of the database using Doctrine via console throws up no primary key error. The mysql server is a remote one which I unfortunately only have read access and I am not able to create a primary key. I did see a few questions on SO with the exact same issue but they were unanswered and old.
I tried https://medium.com/#joaoneto/solves-doctrine-orm-error-with-tables-without-primary-key-on-mysql-when-mapping-the-database-1ce740610b51
but again it throws up error regarding empty columns.
Call to a member function getColumns() on null
My doctrine.yaml. Obviously I altered the connection details.
doctrine:
dbal:
default_connection: default
connections:
# configure these for your database server
default:
driver: 'pdo_mysql'
host: 'localhost'
port: '3306'
dbname: 'symfony_test_db'
user: 'root'
password: ''
charset: utf8mb4
customer:
driver: 'pdo_mysql'
host: 'xxx.xxx.xx.xxx'
port: '3306'
dbname: 'sg3_symfony_db'
user: 'sguser'
password: 'password'
charset: UTF8
backoffice:
driver: 'pdo_mysql'
host: 'localhost'
port: '3306'
dbname: 'back_office'
user: 'backoffice_user'
password: 'password'
charset: UTF8
one:
driver: 'pdo_mysql'
host: 'xxx.xxx.xx.xxx'
port: '3306'
dbname: 'one_db'
user: 'one_user'
password: 'password'
charset: UTF8
staging:
driver: 'pdo_mysql'
host: 'xxx.xxx.xx.xxx'
port: '3306'
dbname: 'staging'
user: 'staginguser'
password: 'password'
charset: UTF8
# With Symfony 3.3, remove the `resolve:` prefix
#url: '%env(resolve:DATABASE_URL)%'
orm:
default_entity_manager: default
entity_managers:
default:
connection: default
#auto_mapping: true
mappings:
Main:
is_bundle: false
type: annotation
dir: '%kernel.project_dir%/src/Entity/Main'
prefix: 'App\Entity\Main'
alias: Main
customer:
connection: customer
mappings:
Customer:
is_bundle: false
type: annotation
dir: '%kernel.project_dir%/src/Entity/Customer'
prefix: 'App\Entity\Customer'
alias: Customer
backoffice:
connection: backoffice
mappings:
Backoffice:
is_bundle: false
type: annotation
dir: '%kernel.project_dir%/src/Entity/Backoffice'
prefix: 'App\Entity\Backoffice'
alias: Backoffice
one:
connection: mt4
mappings:
One:
is_bundle: false
type: annotation
dir: '%kernel.project_dir%/src/Entity/One'
prefix: 'App\Entity\One'
alias: One
staging:
connection: staging
mappings:
staging:
is_bundle: false
type: annotation
dir: '%kernel.project_dir%/src/Entity/Staging'
prefix: 'App\Entity\Staging'
alias: Staging
CLI command I use to map but fails.
php bin/console doctrine:mapping:convert --from-database annotation --force --em=one ./src/Entity/One/ --verbose
In this case, sometimes you need to walk around.
This error:
Table ____ has no primary key. Doctrine does not support reverse
engineering from tables that don’t have a primary key.
So.
Doctrine can not work on tables that have no primary key.
In MySQL, create tables without PK will always be a bad idea, but, in some cases (or legacy systems) that not have PKs on some tables, you still can use Doctrine as ORM.
However, by default (and I believe this will not change) if your database has tables without primary key Mapping simply will not work.
The more fast way to solve this is override the vendor class DatabaseDriver, in the namespace:
namespace Doctrine\ORM\Mapping\Driver;
On line 289, change:
if ( ! $table->hasPrimaryKey()) {
continue;
// throw new MappingException(
// "Table " . $table->getName() . " has no primary key. Doctrine does not ".
// "support reverse engineering from tables that don't have a primary key."
// );
}
To avoid any future problems, after mapping your database, return the settings to avoid any problems later.
Good luck!
Reference: Solves Doctrine ORM Error with tables without Primary Key on MySQL when mapping the database.
Not a very clean solution but for the moment I managed to do it by, exporting the schema of tables I need and recreating them on my local server. Forcing Pk's on the tables that did not have PK defined. This created entity class files instantly and worked like a charm.

Doctrine is not loading entities namespaces

After searching and debbuging I figured out that doctrine is not loading my entities namespaces. I will show you my project config files
AppKernel.php
new CEOC\PresentacionOfertaBundle\CEOCPresentacionOfertaBundle(),
new CEOC\ContactoBundle\CEOCContactoBundle(),
new CEOC\CoreBundle\CEOCCoreBundle(),
config.yml
# Doctrine Configuration
doctrine:
dbal:
driver: pdo_pgsql
host: '%database_host%'
port: '%database_port%'
dbname: '%database_name%'
user: '%database_user%'
password: '%database_password%'
charset: UTF8
orm:
entity_managers:
default:
filters:
softdeleteable:
class: Gedmo\SoftDeleteable\Filter\SoftDeleteableFilter
enabled: true
orm:
auto_generate_proxy_classes: '%kernel.debug%'
naming_strategy: doctrine.orm.naming_strategy.underscore
auto_mapping: true
I have one entity under CEOCContactoBundle (CEOCContactoBundle:Organismo) created by doctrine:generate:entity(it worked fine!) then I did the crud with doctrine:generate:crud(it worked fine!!) but when I'm accessing I got an ORMException: Unknown Entity namespace alias 'CEOCContactoBundle' when I'm calling the EntityManager.
After that I found that the array $this->_attributes['entityNamespaces'] from Configuration.php under ORM was empty.
Why Doctrine recognize my entities namespace when I created them, when I did the crud but it does not when I using the entity manager?!!
I created my project following these steps:
composer create-project symfony/framework-standard-edition
composer update
Thanks in advance.

Database does not have any mapping information Symfony2 Doctrine

NOTE: Its not a Duplicate issue cause I have tried everything I get on google but nothing have helped us.
I am trying to import Tables using Doctrine Reverse Engineering tool, but I m getting this message:
Database does not have any mapping information.
My Connection Details in Config.yml
doctrine:
dbal:
default_connection: default
connections:
default:
driver: pdo_mysql
host: localhost
port: null
dbname: pixel_ashish
user: root
password: abc123
charset: UTF8
schema_filter: ~^(?!some_table1|some_table2)~
orm:
default_entity_manager: default
auto_generate_proxy_classes: true
proxy_dir: "%kernel.cache_dir%/doctrine/orm/Proxies"
proxy_namespace: Proxies
resolve_target_entities: []
What I have tried So Far:
Running php app/console doctrine:mapping:import --force AcmeBlogBundle xml
gives same error
Tried to convert mapping also which does not make any sense cause mappings are not there but still tried didn't worked out.
Created a new project and tried above given configuration didn't worked.
Now I am out of ideas please help me to solve this.
You need to create some mapping information in your config.
You can do it by passing auto_mapping: true under orm section:
doctrine:
orm:
auto_mapping: true
or by manually defining it under orm section:
doctrine:
orm:
default_entity_manager: default
entity_managers:
default:
connection: default
mappings:
YourBundleName:
type: "xml"
dir: "Entity"
prefix: "Your\BundleName\Entity"

Categories