Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

getPathOfAlias('webroot') return wrong value in console applications at least with default settings #1267

Closed
teo1978 opened this issue Aug 21, 2012 · 31 comments

Comments

@teo1978
Copy link

teo1978 commented Aug 21, 2012

yiic seems to be designed to be run from the "protected" directory, at least that's what all the tutorials suggest.

however, when you run a ConsoleApplication using yiic, at least without tweaking any of the default settings of a default installation, getPathOfAlias('webroot') will return the path of the protected directory, which usually not the webroot.

This seems to be because CApplication sets the path of webroot to dirname($_SERVER['SCRIPT_FILENAME'])
(https://github.com/yiisoft/yii/blob/1.1.12/framework/base/CApplication.php#L136) but that's the expected value only for web applications.

@qiangxue
Copy link
Member

Note an issue since 'webroot' is not well defined by nature when you run the app in console mode.

@teo1978
Copy link
Author

teo1978 commented Aug 21, 2012

Hmmm, I guess you're right from a phylosophical point of view. However, if one writes a command script to automate a series of actions usually performed from the web, and hence call code that was written for the web, (isn't that quite common?), then that will break a lot of code. Then probably a good solution would be to offer a way to easily configure the path of webroot via the application's config - or is that already possible?

@teo1978
Copy link
Author

teo1978 commented Aug 21, 2012

I mean, if it is not well defined by nature, then it means it should be possible and easy to define it artificially.

@cebe
Copy link
Member

cebe commented Aug 21, 2012

@matteosistisette you can set Yii::setPathOfAlias('webroot', ...) to your desired path when in console scope e.g. in console config file.

@teo1978
Copy link
Author

teo1978 commented Aug 21, 2012

whopssss I forgot I could execute statements before returning the config array :$:$:$

@teo1978
Copy link
Author

teo1978 commented Apr 15, 2013

Hey, this needs to be reopened!
@cebe 's suggestion DOES NOT work because it cannot be done in config/console.php file, because that is run BEFORE the framework's code calls base/CApplication.php: Yii::setPathOfAlias('webroot',dirname($_SERVER['SCRIPT_FILENAME']));

So, whatever value you set within config/console.php, is then overwritten.
The only way to change the default value of the path is to call setPathOfAlias after the application is created but before it is run. Which right now means changing the very framework's yiic.php. Not the one in protected, but the one in framework, because that calls run().

A way must be provided to override the default "webroot" alias without having to modify framework code.

@samdark
Copy link
Member

samdark commented Apr 15, 2013

You can do so in index.php, for example:

$config = require '...';
$app = Yii::createWebApplication($config);
Yii::setPathOfAlias('webroot',dirname($_SERVER['SCRIPT_FILENAME']));
$app->run();

@cebe
Copy link
Member

cebe commented Apr 15, 2013

@matteosistisette you can put your setPathOfAlias statement into your application preinit() method to overide the default one.

@teo1978
Copy link
Author

teo1978 commented Apr 15, 2013

@samdark it's yiic.php not index.php. It includes the framework's yiic.php which calls both createapplication and run

@AnatolyRugalev
Copy link
Contributor

$config = require '...';
$app = Yii::createWebApplication($config);
chdir('../'); //going to webroot
$app->run();

works like magic

@teo1978
Copy link
Author

teo1978 commented Apr 15, 2013

@AnatolyRugalev it's a ConsoleApplication not a WebApplication and I'm afraid of the side effects of chdir'ing. Anyway I thing @cebe's preinit() suggestion is the solution indeed.

However wouldn't it be more elegant to allow configuring it in the config array the same way it can be done with basePath?? like in https://github.com/yiisoft/yii/blob/1.1.13/framework/base/CApplication.php#L135

@samdark
Copy link
Member

samdark commented Apr 15, 2013

A console app could be for 5—6 webroots or w/o webroots at all. I think it's too application specific.

@cebe
Copy link
Member

cebe commented Apr 15, 2013

The thing I found weird here is that CApplication defines the alias and not CWebApplication. But we can not change this as of BC.

@teo1978
Copy link
Author

teo1978 commented Apr 15, 2013

Hey but how am I supposed to override preinit() if yiic.php hardcodedly instantiates a CConsoleApplication ??

@AnatolyRugalev
Copy link
Contributor

