Create dotenv readEnvFile single function

This commit is contained in:
2021-10-11 08:58:36 +09:00
commit de80a9c061
4 changed files with 166 additions and 0 deletions

43
Readme.md Normal file
View File

@@ -0,0 +1,43 @@
# dotenv: readEnvFile()
A single function implementation of https://github.com/vlucas/phpdotenv
This is not a functional replacement, but a very simple implementation of the basic functions.
## How it works
Put the function where it is needed or put it in a file and load it.
if not parameter is given it will use `__DIR__` as base path.
Second parameter is file name override. Default is `.env`
Data is loaded into _ENV only.
If there is already an entry in _ENV then it will not be overwritten.
## .env file example
A valid entry has to start with an alphanumeric string, underscores are allowed and
then have an equal sign (=). After the equal sign the data block starts. Data can be
quoted with double quotes (") and if this is done can stretch over multiple lines.
The openeing double quote must be on the same lign as the requal sign (=). If double
quoted (") charcters are used it will read each line until another double quote (")
character is found. Everything after that is ignored.
Any spaces before the variable or before and after the equal sign (=) are ignored.
Line is read until `PHP_EOL`. So any trailing spaces are read too.
Any line that is not valid is ignored.
```ini
# this line is ignored
SOMETHING=A
OTHER="A B C"
MULTI_LINE="1 2 3
4 5 6
7 8 9" ; and this is ignored
ESCAPE="String \" inside \" other "
DOUBLE="I will be used"
DOUBLE="This will be ignored"
```

83
src/read_env_file.php Normal file
View File

@@ -0,0 +1,83 @@
<?php
/**
* parses .env file
*
* Rules for .env file
* variable is any alphanumeric string followed by = on the same line
* content starts with the first non space part
* strings can be contained in "
* strings MUST be contained in " if they are multiline
* if string starts with " it will match until another " is found
* anything AFTER " is ignored
* if there are two variables with the same name only the first is used
* variables are case sensitive
*
* @param string $path Folder to file, default is __DIR__
* @param string $env_file What file to load, default is .env
* @return int -1 other error
* 0 for success full load
* 1 for file loadable, but no data inside
* 2 for file not readable
* 3 for file not found
*/
function readEnvFile(string $path = __DIR__, string $env_file = '.env'): int
{
// default -1;
$status = -1;
$env_file_target = $path . DIRECTORY_SEPARATOR . $env_file;
// this is not a file -> abort
if (!is_file($env_file_target)) {
$status = 3;
return $status;
}
// cannot open file -> abort
if (($fp = fopen($env_file_target, 'r')) === false) {
$status = 2;
return $status;
}
// set to readable but not yet any data loaded
$status = 1;
$block = false;
$var = '';
while ($line = fgets($fp)) {
// main match for variable = value part
if (preg_match("/^\s*([\w_]+)\s*=\s*((\"?).*)/", $line, $matches)) {
$var = $matches[1];
$value = $matches[2];
$quotes = $matches[3];
// wirte only if env is not set yet, and write only the first time
if (empty($_ENV[$var])) {
if (!empty($quotes)) {
$block = true;
// match greedy for first to last so we move any " if there are
if (preg_match('/^"(.*[^\\\])"/U', $value, $matches)) {
$value = $matches[1];
} else {
// first " in string remove
// add removed new line back because this is a multi line
$value = ltrim($value, '"') . PHP_EOL;
}
}
// if block is set, we strip line of slashes
$_ENV[$var] = $block === true ? stripslashes($value) : $value;
// set successful load
$status = 0;
}
} elseif ($block === true) {
// read line until there is a unescaped "
// this also strips everything after the last "
if (preg_match("/(.*[^\\\])\"/", $line, $matches)) {
$block = false;
// strip ending " and EVERYTHING that follows after that
$line = $matches[1];
}
// strip line of slashes
$_ENV[$var] .= stripslashes($line);
}
}
fclose($fp);
return $status;
}
// __END__

25
test/.env Normal file
View File

@@ -0,0 +1,25 @@
# enviroment file
SOMETHING=A
OTHER="B IS B"
Complex="A B \"D is F"
HAS_SPACE= "ABC";
FAILURE = ABC
SIMPLEBOX= A B C
TITLE=1
FOO=1.2
Test="A"
TEST="B"
TEST="D"
LINE="ABC
DEF"
OTHERLINE="ABC
AF\"ASFASDF
MORESHIT"
SUPERLINE=
"asfasfasf"
__FOO_BAR_1 = b
__FOOFOO = f
123123=number
EMPTY=
= flase
asfasdf

15
test/read_env_file.php Normal file
View File

@@ -0,0 +1,15 @@
<?php // phpcs:ignore PSR1.Files.SideEffects
// test read .env file
require '../src/read_env_file.php';
print "BASE: " . __DIR__ . "<br>";
print "ORIG: <pre>" . file_get_contents(__DIR__ . DIRECTORY_SEPARATOR . '.env') . "</pre>";
$status = readEnvFile(__DIR__);
print "STATUS: " . ($status ? 'OK' : 'FAIL') . "<br>";
print "ENV: <pre>" . print_r($_ENV, true) . "</pre><br>";
// __END__