Module getBasePath of is wrong if module is "installed" via local repository in dev mode
What steps will reproduce the problem?
I have installed the "dektrium/yii2-user" module in dev mode and wanted to override the view path as mentioned in the modules documentation. https://github.com/dektrium/yii2-user/blob/master/docs/overriding-views.md
I have added the local repository to the composer.json
"repositories": [
{
"packagist.org": false
},
{
"type": "path",
"url": "../packages/dektrium/yii2-user"
}
],
and installed the module in dev mode so it is only symlinked from the repository source.
composer require "dektrium/yii2-user @dev"
I have set the view Map in my config file.
'view' => [
'class' => 'app\components\web\View',
'theme' => [
'pathMap' => [
'@dektrium/user/views' => '@app/views/user',
],
],
],
and also stored the view files in the correct path.
The problem is because of the dev mode (symlinked source and not copied)
The module::getBasePath() function returns e.g.
..\\packages\\dektrium\\yii2-user
instead of the path:
...\test-app\\vendor\\dektrium\\yii2-user
when it is "really installed". (everything works as expected if module is installed correctly)
What is the expected result?
I expected the modules correct vendor path also when the source comes from a local repository.
What do you get instead?
Because the files are symlinked I only get the path of the original source. And therefore the wrong path and therefore the view overwrite doesn't work.
Additional info
Could i somehow set the basePath of the module myself? Could be that this issue is only windows specific and if of course only because the sources are symlinked from a local repository.
How do other dev's solve this problem when doing local development?
| Q | A |
|---|---|
| Yii version | 2.0.? |
| PHP version | 5.6.16 |
| Operating system | Windows |
If the Module::getBasePath function would be changed similar to the Module::getControllerPath function and would use getAlias to get the directory it would work. Still don't know if this is maybe some Windows only issue (i am running win7)
public function getBasePath()
{
if ($this->_basePath === null) {
// $class = new \ReflectionClass($this);
// $this->_basePath = dirname($class->getFileName());
$class = new \ReflectionClass($this);
$this->_basePath = Yii::getAlias('@' . str_replace('\\', '/', $class->getNamespaceName()));
}
return $this->_basePath;
}
there is setBasePath() so you can set the path in module configuration.
doesn't work.
Even if i set the same Path which is returned from my above code directly in the config. Inside setBasePath the realpath($path) call destroys the path and returns the orignal symlinked path ...
So i can't set it in the config as it just would return the real path.
The problem I also coudn't test something like this in setBasePath because the "yii2-user" dir isn't symlinked but the folder above. I must then check each directory level until the vendor path to check if
the path is maybe a symlink but still correct.
if (is_link($path)) {
echo readlink($path);
}
realpath call has been introduced by this commit: https://github.com/yiisoft/yii2/commit/5b412b8f84f7351889b9b046bc484d98b9ec017b#diff-d24221cf7f251030273dc9f1c436ba75R215
@qiangxue do you remember why it was added?
I am having this problem myself. I have added a composer package to my project and set it to have symlink under vendor folder. I cannot use theme for overriding views unless i remove the package and add it again as not symlinked.
This is a huge problem when you are developing av yii2 application at the same time you are developing av composer package that is required from a local path (local path repository).
I'll review it and we'll fix it for the next version.
I'll review it and we'll fix it for the next version.
Please ask if you need details!
If you have the details, just post them, it will be easier to resolve.
One short example why this bug needs to be fixed:
When you are developing a composer package for Yii framework, you need a running Yii2 application that has imported/required your package. The package needs to have a symlink (shortcut) under vendors folder so that your changes to the package is visible immediately in your application. This works good until you need to override views, so you need to require your package again without symlink, so now you have a copy of that package under vendors. The changes you do to the package needs to be copied into the vendors folder each time you want to see changes reflected in the Yii2 application.
I have created a script that will set up a Yii2 application and will require a composer package from a local path. Please unzip the attached file and run the setup.sh file.
In the zip file, there is:
- a composer package under folder
yii2-userwhich will be required first with symlink, then later without to show the bug resources/web.phpwhich will overwrite theconfig/web.phpand which defined the new module with the overriding of views set upresouces/index.phpwhich is the view that should override the view in package
Here is a copy of the setup file to see what it is doing:
#!/usr/bin/env bash
# remove the app folder if already exists
#sudo rm -rf app
# Set up a Yii2 application under folder app
composer create-project yiisoft/yii2-app-basic app
# Set application to accept packages under development
cd app
composer config minimum-stability dev
# Add a repository for the local package
echo "Add repository for the local package"
composer config repositories.my-local-repo path ../yii2-user
# Require this package into the application as a symlink (--prefer-source created the symlink):
echo "Require the local package"
composer require my/yii2-user:dev-main --prefer-source
# Overwrite the config file with a new file where the module is added and override the view
cp ../resources/web.php ./config/
# create the new view file that will override the my\yii2user\views\admin\index file
mkdir -p views/user/admin
cp ../resources/index.php ./views/user/admin
echo "----------------------------------------------------------------------------"
echo "The application is now set up with a package symlinked under vendors folder."
echo "Verify this by loading the page: http://localhost/bug/app/web/?r=user/admin"
echo "Press any key to change the package into a copy to see that the overridden file is shown instead"
echo "----------------------------------------------------------------------------"
read -p "Press Enter to continue..."
# Delete the package
composer remove my/yii2-user
# Update the repository to NOT symlink the package under vendors folder
composer config repositories.my-local-repo '{"type": "path", "url": "../yii2-user", "options": {"symlink": false}}'
# Add the package again (without symlink)
composer require my/yii2-user:dev-main
echo "Now reload the page in the app to see the overriden view"
cd ..
I am running PHP 8.4, Linux, Yii 2.0.53