Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save progmars/1e545d96dd48676a2aa7 to your computer and use it in GitHub Desktop.
Save progmars/1e545d96dd48676a2aa7 to your computer and use it in GitHub Desktop.
Workaround for Dotenv and issues with concurrent requests failing (especially on Windows) because of PHP threaded getenv/putenv implementation. To make this really work, use `getEnvironmentVariable` instead of `getenv` everywhere (e.g. Laravel's `env()` helper, as in the patch https://gist.github.com/progmars/5c18235360c04b621ed7 ).
This is a workaround patch for `getenv()` unstable behavior in multithreaded "PHP as Apache module" environments
(e.g. some prepackaged WAMP stacks).
See
https://github.com/vlucas/phpdotenv/issues/76
https://github.com/vlucas/phpdotenv/issues/163
This fix is intended only for development environments, the same as Dotenv itself.
The paths are based on Composer's vendor directory.
diff --git a/vendor/vlucas/phpdotenv/src/Dotenv.php b/vendor/vlucas/phpdotenv/src/Dotenv.php
index 0737a70..d734a8b 100644
--- a/vendor/vlucas/phpdotenv/src/Dotenv.php
+++ b/vendor/vlucas/phpdotenv/src/Dotenv.php
@@ -55,6 +55,16 @@ class Dotenv
}
/**
+ * Returns current loader.
+ *
+ * @return \Dotenv\Loader
+ */
+ public function getLoader()
+ {
+ return $this->loader;
+ }
+
+ /**
* Returns the full path to the file.
*
* @param string $path
diff --git a/vendor/vlucas/phpdotenv/src/Loader.php b/vendor/vlucas/phpdotenv/src/Loader.php
index ec843e9..4964485 100644
--- a/vendor/vlucas/phpdotenv/src/Loader.php
+++ b/vendor/vlucas/phpdotenv/src/Loader.php
@@ -29,6 +29,14 @@ class Loader
protected $immutable;
/**
+ * Cache to work around issues of getenv() losing values
+ * in multithread configurations.
+ *
+ * @var array
+ */
+ protected $cache;
+
+ /**
* Create a new loader instance.
*
* @param string $filePath
@@ -40,6 +48,7 @@ class Loader
{
$this->filePath = $filePath;
$this->immutable = $immutable;
+ $this->cache = [];
}
/**
@@ -300,6 +309,9 @@ class Loader
public function getEnvironmentVariable($name)
{
switch (true) {
+ // Patched to check the local cache first.
+ case array_key_exists($name, $this->cache):
+ return $this->cache[$name];
case array_key_exists($name, $_ENV):
return $_ENV[$name];
case array_key_exists($name, $_SERVER):
@@ -316,7 +328,8 @@ class Loader
* This is done using:
* - putenv,
* - $_ENV,
- * - $_SERVER.
+ * - $_SERVER
+ * and local cache to work around losing values in some environments.
*
* The environment variable value is stripped of single and double quotes.
*
@@ -329,12 +342,30 @@ class Loader
{
list($name, $value) = $this->normaliseEnvironmentVariable($name, $value);
+ // Patched to support more reliable environment value lookup
+ // in some environments.
+ // See
+ // https://github.com/vlucas/phpdotenv/issues/76
+ // https://github.com/vlucas/phpdotenv/issues/163
+
+ $currentValue = $this->getEnvironmentVariable($name);
+
+ // If we got the value but didn't have it in our cache yet,
+ // then it was specified from outside (possibly leaked from another thread).
+ // Now let's propagate this behavior into Dotenv and sync the cache
+ // with the current value for consistency.
+ if ($currentValue !== null && !array_key_exists($name, $this->cache)){
+ $this->cache[$name] = $currentValue;
+ }
+
// Don't overwrite existing environment variables if we're immutable
// Ruby's dotenv does this with `ENV[key] ||= value`.
- if ($this->immutable && $this->getEnvironmentVariable($name) !== null) {
+ if ($this->immutable && $currentValue !== null) {
return;
}
+ $this->cache[$name] = $value;
+
putenv("$name=$value");
$_ENV[$name] = $value;
@@ -349,7 +380,7 @@ class Loader
*
* This is done using:
* - putenv,
- * - unset($_ENV, $_SERVER).
+ * - unset($_ENV, $_SERVER, $this->cache).
*
* @param string $name
*
@@ -366,6 +397,7 @@ class Loader
putenv($name);
- unset($_ENV[$name], $_SERVER[$name]);
+ // Patched to clear everything, including the cache
+ unset($_ENV[$name], $_SERVER[$name], $this->cache[$name]);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment