Symfony 2 Console command for creating custom Database - mysql

I am working on a Symfony 2 project where each user have his own database. In my config.yml file I have a doctrine:dbal:orm set for a client but no connection properties because they are set at runtime and referenced by all users. I.e I only have one default dbal connection and two orm-connection and the amount of users is unlimited.
This works fine but I need to create the database and schema when the user is registered (FOS UserBundle). In the extended userbundle controller I can put my own logic.
The problem is that I cannot run the 'php app/console doctrine:database:create' since there are not parameters set for the new user.
Is there any way of specifying a custom database parameter to the console commands?
I could probably get around this by some very ugly mysql commands but I'd rather not.
Many thanks in advance!

You can create your own command using the code below as an outline:
namespace Doctrine\Bundle\DoctrineBundle\Command;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Doctrine\DBAL\DriverManager;
class CreateDatabaseDoctrineCommandDynamically extends DoctrineCommand
{
protected function configure()
{
$this
->setName('doctrine:database:createdynamic')
->setDescription('Creates the configured databases');
}
/**
* {#inheritDoc}
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
/***
** Edit this part below to get the database configuration however you want
**/
$connectionFactory = $this->container->get('doctrine.dbal.connection_factory');
$connection = $connectionFactory->createConnection(array(
'driver' => 'pdo_mysql',
'user' => 'root',
'password' => '',
'host' => 'localhost',
'dbname' => 'foo_database',
));
$params = $connection->getParams();
$name = isset($params['path']) ? $params['path'] : $params['dbname'];
unset($params['dbname']);
$tmpConnection = DriverManager::getConnection($params);
// Only quote if we don't have a path
if (!isset($params['path'])) {
$name = $tmpConnection->getDatabasePlatform()->quoteSingleIdentifier($name);
}
$error = false;
try {
$tmpConnection->getSchemaManager()->createDatabase($name);
$output->writeln(sprintf('<info>Created database for connection named <comment>%s</comment></info>', $name));
} catch (\Exception $e) {
$output->writeln(sprintf('<error>Could not create database for connection named <comment>%s</comment></error>', $name));
$output->writeln(sprintf('<error>%s</error>', $e->getMessage()));
$error = true;
}
$tmpConnection->close();
return $error ? 1 : 0;
}
}

Related

Insert query works fine on my local but doesn't execute on my live database (Laravel/MySQL)

