Symfony 3.3 - Entity Manager injection into services with multiple database? - symfony-3.3

I have recently added a new database to my Symfony 3.3 application.
Then my services with injected entity manager are no longer working and return the following error:
Cannot autowire service "RouterBundle\Utils\RoutersUtils": argument
"$em" of method "__construct()" references class
"Doctrine\ORM\EntityManager" but no such service exists. Try changing
the type-hint to one of its parents: interface
"Doctrine\ORM\EntityManagerInterface", or interface
"Doctrine\Common\Persistence\ObjectManager".
So my config.yml file is now like :
# Doctrine Configuration
doctrine:
dbal:
default_connection: router
connections:
router:
driver: pdo_mysql
host: '%database_host%'
port: '%database_port%'
dbname: '%database_router_name%'
user: '%database_router_user%'
password: '%database_router_password%'
charset: utf8mb4
default_table_options:
charset: utf8mb4
collate: utf8mb4_unicode_ci
row_format: DYNAMIC
app:
driver: pdo_mysql
host: '%database_host%'
port: '%database_port%'
dbname: '%database_app_name%'
user: '%database_app_user%'
password: '%database_app_password%'
charset: utf8mb4
default_table_options:
charset: utf8mb4
collate: utf8mb4_unicode_ci
orm:
default_entity_manager: router
entity_managers:
router:
connection: router
mappings:
RouterBundle: ~
dql:
string_functions:
# Match agains should have the path to the Sha1 class created in the previous step
SHA1: RouterBundle\Extensions\Doctrine\Sha1
app:
connection: app
mappings:
AppBundle: ~
One of my service like :
<?php
namespace RouterBundle\Utils;
use Doctrine\ORM\EntityManager;
class RoutersUtils
{
protected $em;
public function __construct(EntityManager $em)
{
$this->em = $em;
}
...
and my services.yml ( I tried to add this arguments but doesn't work)
...
RouterBundle\Utils:
public: true
arguments:
- '#doctrine.dbal.router_connection'
...
Any idea how to inject the correct Entity Manager?
Can I also inject entity manager by default using the "default_entity_manager: router" parameters in teh config file ?
Thanks for the help !
Pierre

You cannot autowiring by using the EntityManagerInterface if you have many managers. You will have to pick the right manager in your service definition for each service.
RouterBundle\Utils:
$em: '#your_entity_manager_service'
PS : You should consider upgrading to sf3.4 as 3.3 is not maintenaited anymore. It also comes with local binding, which will be really useful for what you want to do.
See:
https://symfony.com/blog/new-in-symfony-3-4-local-service-binding

Related

application.yml config file in springboot

I had given application.yml like below
spring:
datasource:
driverClassName: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/user
username: root
password: abc123
jpa:
hibernate.ddl-auto: update
generate-ddl: true
show-sql: true
But I am getting
Failed to configure a DataSource: 'url' attribute is not specified and
no embedded datasource could be configured.
Help me to sort out this.
change the name of your database, 'user' is a reserved keyword!!!

NestJS cacheModule can't connect to Redis store with password

I'm trying to connect to my redis store in NestJS using CacheModule, I updated my store to put a password but now it's impossible to connect from NestJS (work perfectly with redis-cli and it works on nestJS before putting the password).
I have tried this:
import * as redisStore from 'cache-manager-redis-store'; // v2.0
#Module({
imports: [
CacheModule.register({
store: redisStore,
url: 'redis://:azerty#localhost:6379/0', // 'redis://h:azerty#localhost:6379/0' and 'redis://default:azerty#localhost:6379/0'
}),
],
controllers: [],
providers: [],
})
The connection string is working with redis-cli but not in NestJS, it throws ReplyError: WRONGPASS invalid username-password pair or user is disabled. or ReplyError: Ready check failed: NOAUTH Authentication required. (depends on the connection string)
I also tried the "normal" way:
CacheModule.register({
store: redisStore,
host: 'localhost',
port: 6379,
auth_pass: 'azerty', // also tried password: 'azerty'
}),
I got the same errors as the connection string one ReplyError: Ready check failed: NOAUTH Authentication required..
How can I make it works ?
REMINDER: always check if there is multiple instance of CacheModule in your project, just lost 1 day of work because of that.

Sylius\Component\Core\Model\Product::getMainTaxon() returns proxy insead of Taxoninterface

