Symfony2 default configuration parameters - php

Is it possible to have a default configuration parameters in Symfony yeml configuration file. In case where the variable parameter is not available. For example. I have database name coming from Apache configuration, but if I run a command I would like to go with a default database, see below. The example is kind of twigi'ish
doctrine:
dbal:
driver: pdo_mysql
host: "%database_host%"
port: "%database_port%"
dbname: "%database.name%"|default('database1')
user: "%database_user%"
password: "%database_password%"

The only way to do that would be to set the parameter to a default value, which I assume would be early in the configuration file. A theoretic example:
parameters:
foo: bar
imports:
- { resource: parameters.yml }
If parameters.yml contains a definition for the %foo% parameter, it will overwrite the previous definition. If parameter.yml does not contain a definition for %foo% however, it will use the earlier defined (default) value.

You can put your default configuration in parameters.yml.dist, this way when someone new joins the project and runs:
composer install
or
composer update
He will be prompted to provide his environment specific values and so parameters.yml will be created.

I figured out a way around this problem by using "database_prefix" as the default database and other databases just add a suffix to that.
doctrine:
dbal:
driver: pdo_mysql
host: "%database_host%"
port: "%database_port%"
dbname: "database_prefix%database.name%"
user: "%database_user%"
password: "%database_password%"

Related

Multiple connections and entity managers in a symfony 2 / 3 application