I have a very simple function that loops through an array and inserts some data into a results table - this works perfectly fine on my local using the very same code. On my local setup (Mac) using Laravel Valet & an MySQL database it hits the function Result::create($data) and inserts this data in the database. However on the live/remote site it never hits the Result::create() within the insertUniqueMatches for some reason.
I have added the db user in the env file and it has been granted all privileges so I cannot understand why this won't insert the entry into the results table. Can anyone explain what I am doing wrong? All migrations have been ran to ensure my local and live db are identical.
P.S i have tried both the $fillable variable with all the relevant items in the array and also with the $guarded as a blank array and the problem persists.
class Result extends Model
{
use HasFactory;
// protected $fillable = ['match_id', 'home_team_id', 'away_team_id', 'home_team_goals', 'away_team_goals', 'outcome', 'match_date', 'properties', 'platform_id'];
protected $guarded = [];
public static function insertUniqueMatches($matches, $platform = null)
{
$inserted = 0;
foreach ($matches as $match) {
// check if existing match already exists in the db, if so don't re-insert this
if (Result::where('match_id', '=', $match['matchId'])->doesntExist()) {
$carbonDate = Carbon::now();
$carbonDate->timestamp($match['timestamp']);
$clubs = collect($match['clubs'])->values();
$data = [
'match_id' => $match['matchId'],
'home_team_id' => $clubs[0]['id'],
'away_team_id' => $clubs[1]['id'],
'home_team_goals' => $clubs[0]['goals'],
'away_team_goals' => $clubs[1]['goals'],
'outcome' => self::getMatchOutcome($clubs[0]),
'match_date' => $carbonDate->format('Y-m-d H:i:s'),
'properties' => json_encode([
'clubs' => $match['clubs'],
'players' => $match['players']
]),
'platform_id' => $platform
];
dump($data); // this shows valid data in the terminal
// this if condition is only reached on my local development but never on live so no inserts happen on the live DB
if (Result::create($data)) {
$inserted++;
dump('inserted matchId: '. $match['matchId']); // never see this on line but always on local
}
}
}
return $inserted;
}
i think better solution for now is you can find the problem.
you could write code into try-catch for more information.
replace this code
try {
Result::create($data);
} catch (\Exception $e) {
dd($e);
}
with:
dump($data); // this shows valid data in the terminal
// this if condition is only reached on my local development but never on live
if (Result::create($data)) {
$inserted++;
dump('inserted matchId: '. $match['matchId']); // never see this on line but always on local
}

mysql_real_escape_string(): Access denied in DB insert

I am trying to use a legacy MediaWiki extension on PHP 5.6 and later versions, and it fails when it comes to DB inserts.
And yes, this is not a duplicate, as the code is different.
The full error was:
Warning: mysql_real_escape_string(): Access denied for user
''#'localhost' (using password: NO)
I tried changing to mysqli_real_escape_string but then I had:
mysqli_real_escape_string() expects exactly 2 parameters, 1 given on
line 235
Here is the function:
function Lookup_addLookup ($url, $name, $group)
{
$dbw = wfGetDB(DB_MASTER);
$groupOrder = Lookup_getGroupOrder($group);
$dbw->query ("INSERT INTO ".Lookup_prefix()."lookups (lu_name, lu_url, lu_group, lu_order, lu_group_order) VALUES ('".mysql_real_escape_string($name)."', '".mysql_real_escape_string($url)."', '".mysql_real_escape_string($group)."', 1, $groupOrder)");
Lookup_reOrderGroups();
return true;
}
And another one further down:
function Lookup_moveGroupUp($group)
{
$dbw = wfGetDB(DB_MASTER);
$dbw->query ("UPDATE ".Lookup_prefix()."lookups SET lu_group_order = 0 WHERE lu_group = '".mysqli_real_escape_string($group)."'");
Lookup_reOrderGroups();
return true;
}
mysqli_real_escape_string() needs the database link as the first parameter, which is why it isn't working.
However, MediaWiki wants us to avoid direct queries, so it has the $dbw->insert() method instead, one of several wrapper functions.
Use something like this:
function Lookup_addLookup ($url, $name, $group)
{
$dbw = wfGetDB(DB_MASTER);
$groupOrder = Lookup_getGroupOrder($group);
$dbw->insert(
Lookup_prefix()."lookups",
array(
'lu_name' => $name,
'lu_url' => $url,
'lu_group' => $group,
'lu_order' => 1,
'lu_group_order' => $groupOrder
)
);
Lookup_reOrderGroups();
return true;
}
And in the second example, use $dbw->update():
function Lookup_moveGroupUp($group)
{
$dbw = wfGetDB(DB_MASTER);
$dbw->update(
Lookup_prefix()."lookups",
array(
"lu_group_order" => 0
),
array(
"lu_group" => $group
)
);
Lookup_reOrderGroups();
return true;
}
For more information and other SQL wrappers, read about the different wrapper functions and their documentation.

Yii2-user: How to create admin user in batch mode?

When deploying my application there is of course always an admin user.
How can I create such an admin user as a first user without any interaction ...
... by means of SQL?
... using a Yii2-migration?
Found it. There is an easy way to do this with Yii2 builtin migrations.
In Yii2-user there are some hooks we can use to create users.
This code has to be inserted in a migration. after creating a new migration ./yii migrate/create, preferably after creating initial tables in the database:
use yii\db\Transaction;
use app\models\user\User;
public function safeUp()
{
$transaction = $this->getDb()->beginTransaction();
$user = \Yii::createObject([
'class' => User::className(),
'scenario' => 'create',
'email' => 'admin',
'username' => 'admin#example.com',
'password' => 'mysecret',
]);
if (!$user->insert(false)) {
$transaction->rollBack();
return false;
}
$user->confirm();
$transaction->commit();
}
The skeleton code can be found in ./migrations/....
Don't forget to add database config parameters in ./config/db.php
and the user module in ./config/console.php

zf2 Zend\ServiceManager\Exception\ServiceNotCreatedException

I spent half day to resolve this issue with no success.
I'm doing a setup in EC2, centos 6/64 bit. LAMP installed. On another hosting, my zf2 solution it work fine, so I've searched issue in php modules installed also (list at the end).
This error happen when zf2 try to get an instance of my custom service, also with wasabi mail.
\zend\config\application.config.php
'config_glob_paths' => array(
'./config/autoload/{,*.}{global,local}.php',
),
\zend\config\autoload\global.php
'service_manager' => array(
'factories' => array(
'Zend\Db\Adapter\Adapter' => 'Zend\Db\Adapter\AdapterServiceFactory',
'Zend\CustomLogger' => function ($sm) {
$auth = $sm->get('zfcuser_auth_service');
$customLogger = new \Application\Service\CustomLogger(
$sm->get('Request'),
$sm->get('ZendLog'),
new \Zend\Session\SessionManager(),
$auth->getIdentity(), // $user
$sm->get('Mail'));
return $customLogger;
},
controller
<?php
namespace Foo\Controller;
use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;
use Doctrine\ORM\EntityManager;
use MyProject\Proxies\__CG__\OtherProject\Proxies\__CG__\stdClass;
class FooController extends AbstractActionController
{
protected $customLogger;
private function getCustomLogger()
{
if (null === $this->customLogger) {
$this->customLogger = $this->getServiceLocator()->get('Zend\CustomLogger');
}
return $this->customLogger;
}
public function indexAction()
{
$this->getCustomLogger();
$this->customLogger->controllerLog("ENTER IN Foo\Controller\FooController\index", "info");
// .... other code
}
}
Error
Zend\ServiceManager\Exception\ServiceNotCreatedException
File:
/var/www/solutions/mysolution/zend/vendor/zendframework/zendframework/library/Zend/ServiceManager/ServiceManager.php:930
Message:
An exception was raised while creating "Zend\CustomLogger"; no instance returned
PHP modules installed
bz2.so curl.so fileinfo.so iconv.so mbstring.so mysqlnd.so pdo_sqlite.so shmop.so sqlite3.so sysvshm.so xmlreader.so xsl.so
calendar.so dom.so ftp.so intl.so mysqlnd_mysqli.so pdo_mysqlnd.so phar.so simplexml.so sysvmsg.so tokenizer.so xml.so zip.so
ctype.so exif.so gettext.so json.so mysqlnd_mysql.so pdo.so posix.so sockets.so sysvsem.so wddx.so xmlwriter.so
Extension enabled in PHP ini
extension=/usr/lib64/php/5.5/modules/php_bz2.so
extension=/usr/lib64/php/5.5/modules/php_curl.so
extension=/usr/lib64/php/5.5/modules/php_fileinfo.so
extension=/usr/lib64/php/5.5/modules/php_gd2.so
extension=/usr/lib64/php/5.5/modules/php_intl.so
extension=/usr/lib64/php/5.5/modules/php_mbstring.so
extension=/usr/lib64/php/5.5/modules/php_mysql.so
extension=/usr/lib64/php/5.5/modules/php_mysqli.so
extension=/usr/lib64/php/5.5/modules/php_openssl.so
extension=/usr/lib64/php/5.5/modules/php_pdo_mysql.so
extension=/usr/lib64/php/5.5/modules/php_soap.so
extension=/usr/lib64/php/5.5/modules/php_xmlrpc.so
extension=/usr/lib64/php/5.5/modules/php_xsl.so
So simple solution... permission on log directory and some others directory are wrong. Restore the correct permissione, user and group on directory (e.g. data/logs, data/cache...)

Symfony2 execute SQL file in Doctrine Fixtures Load

I'm migrating an old web app based on SQL Server and ASP to Symfony2 and MySQL. I made some queries and export old data to individual SQL files.
How can I execute thoses files in my fixtures, when I run the command
$php app/console doctrine:fixtures:load
Now I have some fixtures that works directly with Doctrine ORM and entities, but I have a lot of data to import.
I find a good solution. I didn't find an exec method in class ObjectManager, so... this work very well for me.
public function load(ObjectManager $manager)
{
// Bundle to manage file and directories
$finder = new Finder();
$finder->in('web/sql');
$finder->name('categories.sql');
foreach( $finder as $file ){
$content = $file->getContents();
$stmt = $this->container->get('doctrine.orm.entity_manager')->getConnection()->prepare($content);
$stmt->execute();
}
}
In this solution your fixture class has to implement the ContainerAwareInterface with the method
public function setContainer( ContainerInterface $container = null )
{
$this->container = $container;
}
You can load the file contents as a string, and execute native SQL using the EntityManager:
class SQLFixtures extends AbstractFixture implements OrderedFixtureInterface
{
$filename = '/path/to/sql/file.sql';
public function load(ObjectManager $manager) {
$sql = file_get_contents($filename); // Read file contents
$manager->getConnection()->exec($sql); // Execute native SQL
$manager->flush();
}
public function getOrder() {
return 99; // Order in which this fixture will be executed
}
}
Answer for Zend Framework 2.5.3 using Doctrine Data-Fixtures.
Not sure if this applies to the given answers, but they are trying a bit too hard. If you inspect the given $manager object, you'll find that it already is the EntityManager (of interface ObjectManager) (at least, in ZF2). As such you're able to get the Connection directly and it's possible to execute without using $this->container->get('doctrine.orm.entity_manager')
Below a snippet which I use for creating the first user "system", with a createdBy FK reference to itself.
public function load(ObjectManager $manager)
{
$sql = 'INSERT INTO users (
id, username, email, display_name, `password`, created_by)
VALUES (:id, :username, :email, :display_name, :password, :created_by)';
$password = $this->createSuperDuperEncryptedPassword();
// $manager === `EntityManager|ObjectManager`, `->getConnection()` is available
$stmt = $manager->getConnection()->prepare($sql);
$stmt->bindValue(':id', 1);
$stmt->bindValue(':username', 'system');
$stmt->bindValue(':email', 'system#system.test');
$stmt->bindValue(':display_name', 'system');
$stmt->bindValue(':password', password );
$stmt->bindValue(':created_by', 1); // Self reference
$stmt->execute();
}