yii2 icon indicating copy to clipboard operation
yii2 copied to clipboard

Module getBasePath of is wrong if module is "installed" via local repository in dev mode

Open Bhoft opened this issue 8 years ago • 9 comments

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

Bhoft avatar Jun 02 '17 10:06 Bhoft

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;
}

Bhoft avatar Jun 02 '17 12:06 Bhoft

there is setBasePath() so you can set the path in module configuration.

cebe avatar Jun 02 '17 12:06 cebe

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);
}

Bhoft avatar Jun 02 '17 13:06 Bhoft

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?

cebe avatar Jun 02 '17 13:06 cebe

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).

paalg avatar Sep 24 '25 12:09 paalg

I'll review it and we'll fix it for the next version.

terabytesoftw avatar Sep 24 '25 13:09 terabytesoftw

I'll review it and we'll fix it for the next version.

Please ask if you need details!

paalg avatar Sep 24 '25 13:09 paalg

If you have the details, just post them, it will be easier to resolve.

terabytesoftw avatar Sep 24 '25 13:09 terabytesoftw

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-user which will be required first with symlink, then later without to show the bug
  • resources/web.php which will overwrite the config/web.php and which defined the new module with the overriding of views set up
  • resouces/index.php which 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

example.zip

paalg avatar Sep 25 '25 13:09 paalg