My multi-tenant-app uses a master database, that holds information about tenants (like name, etc.) and a app-specific database per tenant.
I configured a master and some_tenant connection and entity manager in the doctrine section inside config.yml.
This gives me access to the master database from a controller (eg. for validating and getting tenant information for some_tenant based on the subdomain some_tenant.my-app.com). And it lets me use a tenant-specific database and entity manager during the application life-cycle.
The doctrine section in my config looks like this:
doctrine:
dbal:
default_connection: 'master'
connections:
master:
driver: pdo_mysql
host: "%database_host%"
port: "%database_port%"
dbname: "%database_name%"
user: "%database_user%"
password: "%database_password%"
charset: UTF8
some_tenant:
driver: pdo_mysql
host: "%database_host_some_tenant%"
port: "%database_port_some_tenant%"
dbname: "%database_name_some_tenant%"
user: "%database_user_some_tenant%"
password: "%database_password_some_tenant%"
charset: UTF8
orm:
auto_generate_proxy_classes: "%kernel.debug%"
entity_managers:
master:
connection: master
mappings:
BEMultiTenancyBundle: ~
some_tenant:
connection: some_tenant
mappings:
AppBundle: ~
Here comes the part, which I am unhappy with and cannot find a solution:
First of all, tenants will be more than 20. And it starts to get messy, altering the doctrine config this way.
Then there is another config file, called tenants.yml which holds more information like enabled/disabled app-features, tenant-specific themes, etc.
The file is loaded, validated using the Config Component, and a container parameter is set, so that tenants configurations are available app-wide.
I would like to store the database credentials also in that file.
I want to create connections and entity managers based on that config. One per each tenant, which can be used during the app life-cycle.
I need to have them available also at the console command bin/console doctrine:schema:update --em=some_tenant for updating each tenant's database schem and bin/console doctrine:schema:update --em=master for updating the master database scheme.
By now I guess, the only way to achieve this is to add configuration parameters to the doctrine section programmatically after the AppBundle is loaded, and before the doctrine registry is constructed with the given managers and connections.
But I cannot even find a point, where I could achive this.
Is there another way to get to point 1 and 2?
Even though there is a similiar question, which I am not sure if it is exactly about the same problem and is about 3 years old, I wanted to post this question with a bit more explanation.
The solution in comments is a straight way easy solution and it will work. The other solution I've ever meet is to dynamically replace tenant database credentails using some external conditions, i.e request HOST.
You can decorate or extend the connection factory with a service in a way, that having the request stack available (or providing the domain with ENV or console argument for other SAPI's) you can have the same entity manager (even default!) being configured on demand.
on a brief look this would look like
use Doctrine\Bundle\DoctrineBundle\ConnectionFactory;
use Doctrine\Common\EventManager;
use Doctrine\DBAL\Configuration;
use Symfony\Component\HttpFoundation\RequestStack;
class DynamicConnectionFactory extends Factory
{
/** #var RequestStack */
private $requestStack;
public function __construct(array $types, RequestStack $stack)
{
parent::__construct($types);
$this->requestStack = $stack;
}
public function createConnection(array $params, Configuration $config = null, EventManager $eventManager = null, array $mappingTypes = array())
{
$host = $this->requestStack->getMasterRequest()->getHost();
$params = $this->replaceParamsForHost(array $params, $host);
return parent::createConnection($params, $config, $eventManager, $mappingTypes);
}
private function replaceParamsForHost(array $params, $host)
{
//do your magic, i.e parse config or call Memcache service or count the stars
return array_replace($params, ['database' => $host]);
}
}
I think that, To manage multi-tenant with symfony 2/3.
We can config auto_mapping: false for ORM of doctrine.
file: config.yml
doctrine:
dbal:
default_connection: master
connections:
master:
driver: pdo_mysql
host: '%master_database_host%'
port: '%master_database_port%'
dbname: '%master_database_name%'
user: '%master_database_user%'
password: '%master_database_password%'
charset: UTF8
tenant:
driver: pdo_mysql
host: '%tenant_database_host%'
port: '%tenant_database_port%'
dbname: '%tenant_database_name%'
user: '%tenant_database_user%'
password: '%tenant_database_password%'
charset: UTF8
orm:
default_entity_manager: master
auto_generate_proxy_classes: "%kernel.debug%"
entity_managers:
master:
connection: master
auto_mapping: false
mappings:
AppBundle:
type: yml
dir: Resources/master/config/doctrine
tenant:
connection: tenant
auto_mapping: false
mappings:
AppBundle:
type: yml
dir: Resources/tenant/config/doctrine
After that, we cannot handle connection of each tenant by override connection info in request_listener like article: http://mohdhallal.github.io/blog/2014/09/12/handling-multiple-entity-managers-in-doctrine-the-smart-way/
I hope that, this practice can help someone working with multi-tenant
Regards,
Vuong Nguyen

Connect Doctrine to a MS SQL Database

Just before i get started, I have been trying to figure this out and have clicked nearly every google link there is and I have read nearly all the other questions on this. But I'm stuck because the bundles that are being suggested for this are out of date.
I am creating a website. Tt is a symfony2 application that is being hosted on Microsoft azure. What I want to do is be able to use doctrine of course to fetch and create users to and from the database.
Now from what I've been reading, to connect to this type of database, I have to use the driver called "PDO_dblib".
I have installed this bundle as it seems to be the only one thats still active, don't quote me on that.
https://github.com/realestateconz/MssqlBundle
Now, I installed this in my vendor folder, is this the correct place to store it? Like so:
Project/
app/
src/
vendor/
realestate/
Of course i added the bundle to the AppKernel like so:
new Realestate\MssqlBundle\RealestateMssqlBundle();
and last but not least here is what i have in my config file:
doctrine:
dbal:
default_connection: default
connections:
default:
driver_class: Realestate\MssqlBundle\Driver\PDODblib\Driver
host: %database_host%
dbname: %database_prefix%%database_name%
user: %database_user%
password: %database_password%
so what im thinking im doing here is telling doctrine to use this driver? dont see what else it could be.
I have also declared my parameters.yml for the connection settings.
PS: I am doing my Dev on Linux Mint!
before i tried the steps of this bundle i also ran throught this websites steps: https://dunglas.fr/2014/01/connection-to-a-ms-sql-server-from-symfony-doctrine-on-mac-or-linux/
But again it was throwing errors, I'll post the errors I get down below!
So for the record I have installed freetds and php5-sybase.
The errors that I am getting are such:
[Symfony\Component\Debug\Exception\ContextErrorException]
Warning: class_implements(): Class Realestate\MssqlBundle\Driver\PDODlib\Driver does not exist and could not be loaded
and also this when i try to do a:
php app/console doctrine:database:create
(I do have my entity set up)
but i get the following error from the command of create:
[Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException]
You have requested a non-existent parameter "database_prefix". Did you mean one of these: "database_port", "database_user"?
I have been trying to get this working for the past few days and any help would be fantastic! Any more information needed feel free to ask of course!
According your error code:
[Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException]
You have requested a non-existent parameter "database_prefix". Did you mean one of these: "database_port", "database_user"?
It seems that you miss configuring the parameter “database_prefix”.
If the tables in your database have the unitized prefix e.g. “core_user”,”core_tasks”… You can configure this parameter in the file parameters.yml if not, you can just remove the parameter % database_prefix % in the dbname line in file config.yml.
Here are my code snippets for your reference:
Config.yml:
doctrine:
dbal:
default_connection: default
connections:
default:
driver_class: Realestate\MssqlBundle\Driver\PDODblib\Driver
host: %database_host%
port: %database_port%
dbname: %database_name%
user: %database_user%
password: %database_password%
parameters.yml:
parameters:
database_host: {your_sql_server_name}.database.windows.net
database_port: 1433
database_name: {database_name}
database_user: {username}
database_password: {password}
And the test query in controller:
$conn = $this->get('database_connection');
$data = $conn->fetchAll('SELECT * FROM Testtable');
var_dump($data);

[Symfony][Doctrine]File mapping drivers must have a valid directory path

I have a problems with Doctrine on Sf2.7, when I run a command such as "doctrine: schema: update" I get:
[Doctrine\Common\Persistence\Mapping\MappingException] File mapping drivers must have a valid directory path, however the given path 0 seems to be incorrect!
This worked well until I make a drop of a database to recreate it in "clean" after a lot changed entities ...
Here is an excerpt from my config.yml
# Doctrine Configuration
doctrine:
dbal:
default_connection: default
connections:
default:
driver: pdo_mysql
dbname: "%database_name%"
host: "%database_host%"
port: "%database_port%"
user: "%database_user%"
password: "%database_password%"
charset: UTF8
orm:
default_entity_manager: default
entity_managers:
default:
connection: default
auto_mapping: true
all entities begin with this type of annotations:
/**
 * User
 *
 * #ORM\Entity
 * #ORM\Table(name="usr_user")
 * #ORM\Entity(repositoryClass="Acme\UserBundle\Repository\UserRepository")
 */
I searched our friend Google, OpenClassRooms and here of course but not found ... someone an idea ?
Got the same error when I imported my project to another pc. The solution worked for me is to try clearing configuration cache using php artisan command.
php artisan config:cache
then try to create or update doctrine schema.
For Symfony, you need to clear var/cache directory.
It solved problem for me.

Symfony2 + Propel: no connection information

I'm trying to connect propel and symfony2 together, but the only thing that I get is this exception:
No connection information in your runtime configuration file for datasource [symfony]
I used the propel bundle which I added to the composer, and I edited the kernel to include the bundle.
My config.yml propel conf looks like that:
propel:
dbal:
driver: mysql
user: root
password: null
dsn: mysql:host=localhost;dbname=symfony;charset=UTF8
options: {}
attributes: {}
What can I be missing? I tried googling, but nothing really solves the issue.
Okay, I solved the issue.
The problem lied in the config.yml file, where the propel dbal data should be stored. I initially put it the way they describe it in the manual, like that:
propel:
dbal:
driver: "%database_driver%"
user: "%database_user%"
password: "%database_password%"
dsn: "%database_driver%:host=%database_host%;dbname=%database_name%;charset=%database_charset%"
According to the manual on both the propel and symfony's sites, it is enough. However, this doesn't seem to be the case for some reason yet unknown to me. What I had to do was to explicitly state the connection and name it precisely - symfony, like that:
propel
dbal:
default_connection: symfony
connections:
symfony:
driver: %database_driver%
user: %database_user%
password: %database_password%
dsn: %database_driver%:host=%database_host%;dbname=%database_name%;charset=UTF8
This way it worked. Sucks to be a junior developer sometimes.

Confusion with parameters.yml and config_(dev|stage|prod).yml for database connections

I understand why I should keep my database connections in the parameters.yml file but I also wanted to setup additional database connections as well as different hosts for dev, stage and prod environments. I thought I could do this with the config_dev.yml, config_test.yml and config_prod.yml in conjunction with config.yml, am I wrong?
In parameters.yml I hold the main database connection but can I move this to the config(s) instead?
Example: config.yml
# Doctrine Configuration - notice there is no host defined here
doctrine:
dbal:
default_connection: blah
connections:
blah:
driver: pdo_pgsql
port: 5432
dbname: blah
user: blah_user
password: blah_pass
charset: UTF8
foo:
driver: pdo_pgsql
port: 5432
dbname: foo
user: foo_user
password: foo_pass
charset: UTF8
Example: config_dev.yml
# Doctrine Configuration - Here I define the dev hosts
doctrine:
dbal:
connections:
blah:
host: blah_dev
foo:
host: foo_dev
Example: config_test.yml
# Doctrine Configuration - Here I define the stage or QA hosts
doctrine:
dbal:
connections:
blah:
host: blah_stage
foo:
host: foo_stage
Example: config_prod.yml
# Doctrine Configuration - Here I define the prod hosts
doctrine:
dbal:
connections:
blah:
host: blah_prod
foo:
host: foo_prod
Now I have also removed the settings in parameters.yml but Symfony / Doctrine doesn't like this. Am I missing something? How can I setup something like I have?
Now if I define the default database connection in parameters.yml I can connect to it and then
parameters:
database_driver: pdo_pgsql
database_host: blah_prod
database_port: 5432
database_name: blah
database_user: blah_user
database_password: blah_pass
and in config.yml
doctrine:
dbal:
driver: "%database_driver%"
host: "%database_host%"
dbname: "%database_name%"
user: "%database_user%"
password: "%database_password%"
But now I loose the multiple databases I need and the ability to switch from dev to stage to prod database servers.
I must be missing some additional documentation where this is being addressed, any help would be great.
I've seen the documentation for Multiple Database connections with Doctrine
http://symfony.com/doc/current/cookbook/doctrine/multiple_entity_managers.html
But I would like to avoid having to add three database options like below for each dev, stage and prod server(s) in parameters.yml
parameters:
database_driver: pdo_pgsql
database_host: blah_dev
database_port: 5432
database_name: blah
database_user: blah_user
database_password: blah_pass
#database_driver2: pdo_pgsql
database_host2: blah_stage
#database_port2: 5432
#database_name2: blah
#database_user2: blah_user
#database_password2: blah_pass
#database_driver3: pdo_pgsql
database_host3: blah_prod
#database_port3: 5432
#database_name3: blah
#database_user3: blah_user
#database_password3: blah_pass
( Maybe just configure the different hosts? )
This looks ugly and a PITA, and this is just for blah database, I would have to do this for foo and any other databases I need to configure.
If your connections are the same in each environment but only the configuration values are different, you should use the parameters-configuration-file. Define the environment variables, you need, in the parameters.yml.dist file like this:
# parameters.yml.dist
parameters:
database_host_1: blah
database_host_2: blub
...
Your config.ml may look like this:
# config.yml
imports:
- { resource: parameters.yml }
...
doctrine:
dbal:
default_connection: blah
connections:
blah:
driver: pdo_pgsql
port: 5432
host: "%database_host_1%"
dbname: blah
user: blah_user
password: blah_pass
charset: UTF8
foo:
driver: pdo_pgsql
port: 5432
host: "%database_host_2%"
dbname: foo
user: foo_user
password: foo_pass
charset: UTF8
If your parameters.yml is missing, you'll be ask for the database hostnames next time you call composer update for example.
If you would like to save all your configurations in separate files, you should add this at the beginning of your config_XXX.yml files:
# config_XXX.yml
imports:
- { resource: config.yml }
- { resource: parameters_XXX.yml }
Replace XXX with your environment. Create a parameters_XXX.yml for each environment and set the configuration parameters for your hosts in there like it is in the default parameters.yml file.
# parameters_XXX.yml
parameters:
database_host_1: blahInXXXEnv
database_host_2: blubInXXXEnv
...
I don't see there a reason to use different prod and dev parameters config files.
You can use specific parameters.yml.dist
http://symfony.com/doc/master/cookbook/workflow/new_project_git.html
file at your PC with all defined connections.
Multiple connetions and work with them:
http://symfony.com/doc/master/reference/configuration/doctrine.html
http://symfony.com/doc/current/cookbook/doctrine/multiple_entity_managers.html

Categories