Project directory constant

In public/index.php we have chdir(dirname(__DIR__)); this helps to get the project current working directory via getcwd() .

It looks to me that expressive can define a constant as CWD or something else, so we can use it inside the modules, and libraries we are building.

The problem with using getcwd() inside a library is we don’t know if some library purposefully changed the path via the same chdir function.

If we agree with a constant name, I am happy to send a PR for the same to zend-expressive-skelton.

The reason we do the chdir() is to ensure that operations using filesystem paths can be relative to the application root. Generally speaking, you shouldn’t use getcwd(); you should just specify a path relative to the application root:

'cache' => [
    'path' => 'data/cache/'
],

The few places where that fails are when creating resources, such as a SQLite path for PDO, as these generally need a fully qualified path.

Generally speaking, the PWD/CWD should never change once the request cycle has begun. If you find this happening, then I’d argue that the code doing so should be reviewed.

I’m against defining a constant, as that becomes a global value on which your code then depends, which is something we typically do not encourage.

3 Likes

Who can guarantee if a library or package call chdir ?

I agree with your concern about the global value. How about in the container config ?

I always use __DIR__ constant whenever I need a path. After creating new project from a skeleton I remove chdir from public/index.php and add __DIR__ everywhere. I use it configure the cache path (__DIR__ . '/../../data/cache'), I use it in the application.config.php file, in config loader with glob paths, etc.

__DIR__ acts kind of like global variable but it’s there by definition. And any library could change cwd of the app. It’s wrong but could happend. And it won’t affect my apps.

@piotrek What I was trying to do is pass the value to the library, so we don’t need to call dirname() or ../ .

I fully agree with the idea of not using constants, but just for info about getcwd,

@matthew Generally speaking, you shouldn’t use getcwd(); you should just specify a path relative to the application root…

'cache' => [
   'path' => 'data/cache/'
] 

Imagine:

  logger' => [  ... 'path' => 'data/log/' ] 

For example using a Monolog RotatingFileHandler, I forgot a getcwd() and was wondering why it was not rotated because it uses glob to match old log files:

$logFile = getcwd() . $container->get(config)['logger']['path']; // for brevity
$logger   = new Logger('mylogger');
$logger->pushProcessor(new PsrLogMessageProcessor());
$logger->pushHandler(
   new Handler\RotatingFileHandler($logFile, $days, Logger::INFO)
);

Not a big problem, but good to remember if a library requires a full path. I’m not particularly fond of placing placeholders in config, but that could be considered in this case.

1 Like