Open vinpel opened 7 years ago
after futher reseach it's not a bug
Documentation is not clear in the namespace config part.
It work fine if the vendor library is defined as a yii2-extension
see : http://www.yiiframework.com/doc-2.0/guide-structure-extensions.html
when you type : `composer require library
an alias is created in ./vendor/yiisoft/extensions.php :
'@mycompagny/myExtension' => $vendorDir . 'mycompagny/myExtension/src',
so now in the namespace name :
'controllerMap' => [
'migrate' => [
'class' => 'yii\console\controllers\MigrateController',
'migrationNamespaces' => [
"mycompagny\myExtension\migrations",
...
]
will work correctly
library with yii2 migration or mandatory to be yii2-extension
I have same problem. I have my composer package with yii2 migrations. I did not plan to make it yii2 extension. And I think creating alias for vendor is weird.
I think that if migrationNamespaces
forces to use aliases with it, and does not work without aliases, it is a bug.
Do you use namespaced migrations or classic migrations? The latter should be used with migrationPath
. --migrationPath
accepts an array of aliases since 2.0.12 see https://github.com/yiisoft/yii2/pull/14241
Also related:
@schmunk42 thanks for #14241, I solved my task this via migrationPath
.
I am disillusioned with migrationNamespaces
: it's neither simple nor intuitive. I think migrationPath
approach is better since 2.0.12, as it allows:
and does not require alias to be the same as namespace (namespace is just not used).
Docs state that benefit of migration namespaces is that it adds origin of the migration to the history
In general, to load migrations from different locations, $migrationNamespaces is the preferable solution as the migration name contains the origin of the migration in the history, which is not the case when using multiple migration paths.
But migrationPath
could provide this too, we just need to make it support origin in some way, maybe like this:
'migrationPath' => [
'origin1' => '@root/migrations',
'origin2' => '@vendor/cronfy/..../src/migrations',
]
To summarize: I think namespaces should not be used directly as migration origin, because namespace is subject to change. Origin must be specified separately.
To summarize: I think namespaces should not be used directly as migration origin, because namespace is subject to change. Origin must be specified separately.
FYI: Before 2.0.12 I used our extension https://github.com/dmstr/yii2-migrate-command to handle multiple migrations, I modified the migration table structure to include the alias(-path), so mapping would actually possible via aliases. But this would have been a BC-break if introduced into the framework.
The table looked like this:
I faced again the same probleme, and found a solution to correctly use just namespace for migration.
Consider the following structure :
I have a yii2 extension, directory structure as :
./src/migrations : migration file with namespace company\myExtension
.tests : tests and config file for tests
the composer.json had the following PR4 configuration :
"autoload": {
"psr-4": {
"company\\myExtension\\": "src/"
}
},
Now i want to be able tu use the migration, here in a partial of my config file :
'controllerMap' => [
'migrate' => [
'class' => 'yii\console\controllers\MigrateController',
'migrationPath' => null,
'migrationNamespaces' => [
'company\myExtension\migrations'
],
],
],
using the following command to migrate :
./vendor/bin/yii migrate --appconfig=./tests/config.php
i get the following message :
Yii Migration Tool (based on Yii v2.0.15.1)
No new migrations found. Your system is up-to-date.
the problem is that the namespace is translated to a directory, without looking for psr-4 relation.
Here is my proposed fix , avaible for discussion :
in file :
/**
* Returns the file path matching the give namespace.
* @param string $namespace namespace.
* @return string file path.
* @since 2.0.10
*/
private function getNamespacePath($namespace)
{
//search for psr4 configuration
$autoload_psr4_file = yii::getAlias('@vendor/composer/autoload_psr4.php');
if (is_file($autoload_psr4_file)) {
$autoload_array = require $autoload_psr4_file;
foreach ($autoload_array as $psr4_namespace => $physical_paths) {
if (strcmp($psr4_namespace, substr($namespace, 0, strlen($psr4_namespace))) == 0) {
return str_replace('/', DIRECTORY_SEPARATOR, $physical_paths[0] . DIRECTORY_SEPARATOR . substr($namespace, strlen($psr4_namespace)));
}
}
}
//fallback
return str_replace('/', DIRECTORY_SEPARATOR, Yii::getAlias('@' . str_replace('\\', '/', $namespace)));
}
and now :
Yii Migration Tool (based on Yii v2.0.15.1)
Total 4 new migrations to be applied:
company\myExension\migrations\m181122_120000_hello_world
The following should work:
composer.json
{
...
"autoload": {
"psr-4": {
"company\\myExtension\\": "src/"
}
}
}
config.php
<?php
return [
...
'aliases' => [
'@company/myExtension' => '@app/src',
],
'controllerMap' => [
'migrate' => [
'class' => 'yii\console\controllers\MigrateController',
'migrationPath' => null,
'migrationNamespaces' => [
'company\myExtension\migrations',
],
],
],
];
Then run ./vendor/bin/yii migrate --appconfig=<path to config.php>
i confirm that the response by @OscarBarrett nearly work for me.
When you launch the migration with the --appconfig=XXX the "@app" is where the config is located.
This work for me :
<?php
return [
...
'aliases' => [
'@company/myExtension' => '@app/../src',
],
'controllerMap' => [
'migrate' => [
'class' => 'yii\console\controllers\MigrateController',
'migrationPath' => null,
'migrationNamespaces' => [
'company\myExtension\migrations',
],
],
],
];
Introduction
I want to automaticly apply new migration from my Yii2 library installed in the vendor path with a yii migrate from main project
I use deployer to install app in the production server, i want to have a garanty of correlation between the code version and the database structure.
What steps will reproduce the problem?
My library is in : /vendor/mycompagny/myExtension
/vendor/mycompagny/myExtension/composer.json:
(note the "src" subdirectory who make namespace!=directory)
I set up the application this way :
Now if 'myExtension' have a new version with a new migration i will apply modification with :
What is the expected result?
the new migration is applied
What do you get instead?
What is the origin of the problem ?
The docs claim "namespace setting" but this code search for a file on the disk :
https://github.com/yiisoft/yii2/blob/4e176ca3259083a8c441c70182bc10e96cbfec12/framework/console/controllers/BaseMigrateController.php#L706-L709
Actually :
For me the correct way could be :
How you could bypass the problem ?
Use this setup :
Creating an alias for each vendor just because YiI2 search for a @+namespace is not a good behavior for me.
Additional info