References to relative file paths in programs break if there are multiple entry point processes running the code

This is part of the Semicolon&Sons Code Diary - consisting of lessons learned on the job. You're in the dumb-mistakes-and-gotchas category.

Last Updated: 2024-11-21

I had the following code to assert the presence of an env file. It was for a PHP Laravel app. The code worked fine when I started the server with the usual php artistan serve on my machine.

<?php
// Somewhere in the boot process
if (! file_exists("../.env")) {
  throw new Exception('Could not find .env configuration file.');
}

However, this code broke in Docker - which was how we staged and deployed the software.

Part of the issue was that the Dockerfile did not just use php artisan serve - it also used other commands (such as some composer stuff). What happened was that, in these alternative entry points, the interpreter could not find .env file using the path description I had provided.

I had naively assumed that what mattered for file paths was relativeness to where the file containing the path was located. In fact, the relativeness here (../.env) is relative to the current working directory of the process being run, which depends on how the process was started. (This is generally true for most programming environments)

So, in this case, I figured out what was wrong by print logging the working directory as the PHP interpreter then saw it:

/var/www

This was in fact the root of the project.... therefore the file_exists argument ../.env should have been .env for this path of executing the code.

The solution overall was to explicitly use functions to build up a path up based on the location of the currently executing file:

<?php

file_exists(__DIR__ . '/../.env')