@matteosistisette, sorry, I copied @samdark's code. This works perfect for me

@cebe
Copy link
Member

cebe commented Apr 15, 2013

@matteosistisette you can also have your own yiic.php by just copying over from the framework if you have special needs.

@teo1978
Copy link
Author

teo1978 commented Apr 15, 2013

Ok. I thought I should strive to avoid that, it seems a pretty dirty hack

@teo1978
Copy link
Author

teo1978 commented Apr 15, 2013

Also I wonder where I would have to place my extended ConsoleApplication class, as I don't think it will find it in the "components" folder at that stage of code initialization...

@teo1978
Copy link
Author

teo1978 commented Apr 15, 2013

In the end this is the old problem of "how do I cleanly extend CConsoleApplication or CWebApplication"

@cebe
Copy link
Member

cebe commented Apr 15, 2013

there is no problem with putting it in components folder and also overriding yiic.php is not dirty.

@resurtm
Copy link
Contributor

resurtm commented Apr 15, 2013

I don't see a problem here as well. I rarely use built-in webroot alias and i always use my own alias (which can be called something like www, media, htdocs, etc.).

@teo1978
Copy link
Author

teo1978 commented Apr 15, 2013

@resurtm that's not always an option. Sometimes you need the same code to be run both from web and console application. Anyway, the solution is extending CConsoleApplication (you need to explicitly include the file too) and copying and modifying framework/yiic.php in order to use that. I still think having to "rewrite" the whole core yiic.php file just to change the name of the class being instantiated is too much, though. (e.g. the name of the application class should be allowed to be defined in the config file, or in a constant or whatever)

@samdark
Copy link
Member

samdark commented Apr 15, 2013

@matteosistisette here's the solution w/o overriding the app:

yiic.php:

defined('STDIN') or define('STDIN', fopen('php://stdin', 'r'));
defined('YII_DEBUG') or define('YII_DEBUG',true);
require_once('path_to_framework'.'/yii.php');
$config = require 'path_to_config.php';
$app=Yii::createConsoleApplication($config);

$app->commandRunner->addCommands(YII_PATH.'/cli/commands');
$env=@getenv('YII_CONSOLE_COMMANDS');
if(!empty($env))
   $app->commandRunner->addCommands($env);

Yii::setPathOfAlias('webroot','path_to_your_webroot');

$app->run();

@cebe
Copy link
Member

cebe commented Apr 15, 2013

I still think having to "rewrite" the whole core yiic.php file just to change the name of the class being instantiated is too much

yiic.php in the framework is an example of how to create a console application. If you have special needs you can copy that example and adjust it.

@teo1978
Copy link
Author

teo1978 commented Apr 15, 2013

Just to clarify I'm talking about the one that is inside the framework directory, not the one in the protected directory which include()s it.

@resurtm
Copy link
Contributor

resurtm commented Apr 15, 2013

@matteosistisette:

@resurtm that's not always an option. Sometimes you need the same code to be run both from web and console application.

I'm defining all custom aliases both in console.php and main.php configs and i use the same code which deals with aliases both from console and web applications. This is not an issue.

@teo1978
Copy link
Author

teo1978 commented Apr 15, 2013

@resurtum of course if you plan it in advance. If you have already written a webapp that uses the webroot alias in a thousand places and then decide to create a console app that will do some job using the same models, you would have to do a search and replace.

@cebe
Copy link
Member

cebe commented Apr 15, 2013

Just to clarify I'm talking about the one that is inside the framework directory, not the one in the protected directory which include()s it.

I know, I was talking about the file in the framework dir. It is included by the one in the application as it uses same functionality in simple cases. You can have your own console app in a yiic.php but you can also name your console app file like you want. Use the framework yiic as a template but no need to include it at all.

@konapaz
Copy link

konapaz commented Dec 4, 2014

In my case

Yii::setPathOfAlias('webroot',getcwd().'/protected');

@dtmp
Copy link

dtmp commented Sep 2, 2015

if (get_class(Yii::app()) == 'CConsoleApplication') {
r o o t p a t h = p r e g r e p l a c e ( / / p r o t e c t e d /', '', Yii::getPathOfAlias('webroot'))
}

@wesslim
Copy link

wesslim commented Jul 14, 2021

is there any solution?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

9 participants