I got a question about doctrine migrations in relation with multiple databases. Accordingly to this question and mage as the deploying tool(but not restricted only to mage, because mage only does the manual thing automaticaly): Symfony: It's possible load different parameters.yml?
When i go this way, mentioned in the question posted with the link above, how can i do migrations on each database? Because to change the AppKernel loader is in my view only possible over the requested URL, which is not present for doctrine migrations, because you run it on the shell.
Did someone has a tip, how to go with this kind of setup ( one source for application, multiple databases per multiple parameters ), because its not an option for me, to build multiple fullstack symfony applications for this, because one installation has over 1GB and the only difference between the applications is the userdata, which i do not want to hold in one database, because backup policy and others ( easy backup per customer instead of pulling out from one database with customerid )
Hopefuly i did explain it exactly enough, what my question is - and more hope i did set on the issue itself and that someone has a solution ;-)
UPDATE AND SOLUTION
I got finaly a working solution, with most tasks run auto.
First, you have to define inside your SymfonyApp a folderstructure (mine is below)
_portals
|-mySUBPORTAL
|-app
|-config
|-parameters.yml.prod
|-parameters.yml.stage
|-bin
|-var
|-cache
|-.gitkeep
|-logs
|-.gitkeep
|-sessions
|-.gitkeep
|-vendor
|-.gitkeep
|-web
|-.gitkeep
|-createAppStructure.php
The File createAppStructure.php (which could be opti- or customized, if needed)
createAppStructure.php
#!/usr/bin/php
<?php
error_reporting(E_ERROR | E_WARNING | E_PARSE);
/** Parameter Check */
if(!array_key_exists(1,$argv)) exit('Es muss das Environment angegeben werden (stage|prod)'."\r\n");
/** Funktionen */
function getFolders($path)
{
$portalsDir = scandir($path);
$portals=[];
foreach($portalsDir as $portaldir)
{
if(!in_array($portaldir, [".",".."])) {
if(is_dir($path.DIRECTORY_SEPARATOR.$portaldir)) {
$portals[] = $path.DIRECTORY_SEPARATOR.$portaldir;
}
}
}
return $portals;
}
/** Alle Customers auslesen */
$env = $argv[1];
$basepath = dirname(__FILE__);
$portals = getFolders($basepath);
/** Alle Customers durchlaufen und Directory Struktur aufbauen */
$cmd = [];
$returnCode = 0;
foreach($portals as $customer)
{
$cmd=[];
/* Full Link Folders */
$cmd['fulllink'][] = "cd $customer";
$cmd['fulllink'][] = "ln -sf ../../src ./";
$cmd['fulllink'][] = "ln -sf ../../tests ./";
/* Root Struktur */
$cmd['rootDir'][] = "cd $customer";
$cmd['rootDir'][] = "ln -sf ../../composer.json ./";
$cmd['rootDir'][] = "ln -sf ../../composer.lock ./";
$cmd['rootDir'][] = "ln -sf ../../composer.phar ./";
/* App Struktur bauen */
$cmd['appDir'][] = "cd ".$customer.DIRECTORY_SEPARATOR."app/";
$cmd['appDir'][] = "ln -sf ../../../app/AppDoc ./";
$cmd['appDir'][] = "ln -sf ../../../../app/config/config.yml ./config/";
$cmd['appDir'][] = "ln -sf ../../../../app/config/config_prod.yml ./config/";
$cmd['appDir'][] = "ln -sf ../../../../app/config/config_dev.yml ./config/";
$cmd['appDir'][] = "ln -sf ../../../../app/config/config_test.yml ./config/";
$cmd['appDir'][] = "ln -sf ../../../../app/config/routing.yml ./config/";
$cmd['appDir'][] = "ln -sf ../../../../app/config/routing_dev.yml ./config/";
$cmd['appDir'][] = "ln -sf ../../../../app/config/parameters.yml.dist ./config/";
$cmd['appDir'][] = "ln -sf ../../../../app/config/security.yml ./config/";
$cmd['appDir'][] = "ln -sf ../../../../app/config/services.yml ./config/";
$cmd['appDir'][] = "ln -sf ../../../app/db ./";
$cmd['appDir'][] = "ln -sf ../../../app/DoctrineMigrations ./";
$cmd['appDir'][] = "ln -sf ../../../app/Resources ./";
$cmd['appDir'][] = "ln -sf ../../../app/.htaccess ./";
$cmd['appDir'][] = "cp -f ../../../app/AppCache.php ./";
$cmd['appDir'][] = "cp -f ../../../app/AppKernel.php ./";
$cmd['appDir'][] = "cp -f ../../../app/autoload.php ./";
$cmd['appDir'][] = "cp -f ./config/parameters.yml.".$env." ./config/parameters.yml";
/* Bin Struktur */
$cmd['binDir'][] = "cd ".$customer.DIRECTORY_SEPARATOR."bin/";
$cmd['binDir'][] = "cp -f ../../../bin/console ./";
$cmd['binDir'][] = "cp -f ../../../bin/symfony_requirements ./";
$cmd['binDir'][] = "ln -sf ../../../bin/wkhtmltox ./";
/* Var Struktur */
$cmd['varDir'][] = "cd ".$customer.DIRECTORY_SEPARATOR."var/";
$cmd['varDir'][] = "cp -f ../../../var/bootstrap.php.cache ./";
$cmd['varDir'][] = "cp -f ../../../var/SymfonyRequirements.php ./";
$cmd['varDir'][] = "ln -sf ../../../var/data ./";
/* Vendor Structure */
$cmd['vendorDir'][] = "cd $customer";
$vendorDirs = getFolders(dirname(__FILE__).DIRECTORY_SEPARATOR.'../vendor');
foreach($vendorDirs as $vendor) {
$vendorName = end(explode("/", $vendor));
if($vendorName!='composer') {
$cmd['vendorDir'][] = "ln -sf $vendor ./vendor/";
}
}
$cmd['vendorDir'][] = "cp -rpP ../../vendor/composer/ ./vendor/composer";
/* Web Struktur */
$cmd['webDir'][] = "cd ".$customer.DIRECTORY_SEPARATOR."web/";
$cmd['webDir'][] = "ln -sf ../../../web/bundles ./";
$cmd['webDir'][] = "ln -sf ../../../web/cache ./";
$cmd['webDir'][] = "ln -sf ../../../web/logos ./";
$cmd['webDir'][] = "cp -f ../../../web/.htaccess ./";
$cmd['webDir'][] = "cp -f ../../../web/app.php ./";
$cmd['webDir'][] = "cp -f ../../../web/app_dev.php ./";
$cmd['webDir'][] = "cp -f ../../../web/config.php ./";
$cmd['webDir'][] = "ln -sf ../../../web/apple-touch-icon.png ./";
$cmd['webDir'][] = "ln -sf ../../../web/favicon.ico ./";
$cmd['webDir'][] = "ln -sf ../../../web/robots.txt ./";
/* Administrative Tasks */
$cmd['administrative'][] = "cd $customer";
$cmd['administrative'][] = "./composer.phar install";
$cmd['administrative'][] = "bin/console --no-interaction doc:mig:mig";
$cmd['administrative'][] = "bin/console cache:clear --no-warmup";
$cmd['administrative'][] = "bin/console cache:warmup";
/** Run Commands */
$returnCode = 0;
$output = [];
foreach($cmd as $key => $command)
{
echo "Kommando wird ausgeführt => ".implode(" && ", $cmd[$key])." \r\n";
exec(implode(" && ", $cmd[$key]), $output, $retval);
echo "Rückgabecode: $retval"."\r\n";
$returnCode = ($retval==1) ? 1 : $returnCode ;
foreach($output as $line) {
echo "Output: $line"."\r\n";
}
}
}
exit($returnCode);
?>
You have to run this script after each deployment of your application - I did use mage (Magallanes) to deploy my application. So i did add a task (execShell) and start this script with mage. But you can also run it manualy.
After the structure is created, you can access _portals/mySUBPortal/ and you'll find a full symfony app structure with all abilities. Some type of files are copied (because otherwise, it will not work, because of the usage of DIR or FILE) and other are symlinked.
With this kind of setup you can have the same source for an SymfonyApp but different databases and working doctrine migration ...
DONT FORGET TO PUT CUSTOM VHOST (APACHE/NGINX) WHERE THE DOCUMENT_ROOT IS INSIDE _PORTALS.