getMainTaxon() returns Proxy instead of TaxonInterface
I am doing migration from sylius 1.1 to sylius 1.5. Everything works fine except this error. I have no idea what should i do with this error.
My _sylius.yaml contains these entries:
sylius_product:
resources:
product:
classes:
repository: App\Repository\ProductRepository
model: App\Entity\Product
controller: App\Controller\ProductController
translation:
classes:
model: App\Entity\ProductTranslation
sylius_taxonomy:
resources:
taxon:
classes:
repository: App\Repository\TaxonRepository
model: App\Entity\Taxon
My doctrine.yaml looks like this:
doctrine:
dbal:
driver: 'pdo_mysql'
server_version: '5.7'
charset: UTF8
url: '%env(resolve:DATABASE_URL)%'
orm:
auto_generate_proxy_classes: '%kernel.debug%'
auto_mapping: true
mappings:
App:
is_bundle: false
type: yml
dir: '%kernel.project_dir%/config/doctrine'
prefix: 'App\Entity'
alias: App
Full error looks like this
Return value of Sylius\Component\Core\Model\Product::getMainTaxon() must be an instance of Sylius\Component\Core\Model\TaxonInterface or null, instance of Proxies__CG__\App\Entity\Taxon returned
Do you know what can cause this error and how to manage it?
finally I managed to solve this issue. Maybe it will help someone who migrates an application from legacy sylius.
In the past, I extended the Taxon entity and my Taxon.php looked like this
use Sylius\Component\Taxonomy\Model\Taxon as BaseTaxon;
class Taxon extends BaseTaxon {
The issue was I should have extended Sylius\Component\Core\Model\Taxon class so my entity file now looks like this
use Sylius\Component\Core\Model\Taxon as BaseTaxon;
class Taxon extends BaseTaxon {

Symfony 4 one entity, two entity Manager

Hello everyone, I'm trying to have 2 entityManagers for one entity in Symfony4 but I have some trouble to do this.
When I persist an entity it works,(For example if have two entity Mananagers : Customer and Default ,when I use Customer or Default to persist) but when I want to use Repository, The first entity Managare in doctrine.yaml is always used.
I have to do this because I have 2 databases. One in internet and one inside my intranet that i have created and I search to do is that when the user click one button for example. It update the database on internet.
config/packages/doctrine.yaml
doctrine:
dbal:
default_connection: default
connections:
default:
driver: pdo_mysql
host: **************
port: 3306
dbname: intranetDb
user: **********
password: *****
charset: UTF8
customer:
driver: pdo_mysql
host: internetDb
port: 3306
dbname: *********
user: *********
password: *********
charset: UTF8
orm:
default_entity_manager: default
entity_managers:
default:
connection: default
auto_mapping: false
mappings:
Main:
is_bundle: false
type: annotation
dir: '%kernel.project_dir%/src/Entity'
prefix: 'App\Entity'
alias: Main
customer:
connection: customer
auto_mapping: false
mappings:
Customer:
is_bundle: false
type: annotation
dir: '%kernel.project_dir%/src/Entity'
prefix: 'App\Entity'
alias: Main
MyController.php
..
$drug = $this->getDoctrine()->getRepository(Drug::class,'customer')->findAll() ;
..
This code always give me the data inside of default and if I put customer first inside of orm the customer is always given.
Some help will be welcome because I have this problem in few days and I have no Idea to solve this(It's probably because of symfony version that I didn't found solution inside forum).
Thank you.(And sorry for my bad English)
You can get the repository from an entity manager, instead of getting it from the ManagerRegistry returned by getDoctrine().
Example:
[...]
$this->getDoctrine()->getManager('manager_name')->getRepository('class_name');
[...]

deepstream error listen EADDRINUSE 127.0.0.1:6020

i try to run my first deepstream.io server from this link but i get this error :
error:
CONNECTION_ERROR | Error: listen EADDRINUSE 127.0.0.1:3003
PLUGIN_ERROR | connectionEndpoint wasn't initialised in time
f:\try\deep\node_modules\deepstream.io\src\utils\dependency-
initialiser.js:96
throw error
^
Error: connectionEndpoint wasn't initialised in time
at DependencyInitialiser._onTimeout
(f:\try\deep\node_modules\deepstream.io\src\utils\dependency-
initialiser.js:94:17)
at ontimeout (timers.js:386:14)
at tryOnTimeout (timers.js:250:5)
at Timer.listOnTimeout (timers.js:214:5)
and this is my code:
const DeepStreamServer = require("deepstream.io")
const C = DeepStreamServer.constants;
const server = new DeepStreamServer({
host:'localhost',
port:3003
})
server.start();
In deepstream 3.0 we released our HTTP endpoint, by default this runs alongside our websocket endpoint.
Because of this, passing the port option at the root level of the config no longer works (it overrides both the HTTP and websocket port options, as you can see in the screen capture provided, both endpoints are trying to start on the same port).
You can override each of these ports as follows:
const deepstream = require('deepstream.io')
const server = new deepstream({
connectionEndpoints: {
http: {
options: {
port: ...
}
},
websocket: {
options: {
port: ...
}
}
}
})
server.start()
Or you can define your config in a file and point to that while initialising deepstream[1].
[1] deepstream server configuration
One solution that i find is passing empty config object so inseted of :
const server = new DeepStreamServer({
host:'localhost',
port:3003
})
i'm just using this :
const server = new DeepStreamServer({})
and now everything work's well.
All the bellow is for Version 4.2.2 (last version by now)
I was having the same Port in use or config file not found errors. And i was using typescript and i didn't pay attention too to the output dir and build (which can be a problem when one use typescript and build). I was able to run the server in the end. And i had a lot of analysis.
I checked up the code source and i have seen how the config is loaded
const SUPPORTED_EXTENSIONS = ['.yml', '.yaml', '.json', '.js']
const DEFAULT_CONFIG_DIRS = [
path.join('.', 'conf', 'config'), path.join('..', 'conf', 'config'),
'/etc/deepstream/config', '/usr/local/etc/deepstream/config',
'/usr/local/etc/deepstream/conf/config',
]
DEFAULT_CONFIG_DIRS.push(path.join(process.argv[1], '..', 'conf', 'config'))
DEFAULT_CONFIG_DIRS.push(path.join(process.argv[1], '..', '..', 'conf', 'config'))
Also i tested different things and all. Here what i came up with:
First of all if we don't precise any parameter in the constructor. A config from the default directories will get to load. If there isn't then the server fail to run.
And one of the places where we can put a config is ./conf in the same folder as the server node script.
Secondly we can precise a config as a string path (parameter in the constructor). config.yml or one of the supported extensions. That will allow the server to load the server config + the permission.yml and users.yml configs. Which too are supposed to be in the same folder. If not in the same folder there load will fail, and therefor the permission plugin will not load. And so does the users config. And no fall back to default will happen.
Thirdly the supported extensions for the config files are: yml, yaml, json, js.
In nodejs context. If nothing precised. There is no fallback to some default config. The config need to be provided in one of the default folders, or by precising a path to it. Or by passing a config object. And all the optional options will default to some values if not provided ( a bit bellow there is an example that can show that ). Know however that precising an end point is very important and required.
To precise the path, we need to precise the path to the config.yml file (the server config) [example: path.join(__dirname, './conf/config.yml')]. Then from the same dir permission.yml and users.yml will be retrieved (the extension can be any of the supported one). We can not precise a path to a directory, it will fail.
We can precise the path to permission config or user config separatly within config.yaml as shown bellow:
# Permissioning example with default values for config-based permissioning
permission:
type: config
options:
path: ./permissions.yml
maxRuleIterations: 3
cacheEvacuationInterval: 60000
Finally we can pass an object to configure the server, or by passing null as a parameter and use .set methods (i didn't test the second method). For configuring the server we need to follow the same structure as the yml file. With sometimes a bit different naming. The typescript declaration files or types show us the way. With an editor like vscode. Even if we are not using typescript we can keep get the auto completion and type definitions.
And the simplest for equivalent to the previous version is :
const webSocketServer = new Deepstream({
connectionEndpoints: [
{
type: 'ws-websocket',
options: {
port: 6020,
host: '127.0.0.1',
urlPath: '/deepstream'
}
}
]
});
webSocketServer.start();
the above is the new syntax and way.
const server = new DeepStreamServer({
host:'localhost',
port:3003
})
^^^^^^^ is completely deprecated and not supported in version 4 (the doc is not updated).