Created
March 17, 2016 17:24
-
-
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 file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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