Disable foreign keys in Doctrine Migrations - symfony

I'm using NDBCLUSTER engine in a MySQL DB. I've added a class for wrapping Connection and adding the engine option:
namespace AppBundle\DBAL;
use Doctrine\DBAL\Connection as BaseConnection;
use Doctrine\DBAL\Driver;
use Doctrine\DBAL\Configuration;
use Doctrine\Common\EventManager;
class Connection extends BaseConnection
{
public function __construct(array $params, Driver $driver, Configuration $config = null, EventManager $eventManager = null)
{
if (isset($params['driverOptions']['engine'])) {
$params['defaultTableOptions']['engine'] = $params['driverOptions']['engine'];
}
return parent::__construct($params, $driver, $config, $eventManager);
}
}
I define the engine option in the config.yml file:
doctrine:
dbal:
default_connection: default
connections:
default:
driver: "%database_driver%"
host: "%database_host%"
port: "%database_port%"
dbname: "%database_name%"
user: "%database_user%"
password: "%database_password%"
charset: UTF8
wrapper_class: AppBundle\DBAL\Connection
options:
engine: NDBCLUSTER
orm:
auto_generate_proxy_classes: "%kernel.debug%"
default_entity_manager: default
entity_managers:
default:
connection: default
mappings:
AppBundle: ~
Then, if I execute php app/console doctrine:migrations:diff the NDBCLUSTER engine is added to the CREATE statements. However, the foreign keys are added too, and NDBCLUSTER does not accept foreign keys. Is there any way to disable the foreign keys (I mean, not writing them in the migration files)?

I disabled the foreign keys by implementing my own platform_service for that connection:
namespace AcmeBundle\Doctrine;
use Doctrine\DBAL\Platforms\MySQL57Platform;
class CustomMySQLPlatform extends MySQL57Platform
{
public function supportsForeignKeyConstraints()
{
return false;
}
public function supportsForeignKeyOnUpdate()
{
return false;
}
}
Service definition in services.yml:
acme.dbal.service.custom_mysql_platform:
class: AcmeBundle\Doctrine\CustomMySQLPlatform
Doctrine DBAL definition in config.yml:
doctrine:
dbal:
connections:
default:
....
platform_service: acme.dbal.service.custom_mysql_platform

Related

Can't send emails using SwiftMailer (Symfony4): wrong SMTP parameters?

I'm coding a small website using Symfony 4.
There's a simple contact form that is supposed to send emails, seemed easy until I realize I can't configure it ^^
I've followed Symfony doc instructions from here:
[https://symfony.com/doc/current/email.html][1]
Meaning mainly having the Swift mailer dependy:
composer require mailer
And my Controller looks like this:
/**
* #Route("/contact", name="contact_handling")
*/
public function contactHandler(Request $request, \Swift_Mailer $mailer)
{
$contact = new Contact();
$form = $this->createForm(ContactType::class, $contact);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$message = (new \Swift_Message('Hello Email'))
->setFrom('send#example.com')
->setTo('myownemail#hotmail.fr')
->setBody("plopppp mail")
;
$mailer->send($message);
$contact = $form->getData();
return $this->render('home.html.twig', array(
'form' => $form->createView(),
));
}
return $this->render('home.html.twig', array(
'form' => $form->createView(),
));
No matter what it does next in the return (I'm also trying to figure out how to avoid the page reload and just return an answer like "OK" or "not OK" then my Javascript pops up a message)
For dev environment (I'll have the same problem when moving to prod by the way),
my .env conf file has this parameter:
MAILER_URL=smtp://smtp-mail.outlook.com:587?encryption=tls&username=myownemail#hotmail.fr&password=mypwd
while trying to use my own email account, which could be my problem
Smtp address, port and encryption are some parameters found on website like this one:
[https://www.lifewire.com/what-are-the-outlook-com-smtp-server-settings-1170671][1]
Of course, I've never received anything.
If someone familiar whith this could help me it would be very nice :)
I'm using Windows10 + PhpStorm + php7 + built-in symfony server
Thanks!
Edit:
Output from: php bin/console debug:config SwiftmailerBundle
swiftmailer:
default_mailer: default
mailers:
default:
url: '%env(MAILER_URL)%'
spool:
type: memory
path: 'C:\www\h4h\var\cache\dev/swiftmailer/spool'
id: null
transport: smtp
command: '/usr/sbin/sendmail -bs'
username: null
password: null
host: localhost
port: null
timeout: 30
source_ip: null
local_domain: null
encryption: null
auth_mode: null
delivery_addresses: { }
logging: true
delivery_whitelist: { }
Edit 2:
I've just tried putting the conf in the config/packages/swiftmailer.yaml without more success, but at least, php bin/console debug:config SwiftmailerBundle outputs the correct info:
swiftmailer:
transport: gmail
username: mylogin
password: mypwd
host: smtp.gmail.com
port: 587
encryption: ssl
auth_mode: login
spool:
type: file
path: '%kernel.cache_dir%/swiftmailer/spool'
sender_address: ~
antiflood:
threshold: 99
sleep: 0
delivery_addresses: []
disable_delivery: ~
logging: '%kernel.debug%'

Error: Call to a member function getUser() on null" at AuthorizeController.php line 58

I am trying to configure FOSOAuthServerBundle with FOSUserBundle using the documentation of FOSOAuthServerBundle. This is the config:
config.yml
fos_user:
db_driver: orm
firewall_name: oauth_token #main
user_class: Minn\UserBundle\Entity\User
fos_oauth_server:
db_driver: orm
client_class: Minn\UserBundle\Entity\Client
access_token_class: Minn\UserBundle\Entity\AccessToken
refresh_token_class: Minn\UserBundle\Entity\RefreshToken
auth_code_class: Minn\UserBundle\Entity\AuthCode
service:
user_provider: fos_user.user_manager # this is added to fos_oauth to use fos_user for authentication
options:
supported_scopes: api
security.yml
security:
encoders:
FOS\UserBundle\Model\UserInterface: bcrypt
role_hierarchy:
ROLE_USER : ROLE_API
ROLE_ADMIN: ROLE_USER
ROLE_SUPER_ADMIN: [ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH]
providers:
fos_userbundle:
id: fos_user.user_provider.username
firewalls:
# disables authentication for assets and the profiler, adapt it according to your needs
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
oauth_token:
pattern: ^/oauth/v2/token
security: false
api_doc:
pattern: ^/api/doc
security: false
api:
pattern: ^/api
fos_oauth: true
stateless: true
access_control:
- { path: ^/api, roles: [ IS_AUTHENTICATED_FULLY ] }
A this point, it seems to be working as testing the config with the creation of symfony command worked well.
The testing command:
<?php
namespace Minn\UserBundle\Command;
use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Acme\OAuthServerBundle\Document\Client;
class CreateOAuthClientCommand extends ContainerAwareCommand {
protected function configure() {
$this
->setName('oauth:client:create')
->setDescription('Creates a new client')
->addOption(
'redirect-uri', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Sets redirect uri for client. Use this option multiple times to set multiple redirect URIs.', null
)
->addOption(
'grant-type', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Sets allowed grant type for client. Use this option multiple times to set multiple grant types..', null
);
}
protected function execute(InputInterface $input, OutputInterface $output) {
$clientManager = $this->getContainer()->get('fos_oauth_server.client_manager.default');
$client = $clientManager->createClient();
$client->setRedirectUris($input->getOption('redirect-uri'));
$client->setAllowedGrantTypes($input->getOption('grant-type'));
$clientManager->updateClient($client);
$output->writeln(
sprintf(
'Added a new client with public id <info>%s</info>, secret <info>%s</info>', $client->getPublicId(), $client->getSecret()
)
);
}
}
Run the following symfony command:
php app/console oauth:client:create --redirect-uri="http://localhost/minnapi/web/app_dev.php/" --grant-type="authorization_code" --grant-type="password" --grant-type="refresh-token" --grant-type="token" --grant-type="client_credentials"
the output of the command is:
Added a new client with public id 5_552osbf54k4c0kow00ko8ww8kkgcwgg4g4okkgc0wcww0ggsw8, secret 10kv0z11wr688o8kws4wg08scs48o4o8o8cg004c44wcgcgc4s
Please be noted that the command created a record in the table client witch is as follows:
INSERT INTO `minn_client` (`id`, `name`, `random_id`, `redirect_uris`, `secret`, `allowed_grant_types`) VALUES
(5, NULL, '552osbf54k4c0kow00ko8ww8kkgcwgg4g4okkgc0wcww0ggsw8', 'a:1:{i:0;s:41:"http://localhost/minnapi/web/app_dev.php/";}', '10kv0z11wr688o8kws4wg08scs48o4o8o8cg004c44wcgcgc4s', 'a:5:{i:0;s:18:"authorization_code";i:1;s:8:"password";i:2;s:13:"refresh-token";i:3;s:5:"token";i:4;s:18:"client_credentials";}');
Execute the following request in your browser
http://localhost/minnapi/web/app_dev.php/oauth/v2/token?client_id=5_552osbf54k4c0kow00ko8ww8kkgcwgg4g4okkgc0wcww0ggsw8&client_secret=10kv0z11wr688o8kws4wg08scs48o4o8o8cg004c44wcgcgc4s&grant_type=client_credentials
The returned answer of the browser is:
{"access_token":"Njg5OWUzZmI5Yjg5MWFlYTZkOWNmMWIwNGMwNDNmZDhkZmEwZDhjMDM4OTcyNzZiNzRiMTNiZjBlOGMyMDk0OA","expires_in":3600,"token_type":"bearer","scope":"api"}
Now, the problems come when I tried to check it with an action in a controller as proposed by the documentation:
The testing action
/**
* #Route("/connect")
*/
public function connectAction(){
// 1. creation of a client (manually)
$clientManager = $this->get('fos_oauth_server.client_manager.default');
$client = $clientManager->createClient();
$client->setRedirectUris(array('http://localhost/minnapi/web/app_dev.php/'));
$client->setAllowedGrantTypes(array('token', 'authorization_code'));
$clientManager->updateClient($client);
return $this->redirect($this->generateUrl('fos_oauth_server_authorize', array(
'client_id' => $client->getPublicId(),
'redirect_uri' => 'http://localhost/minnapi/web/app_dev.php/',
'response_type' => 'api'
)));
}
The error I got is:
Uncaught PHP Exception Symfony\Component\Debug\Exception\FatalErrorException: "Error: Call to a member function getUser() on null" at /home/amine/NetBeansProjects/minnapi/vendor/friendsofsymfony/oauth-server-bundle/Controller/AuthorizeController.php line 58
Context: { "exception": "Object(Symfony\Component\Debug\Exception\FatalErrorException)" }
Is there any idea about the error?
Thanks

Can I put doctrine dbal and orm config in a vendor bundle?

I'm just asking a question, that's can we put all doctrine (orm and dbal) configuration in the config.yml file which is localized inside a vendor bundle ? And how to access to this entity manager outside of this bundle ?
Thanks per advance
EDIT1:
I think it's possible by using the PrependExtensionInterface like that :
//vendor/XXXXBundle/DependencyInjection/XXXXExtension.php
class XXXXExtension extends Extension implements PrependExtensionInterface
{
public function load(array $configs, ContainerBuilder $container)
{
$configuration = new Configuration();
$config = $this->processConfiguration($configuration, $configs);
$loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
$loader->load('services.yml');
}
public function prepend(ContainerBuilder $container)
{
$configFile = __DIR__ . '/../Resources/config/config.yml';
$content = Yaml::parse(
file_get_contents($configFile)
);
$container->prependExtensionConfig('', $content);
}
}
# vendor/XXXXBundle/Resources/config/config.yml
imports:
- { resource: parameters.yml }
doctrine:
dbal:
default_connection: default_conn
connections:
default:
driver: "%XXXXBundle.database_driver%"
host: "%XXXXBundle.database_host%"
port: "%XXXXBundle.database_port%"
dbname: "%XXXXBundle.database_name%"
user: "%XXXXBundle.database_user%"
password: "%XXXXBundle.database_password%"
charset: UTF8
orm:
default_entity_manager: default_em
auto_generate_proxy_classes: "%kernel.debug%"
auto_mapping: true
entity_managers:
default_em:
connection: default_conn
mappings:
XXXXBundle:
type: annotation
is_bundle: false
dir: %kernel.root_dir%/../vendor/awcb/Aw/Common/Model/XXXXBundle/Entity
prefix: Aw\Common\Model\XXXXBundle\Entity
alias: XXXXBundle
# vendor/YYYYBundle/Resources/config/services.yml
services:
common_business_profile:
class: Aw\Common\Business\ProfileBundle\Lib\ProfileLibrary
arguments: ["#doctrine.orm.default_em"] # already tried default_entity_manager and entity_manager
And I get the error :
The service "common_business_profile" has a dependency on a non-existent service "doctrine.orm.entity_manager".
You can note that a php app/console container:debug shows that there is no doctrine.* that's loaded...
Can you help me more please ? :)
Regards,

Symfony2: Bundle does not exist

I have this problem:
InvalidArgumentException: Bundle "DipUserBundle" does not exist or it is not enabled.
Btw I have two bundle inside Dip namespace. Both of them I made through console.
Please, is there someone who can help me.. here is my code!! Tnx
config.yml
orm:
auto_generate_proxy_classes: %kernel.debug%
default_entity_manager: default
entity_managers:
default:
mappings:
# ...
DipBiznisBundle: ~
DipUserBundle: ~
AppKernel.php
class AppKernel extends Kernel {
public function registerBundles() {
$bundles = array(
...
new Dip\BiznisBundle\DipBiznisBundle(),
new Dip\UserBundle\UserBundle(),
);
routing.yml
homepage:
pattern: /
defaults: { _controller: DipUserBundle:Default:index }
UserBundle.php
<?php
namespace Dip\UserBundle;
use Symfony\Component\HttpKernel\Bundle\Bundle;
class UserBundle extends Bundle {
}
Your problem will be solved if you rename file and BiznisBundle to DipBiznisBundle and UserBundle to DipUserBundle... to avoid problems on future generate bundles using generate command and would define namespaces using slashes instead of backslashes....

Multiple, dynamic database connections in Symfony2

I have a Symfony2 application that I want to make multi-tenant by the use of one database pr tenant (some don't consider this to be multi-tenancy, but that's not really the point).
The documentation describes how to accomplish this. However, I want to be able to create tenants dynamically, and writing the new database connection details (and entity managers) to the config.yml file directly seems messy. I would rather have a separate database which holds the tenants and their connections, and then select the proper connection/em based on an identifier (fetched, for instance, from a the subdomain of the app - clientname.app.com).
Using this approach I should be able to accomplish this, but will at the same time probably break the ability to specify the database connection and/or entity manager when running the command line commands for updating database schemas and the likes.
Provided that what I want to do make sense, is there a clever way to achieve this?
I set ours up with a static database to handle login and tenancy information and a secondary database to hold user data
app/config/config.yml:
doctrine:
dbal:
default_connection: default
connections:
default:
driver: "%database_driver%"
host: "%database_host%"
port: "%database_port%"
dbname: "%database_name%"
user: "%database_user%"
password: "%database_password%"
charset: UTF8
tenantdb:
driver: "%database_driver%"
host: "%database_host%"
port: "%database_port%"
dbname: "%database_name%"
user: "%database_user%"
password: "%database_password%"
charset: UTF8
orm:
default_entity_manager: default
entity_managers:
default:
connection: default
mappings:
MyCoreBundle: ~
tenantdb:
connection: tenantdb
mappings:
MyAppBundle: ~
And then, in controllers, instead of
$something = $this->getDoctrine()
->getManager()
->getRepository('MyAppBundle:Thing')
->findAll();
we did:
$something = $this->getDoctrine()
->getManager('tenantdb')
->getRepository('MyAppBundle:Thing', 'tenantdb')
->findAll();
which you can find details of here:
http://symfony.com/doc/current/cookbook/doctrine/multiple_entity_managers.html
Then, based on Symfony2, Dynamic DB Connection/Early override of Doctrine Service
I set up a service to switch databases based on the subdomain of the request (e.g. tenant1.example.com tenant2.example.com)
src/MyCoreBundle/Resources/config/services.yml:
services:
my.database_switcher:
class: MyCoreBundle\EventListener\DatabaseSwitcherEventListener
arguments: [#request, #doctrine.dbal.tenantdb_connection]
scope: request
tags:
- { name: kernel.event_listener, event: kernel.request, method: onKernelRequest }
MyCoreBundle\EventListener\DatabaseSwitcherEventListener.php
namespace MyCoreBundle\EventListener;
use Symfony\Component\HttpFoundation\Request;
use Doctrine\DBAL\Connection;
class DatabaseSwitcherEventListener {
private $request;
private $connection;
public function __construct(Request $request, Connection $connection) {
$this->request = $request;
$this->connection = $connection;
}
public function onKernelRequest() {
$connection = $this->connection;
if (! $connection->isConnected()) {
$params = $this->connection->getParams();
$subdomain = __GET_SUBDOMAIN__();
$oldname = preg_replace (
"/_tenant_$subdomain|_template/",
'',
$params['dbname']
);
$params['dbname'] = $oldname . ($subdomain ? "_tenant_$subdomain"
: "_template");
$connection->__construct(
$params,
$connection->getDriver(),
$connection->getConfiguration(),
$connection->getEventManager()
);
$connection->connect();
}
}
}
For convenience sake, we have an "extra" tenant database called XXX_template which system admins connect to when making global changes.
The plan is that this database is copied to tenant databases on tenant create.
Create a service that produces your custom entity managers based on the user's credential.
$this->get('my.db.service')->getEmForUser('bob');
Then your service would be something like this
class EntityManagerService
{
function __construct($doctrine)
{ ... }
function getEmForUser($user)
{
//look up Bob's connection details in your connection db
//and get them using the globally configured entity manager
//create Entity Manager using bob's config
return $em.
}
This is the most reusable way to do things and it fits with the Dependency Injection pattern Symfony2 uses.
You'll want to return instances of this class
https://github.com/doctrine/doctrine2/blob/master/lib/Doctrine/ORM/EntityManager.php
Don't know if I gresped the extent of your question, but I connect to different databases using this:
$connectionFactory = $this->container->get('doctrine.dbal.connection_factory');
$conn = $connectionFactory->createConnection(array(
'driver' => 'pdo_mysql',
'user' => 'mattias',
'password' => 'nkjhnjknj',
'host' => 'fs1.uuyh.se',
'dbname' => 'csmedia',
));
return $conn;
We had the same problem on our project.
We created a new service in vendor bundle named : connectionManager.
The service is a multiton which return an entityManager by parameters.

Resources