I know that using the Doctrinebundle in Symfony2 it is possible to instantiate multiple DB connections under Doctrine...
$connectionFactory = $this->container->get('doctrine.dbal.connection_factory');
$connection = $connectionFactory->createConnection(array(
'driver' => 'pdo_mysql',
'user' => 'foo_user',
'password' => 'foo_pass',
'host' => 'foo_host',
'dbname' => 'foo_db',
));
I'm curious if this is the case if you are using PURELY Doctrine though?, I've set up Doctrine via Composer like so...
{
"config": {
"vendor-dir": "lib/"
},
"require": {
"doctrine/orm": "2.3.4",
"doctrine/dbal": "2.3.4"
}
}
And have been looking for my ConnectionFactory class but am not seeing it anywhere? Am I required to use Symfony2 to do this?
Should I just download ConnectionFactory.php from the DoctrineBundle and include it in my DBAL folder?? idk?
A bundle is only in the context of symfony needed, it wraps the orm into symfony infrastructure (services, etc.). For pure use of the orm you should read the ORM: Installation and Configuration. As you see you must create an entity manager by yourself with EntityManager::create($dbParams, $config), so simply create different entity managers for your different databases.
For DBAL use you should read DBAL: Configuration and see, a connection can simply obtained trough DriverManager::getConnection($connectionParams, $config); But if you are sure the ConnectionFactory has no dependency to symfony stuff and you really need it, you can try copy it to your code and construct a new factory to obtain a DBAL connection.
$connectionFactory = new ConnectionFactory(array());
$connection = $connectionFactory->createConnection(array(
'driver' => 'pdo_mysql',
'user' => 'foo_user',
'password' => 'foo_pass',
'host' => 'foo_host',
'dbname' => 'foo_db',
));
But take care, this is a DBAL connection, i.e. it's a abstraction layer which sits on top of PDO and only for pure SQL queries. If you need a entity manager you have to initialize it as mentioned in the docs above, or maybe you find another entity manager factory class, which you can "copy".
Related
I just upgraded API platform to version 3.0.
After the few classical modifications linked to the version upgrade, and despite the use of: php bin/console api:upgrade-resource
I notice that my entities are not exposed anymore when I go to the API documentation and if I try to access an endpoint, I get a route error:
No route found for "GET https://127.0.0.1:9000/api/XXX
I replaced all the ApiResource uses in my entities and rewrote my annotations.
example of an entity:
<?php
namespace App\Entity\Test;
use ApiPlatform\Metadata\ApiResource;
#[ApiResource(
collectionOperations: [
'get',
'post' => [
'denormalization_context' => ['groups' => ['create:xxx']]
]
],
itemOperations: [
'get' => [
'normalization_context' => ['groups' => ['read:fully:xxx']]
],
'put' => [
'denormalization_context' => ['groups' => ['update:xxx']]
],
'delete'
],
normalizationContext: ['groups' => ['read:xxx']]
)]
class Departement
{
....
}
Thanks in advance!
ok so, i update a little entity manually and now she is exposed !
<?php
namespace App\Entity\Agorha;
//use ApiPlatform\Core\Annotation\ApiResource;
use ApiPlatform\Metadata\ApiResource;
use ApiPlatform\Metadata\Get;
use ApiPlatform\Metadata\GetCollection;
use ApiPlatform\Metadata\Post;
use App\Entity\ChoixEcole;
use App\Repository\Agorha\EcoleRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
#[ORM\Entity(repositoryClass: EcoleRepository::class)]
#[ORM\Table(name: "agorha_ecole")]
#[ORM\HasLifecycleCallbacks()]
#[ApiResource(operations: [
new Get(),
new GetCollection()
])]
#[
UniqueEntity('code')
]
class Ecole
{
#[ORM\Id()]
#[ORM\GeneratedValue()]
#[ORM\Column(type: "integer")]
private $id;
i didn't see the results of the upgrade command, which ended up being an error and therefore did nothing.
in fact, it does not seem to exist
Command "api:upgrade-resource" is not defined.
anyone would know why ?
It looks like your entities are still in the <= v2.6 format despite your call to the api:upgrade-resource command.
See the migration documentation: instead of
'get', 'post', etc. you should use new Metadata classes Get(), Post(), etc.
Are you sure that the migration command returned no error?
In my case (migration from 2.6 to 3.0) the migration command was not available for unknwon reason (not found from the console).
Try migrating manually one entity to the new format and watch your openApi documentation to see if your endpoints are back.
Edit: Why didn't api:upgrade-resource work ?
As far as I understand, the migration command is provided in v2.7 to prepare migration to 3.0 but has been dropped from v3.0. So the proper way to migrate according to the doc is:
migrate to 2.7
call api:upgrade-resource and check all is working
THEN migrate to 3.0
like #MendelYev says i should run the api upgrade command before upgrade.
now i ve to upgrade manually my entities using PHP attributes and new Metadata classes from Doctrine
I'm currently working on an OroPlatform project and I need to add a custom field on the BusinessUnit core entity.
I have read the Oro documentation section about the way to extend core entities : https://doc.oroinc.com/backend/entities/extend-entities/#id1
<?php
namespace MyBundle\Bundle\AppBundle\Migrations\Schema\v1_0;
use Doctrine\DBAL\Schema\Schema;
use Oro\Bundle\EntityExtendBundle\EntityConfig\ExtendScope;
use Oro\Bundle\MigrationBundle\Migration\Migration;
use Oro\Bundle\MigrationBundle\Migration\QueryBag;
class AddColumnsToBusinessUnit implements Migration
{
public function up(Schema $schema, QueryBag $queries)
{
$table = $schema->getTable('oro_business_unit');
$table->addColumn('siret', 'string', [
'oro_options' => [
'extend' => ['owner' => ExtendScope::OWNER_CUSTOM],
'entity' => ['label' => 'siret'],
],
]);
}
}
When I run the command symfony console oro:migration:load --force, it works and the migration is applied to my database.
Now, I want a required field. I have seen the instruction 'notnull' => true to setup a non nullable field on the database.
Everything works well, but my field hasn't any JavaScript validation on the organization/business_unit/create route. Any ideas ?
You can validate the new field by extending the validation metadata that is already defined for the core entity you are extending.
To do this, please follow the official Symfony documentation and use the YML format:
https://symfony.com/doc/4.4/validation.html#constraint-configuration
The constraint that you can use for the field is "not blank."
Here is an example:
# src/<YourBundlePath>/Resources/config/validation.yml
Oro\Bundle\OrganizationBundle\Entity\BusinessUnit:
properties:
siret:
- NotBlank: ~
I am looking for a good solution to on-the-fly connection of databases within Symfony utilizing Doctrine for entity management.
The scenario I have is that all inbound users to our service will be visiting *.website.com addresses, like client1.website.com.
We would like to use one Doctrine entity for the Client table to then look up their database credentials based on the URL of their account on the fly.
So far I have found the following topics here on stackoverflow that discuss dynamically changing the database credentials--but no clear workable solutions.
I'd like to propose collaborating to put together a working solution, and I'll put together a blog/tutorial post for other folks looking to modify database connection parameters within Symfony.
Here are some related posts:
Dynamic database connection symfony2
Symfony2, Dynamic DB Connection/Early override of Doctrine Service
Thanks!
If $em is existing entity manager and you want to reuse it's configuration, you can use this:
$conn = array(
'driver' => 'pdo_mysql',
'user' => 'root',
'password' => '',
'dbname' => 'foo'
);
$new = \Doctrine\ORM\EntityManager::create(
$conn,
$em->getConfiguration(),
$em->getEventManager()
);
I needed to do something similar - runtime discovery of an available database server. I did it by overriding the doctrine.dbal.connection_factory.class parameter and substituting my own derivation of the Doctrine bundle's ConnectionFactory class
My services.yml provides the parameter, pointing at my custom class
parameters:
doctrine.dbal.connection_factory.class: Path\To\Class\CustomConnectionFactory
Then fill in your discovery logic in Path\To\Class\CustomConnectionFactory.php
<?php
namespace Path\To\Class;
use Doctrine\Bundle\DoctrineBundle\ConnectionFactory;
use Doctrine\Common\EventManager;
use Doctrine\DBAL\Configuration;
class CustomConnectionFactory extends ConnectionFactory
{
public function createConnection(array $params, Configuration $config = null, EventManager $eventManager = null, array $mappingTypes = array())
{
// Discover and override $params array here.
// A real-world example might obtain them from zookeeper,
// consul or etcd for example. You'll probably want to cache
// anything you obtain from such a service too.
$params['driver'] = 'pdo_mysql';
$params['host'] = '10.1.2.3';
$params['port'] = 3306;
$params['dbname'] = 'foo';
$params['user'] = 'myuser';
$params['password'] = 'mypass';
//continue with regular connection creation using new params
return parent::createConnection($params, $config, $eventManager,$mappingTypes);
}
}
Note also that Symfony 3.2 features the ability to use environment variables in container configurations, and to use their values on-demand (rather than fixing them when the container is compiled). See the blog announcement for more details.
I'm using Doctrine 2 and I want to generate an ORM of my database but I don't want select all tables of the db.
For example, in this db :
Table 1 has no primary key
Table 2 is normal
I want to choose ONLY Table 2 with this command:
doctrine:mapping:convert --from-database yml ./src/Application/TestBundle/Resources/config/doctrine/metadata/orm --filter="Table2"
I have an error :
Table Table_1 has no primary key. Doctrine does not support reverse engineering from tables that don't have a primary key.
Ok I know , but I don't want my table 1 in my ORM. When my table 1 has primary key i can filter the tables. I've seen
Generating a single Entity from existing database using symfony2 and doctrine, but it doesn't work.
Ignoring the table was the solution:
doctrine:
dbal:
schema_filter: ~^(?!Table1)~
If you use Doctrine2 without Symfony then you should add this line to your bootstrap:
// With this expression all tables prefixed with Table1 will ignored by the schema tool.
$entityManager->getConnection()->getConfiguration()->setFilterSchemaAssetsExpression("~^(?!Table1)~");
the whole bootstrap looks like
<?php
// bootstrap.php
use Doctrine\ORM\Tools\Setup;
use Doctrine\ORM\EntityManager;
// Include Composer Autoload (relative to project root).
require_once "vendor/autoload.php";
// Create a simple "default" Doctrine ORM configuration for Annotations
$isDevMode = true;
$paths = array(__DIR__."/doctrine/entities");
$config = Setup::createAnnotationMetadataConfiguration($paths, $isDevMode);
//$config = Setup::createYAMLMetadataConfiguration(array(__DIR__."/doctrine/yaml"), $isDevMode);
// the connection configuration
$dbParams = array(
'driver' => 'pdo_mysql',
'user' => 'username',
'password' => 'password',
'dbname' => 'database',
);
/** #var $entityManager \Doctrine\ORM\EntityManager */
$entityManager = EntityManager::create($dbParams, $config);
// Set the other connections parameters
$conn = $entityManager->getConnection();
$platform = $conn->getDatabasePlatform();
$platform->registerDoctrineTypeMapping('enum', 'string');
// With this expression all tables prefixed with t_ will ignored by the schema tool.
$conn->getConfiguration()->setFilterSchemaAssetsExpression("~^(?!t__)~");
In recent versions of the Doctrine bundle one has to configure schema filter on the connection level, so:
doctrine:
dbal:
default_connection: default
connections:
default: # <- your connection name
url: '%env(DATABASE_URL)%'
schema_filter: '#^(?!table_to_exclude)#'
Doctrine first validates your tables and only then executes the command.
So you should always have valid DB schema in order to make any operations with it.
I have a Laravel 4 application with sqlite db configured for testing.
I am working in a workbench package
I have a problem testing my models in a PHPUnit Test, because i defined some unique properties on my model. I run Artisan::call('migrate', array('--bench' => 'vendor/webshop')); from my Basic Test Class from which i extend other Tests.
I think this runs the database migrations, but in my opinion it does not delete the models in the database.
Because if i do
public function setUp() {
parent::setUp();
$this->order = Order::create(array(
"uniquekey" = "123"
));
}
I get an error saying, can not insert model because of violation of unique key rule.
How should i clean the database before every test?
You should define environment for testing purposes.
Actually Laravel does have one for you - notice testing folder inside your app/config.
Create app/config/testing/database.php (or modify if exists) and place this:
return array(
'default' => 'sqlite',
'connections' => array(
'sqlite' => array(
'driver' => 'sqlite',
'database' => ':memory:', // this will do the trick ;)
'prefix' => '',
),
),
);
When you run tests, Laravel sets it's environment to 'testing' automaticaly - no need to play with this.
SQLite in-memory DB is memory stored withing RAM, thus it's fast - and yes, tests start with empty database as well.