Giter Site home page Giter Site logo

vlucas / phpdotenv Goto Github PK

View Code? Open in Web Editor NEW
12.9K 172.0 615.0 661 KB

Loads environment variables from `.env` to `getenv()`, `$_ENV` and `$_SERVER` automagically.

License: BSD 3-Clause "New" or "Revised" License

PHP 98.99% Makefile 1.01%
hacktoberfest php environment dotenv environment-variables configuration

phpdotenv's Introduction

PHP dotenv

Loads environment variables from .env to getenv(), $_ENV and $_SERVER automagically.

Banner

Software License Total Downloads Latest Version

Why .env?

You should never store sensitive credentials in your code. Storing configuration in the environment is one of the tenets of a twelve-factor app. Anything that is likely to change between deployment environments – such as database credentials or credentials for 3rd party services – should be extracted from the code into environment variables.

Basically, a .env file is an easy way to load custom configuration variables that your application needs without having to modify .htaccess files or Apache/nginx virtual hosts. This means you won't have to edit any files outside the project, and all the environment variables are always set no matter how you run your project - Apache, Nginx, CLI, and even PHP's built-in webserver. It's WAY easier than all the other ways you know of to set environment variables, and you're going to love it!

  • NO editing virtual hosts in Apache or Nginx
  • NO adding php_value flags to .htaccess files
  • EASY portability and sharing of required ENV values
  • COMPATIBLE with PHP's built-in web server and CLI runner

PHP dotenv is a PHP version of the original Ruby dotenv.

Installation

Installation is super-easy via Composer:

$ composer require vlucas/phpdotenv

or add it by hand to your composer.json file.

Upgrading

We follow semantic versioning, which means breaking changes may occur between major releases. We have upgrading guides available for V2 to V3, V3 to V4 and V4 to V5 available here.

Usage

The .env file is generally kept out of version control since it can contain sensitive API keys and passwords. A separate .env.example file is created with all the required environment variables defined except for the sensitive ones, which are either user-supplied for their own development environments or are communicated elsewhere to project collaborators. The project collaborators then independently copy the .env.example file to a local .env and ensure all the settings are correct for their local environment, filling in the secret keys or providing their own values when necessary. In this usage, the .env file should be added to the project's .gitignore file so that it will never be committed by collaborators. This usage ensures that no sensitive passwords or API keys will ever be in the version control history so there is less risk of a security breach, and production values will never have to be shared with all project collaborators.

Add your application configuration to a .env file in the root of your project. Make sure the .env file is added to your .gitignore so it is not checked-in the code

S3_BUCKET="dotenv"
SECRET_KEY="souper_seekret_key"

Now create a file named .env.example and check this into the project. This should have the ENV variables you need to have set, but the values should either be blank or filled with dummy data. The idea is to let people know what variables are required, but not give them the sensitive production values.

S3_BUCKET="devbucket"
SECRET_KEY="abc123"

You can then load .env in your application with:

$dotenv = Dotenv\Dotenv::createImmutable(__DIR__);
$dotenv->load();

To suppress the exception that is thrown when there is no .env file, you can:

$dotenv = Dotenv\Dotenv::createImmutable(__DIR__);
$dotenv->safeLoad();

Optionally you can pass in a filename as the second parameter, if you would like to use something other than .env:

$dotenv = Dotenv\Dotenv::createImmutable(__DIR__, 'myconfig');
$dotenv->load();

All of the defined variables are now available in the $_ENV and $_SERVER super-globals.

$s3_bucket = $_ENV['S3_BUCKET'];
$s3_bucket = $_SERVER['S3_BUCKET'];

Putenv and Getenv

Using getenv() and putenv() is strongly discouraged due to the fact that these functions are not thread safe, however it is still possible to instruct PHP dotenv to use these functions. Instead of calling Dotenv::createImmutable, one can call Dotenv::createUnsafeImmutable, which will add the PutenvAdapter behind the scenes. Your environment variables will now be available using the getenv method, as well as the super-globals:

$s3_bucket = getenv('S3_BUCKET');
$s3_bucket = $_ENV['S3_BUCKET'];
$s3_bucket = $_SERVER['S3_BUCKET'];

Nesting Variables

It's possible to nest an environment variable within another, useful to cut down on repetition.

This is done by wrapping an existing environment variable in ${…} e.g.

BASE_DIR="/var/webroot/project-root"
CACHE_DIR="${BASE_DIR}/cache"
TMP_DIR="${BASE_DIR}/tmp"

Immutability and Repository Customization

Immutability refers to if Dotenv is allowed to overwrite existing environment variables. If you want Dotenv to overwrite existing environment variables, use createMutable instead of createImmutable:

$dotenv = Dotenv\Dotenv::createMutable(__DIR__);
$dotenv->load();

Behind the scenes, this is instructing the "repository" to allow immutability or not. By default, the repository is configured to allow overwriting existing values by default, which is relevant if one is calling the "create" method using the RepositoryBuilder to construct a more custom repository:

$repository = Dotenv\Repository\RepositoryBuilder::createWithNoAdapters()
    ->addAdapter(Dotenv\Repository\Adapter\EnvConstAdapter::class)
    ->addWriter(Dotenv\Repository\Adapter\PutenvAdapter::class)
    ->immutable()
    ->make();

$dotenv = Dotenv\Dotenv::create($repository, __DIR__);
$dotenv->load();

The above example will write loaded values to $_ENV and putenv, but when interpolating environment variables, we'll only read from $_ENV. Moreover, it will never replace any variables already set before loading the file.

By means of another example, one can also specify a set of variables to be allow listed. That is, only the variables in the allow list will be loaded:

$repository = Dotenv\Repository\RepositoryBuilder::createWithDefaultAdapters()
    ->allowList(['FOO', 'BAR'])
    ->make();

$dotenv = Dotenv\Dotenv::create($repository, __DIR__);
$dotenv->load();

Requiring Variables to be Set

PHP dotenv has built in validation functionality, including for enforcing the presence of an environment variable. This is particularly useful to let people know any explicit required variables that your app will not work without.

You can use a single string:

$dotenv->required('DATABASE_DSN');

Or an array of strings:

$dotenv->required(['DB_HOST', 'DB_NAME', 'DB_USER', 'DB_PASS']);

If any ENV vars are missing, Dotenv will throw a RuntimeException like this:

One or more environment variables failed assertions: DATABASE_DSN is missing

Empty Variables

Beyond simply requiring a variable to be set, you might also need to ensure the variable is not empty:

$dotenv->required('DATABASE_DSN')->notEmpty();

If the environment variable is empty, you'd get an Exception:

One or more environment variables failed assertions: DATABASE_DSN is empty

Integer Variables

You might also need to ensure that the variable is of an integer value. You may do the following:

$dotenv->required('FOO')->isInteger();

If the environment variable is not an integer, you'd get an Exception:

One or more environment variables failed assertions: FOO is not an integer.

One may only want to enforce validation rules when a variable is set. We support this too:

$dotenv->ifPresent('FOO')->isInteger();

Boolean Variables

You may need to ensure a variable is in the form of a boolean, accepting "true", "false", "On", "1", "Yes", "Off", "0" and "No". You may do the following:

$dotenv->required('FOO')->isBoolean();

If the environment variable is not a boolean, you'd get an Exception:

One or more environment variables failed assertions: FOO is not a boolean.

Similarly, one may write:

$dotenv->ifPresent('FOO')->isBoolean();

Allowed Values

It is also possible to define a set of values that your environment variable should be. This is especially useful in situations where only a handful of options or drivers are actually supported by your code:

$dotenv->required('SESSION_STORE')->allowedValues(['Filesystem', 'Memcached']);

If the environment variable wasn't in this list of allowed values, you'd get a similar Exception:

One or more environment variables failed assertions: SESSION_STORE is not an allowed value.

It is also possible to define a regex that your environment variable should be.

$dotenv->required('FOO')->allowedRegexValues('([[:lower:]]{3})');

Comments

You can comment your .env file using the # character. E.g.

# this is a comment
VAR="value" # comment
VAR=value # comment

Parsing Without Loading

Sometimes you just wanna parse the file and resolve the nested environment variables, by giving us a string, and have an array returned back to you. While this is already possible, it is a little fiddly, so we have provided a direct way to do this:

// ['FOO' => 'Bar', 'BAZ' => 'Hello Bar']
Dotenv\Dotenv::parse("FOO=Bar\nBAZ=\"Hello \${FOO}\"");

This is exactly the same as:

Dotenv\Dotenv::createArrayBacked(__DIR__)->load();

only, instead of providing the directory to find the file, you have directly provided the file contents.

Usage Notes

When a new developer clones your codebase, they will have an additional one-time step to manually copy the .env.example file to .env and fill-in their own values (or get any sensitive values from a project co-worker).

Troubleshooting

In certain server setups (most commonly found in shared hosting), PHP might deactivate superglobals like $_ENV or $_SERVER. If these variables are not set, review the variables_order in the php.ini file. See php.net/manual/en/ini.core.php#ini.variables-order.

Security

If you discover a security vulnerability within this package, please send an email to [email protected]. All security vulnerabilities will be promptly addressed. You may view our full security policy here.

License

PHP dotenv is licensed under The BSD 3-Clause License.

For Enterprise

Available as part of the Tidelift Subscription

The maintainers of vlucas/phpdotenv and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source dependencies you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use. Learn more.

phpdotenv's People

Contributors

aaemnnosttv avatar andreybolonin avatar carusogabriel avatar chapeupreto avatar danmichaelo avatar gabemedrash avatar grahamcampbell avatar jpuck avatar jrchamp avatar korbeil avatar localheinz avatar louim avatar lucasmichot avatar markwalet avatar mgparisi avatar mortenhauberg avatar pda avatar pfrenssen avatar piotr-cz avatar sergeax avatar shuber avatar slaffik avatar stanlemon avatar sunspikes avatar swalkinshaw avatar thedavidmeister avatar ultrabenosaurus avatar vinkla avatar vlucas avatar xjchengo avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

phpdotenv's Issues

Does not support Chinese characters ?

I use Laravel5 framework to develop
then in .env has

APP_NAME="中文"

and in config/app.php has

'app_name'=>env('APP_NAME', 'app_name')

run the code

$name = config('app.app_name');
dd($name);

print

app_name

Special characters in variables?

Somewhere between 1.0.6 and 1.0.8, special characters in my dotenv broke.

In my staging environment, my DB password includes a special character ($). (It's a randomly-generated password, and my host requires non-alphanumeric characters in DB passwords.) Using 1.0.6, this was fine; but after upgrading to 1.0.8, WordPress couldn't connect to the database.

Manually entering the password into wp-config (thereby bypassing Dotenv) worked.

Downgrading back to 1.0.6 did the trick for now.

Is there some way to ensure that an envvar is a string, and nothing more? (Single-quotes around the password didn't do the trick.)

Happy to help debug, but I'm not sure where to start!

Changing process environment unsafe on multithreaded servers

When using Dotenv on a multithreaded webserver, such as through Apache on Windows with the winnt mpm or on Linux/Unix with an event or worker mpm, using putenv and getenv is actually unsafe.

This is because:

  1. The environment is per process. This means that two instances of PHP will share the same environment in a multithreaded server, rather than each using a unique one.
  2. The functions putenv() and getenv() are not required to be re-entrant or thread safe. What this means is that if two threads happen to call them at the same time (either on different cores, or from a context switch in the middle of the function), bad things can happen.
  3. putenv() (in C) takes a pointer and references the memory, rather than copying it (depending on implementation; on a Mac it does make a copy iirc, even though this violates the spec.) PHP keeps this around in a hash table, which is destroyed at the end of the request. This may cause the environment to be cleared while another thread is running and using it.

See laravel/framework#8187 for a deeper description of the effects of these problems.

The only real benefit of modifying the environment using putenv() is that forked child processes will inherit the environment. For the most part, modifying $_ENV would be enough (however, using getenv() would no longer be enough in that case.)

Unable to nest variables

We are trying to set up our CI for a laravel project, we use drone as our CI tool. We are running into an issue with the .env file where when we try to add the build number for the database we are using, it does not interpolate the string with the build number.

APP_ENV=test
APP_DEBUG=true
APP_KEY=SomeRandomString

DB_HOST=server
DB_DATABASE="BUILD_${DRONE_BUILD_NUMBER}"
DB_USERNAME=user
DB_PASSWORD=password

CACHE_DRIVER=file
SESSION_DRIVER=file
QUEUE_DRIVER=sync

MAIL_DRIVER=smtp
MAIL_HOST=mailtrap.io
MAIL_PORT=2525
MAIL_USERNAME=null
MAIL_PASSWORD=null

The issue is here: DB_DATABASE="BUILD_${DRONE_BUILD_NUMBER}". We are running our laravel 5 app inside docker on a drone environment, anybody run into this before?

Do not throw and exception if .env file is missing

I think it would be a good idea to change the Dotenv::load method so that it wouldn't throw an exception. The motivation for this is that not all environments use a .env file, for example when we deploy to Amazon we configure the environmental variables through OpsWorks. What this means in practice is that I need an additional check in application to see if the file actually exists before calling Dotenv::load. What do you think?

$_ENV empty but $_SERVER and getenv() working

Hi, I recently ran into this problem where the $_ENV array isn't filled when trying to exec() another script. For example:

index.php contents:

<?php

# Get the server's env vars
require 'vendor/autoload.php';
$dotenv = new Dotenv\Dotenv('/etc/myconfigdir');
$dotenv->load();

var_dump($_ENV); // Correctly outputs a full array
var_dump($_SERVER); // Correctly outputs a full array

$result = exec('/usr/bin/php ' . dirname(__DIR__) . '/test.php');

test.php contents:

<?php

# Get the server's env vars
require 'vendor/autoload.php';
$dotenv = new Dotenv\Dotenv('/etc/myconfigdir');
$dotenv->load();

var_dump($_ENV); // EMPTY!?
var_dump($_SERVER); // Correctly outputs a full array

I'm assuming this has something to do with the exec'd PHP script not being run from a valid shell? Is this normal?

Overriding Apache env variables

So some time ago I had a problem where a certain environment variable was configured in Apache's <VirtualHost> block, and phpdotenv wasn't overwriting that value with what was configured in the .env file.

I use getenv() calls in my config files instead of $_ENV to simplify handling non-configured values - otherwise I'd have to do something like array_key_exists($_ENV, 'key') or something, which is too verbose with no benefit.

The problem with that is, when you have, for example SetEnv APP_ENV production in Apache's <VirtualHost> block, then the code

putenv('APP_ENV=staging');
echo getenv('APP_ENV');

will output production.

To successfully override this, PHP's apache_setenv function must be called instead, like this:

if (function_exists('apache_setenv'))
{
    apache_setenv('APP_ENV', 'staging');
}

The function_exists() check must be present so as not to cause errors when the user is not running Apache.

Now of course, this depends on a higher-level decision of whether an Apache-configured environment variable should take precedence over the one specified in a project's .env file - and to me it's kind of obvious that it shouldn't, since an .env file is a more granular configuration method, and as such, it should take precedence, but of course I may be wrong about that.

Do you think this could/should be included in phpdotenv?


Also, as an unrelated question (and sorry for hijacking this issue, I just want to avoid spamming issues), is there any reason why you chose to use this specific syntax for .env files, other than being similar to Ruby's dotenv syntax? Just plain requiring PHP files (as e.g. Laravel < 5 does) seems to be a much more straightforward approach, which avoids the various issues related to actually parsing the .env files, including comments etc. and additionally simplifies generating them, as you can simply var_export() an array and be done with it - with the current syntax, it doesn't seem to be as trivial, as one must be careful to correctly escape stuff since the syntax isn't really documented completely (e.g. there's nothing in the docs to explain what to do if I want the literal {$BASE_DIR}/tmp as a variable value, without resolving {$BASE_DIR} to something else). I'm interested in whether you feel there is any advantage to the current approach over simply doing $variables = require '/path/to/project/.env.php'; - thanks in advance for your thoughts on this, and sorry for the longish-double-issue.

Thanks for your work, cheers!

PSR-4 Compliance?

One nice-to-have would be a PSR-4 namespace so that it does not conflict with any hypothetical Dotenv class from some other project. The "fix" (such as it is) would be to put the Dotenv class in a namespace, such as vlucas\ or something like that.

Option to silently ignore missing env config

I'd love an option to ignore missing environment config.

Let me explain the use case.

  1. I usually keep .env out of application directory (e.g. one level higher than application code that is installed as a package or checked out from the repository) because I think it's easier to maintain the application this way: I can safely lose the directory with all the code (accidentally or not) and nothing breaks as long as it gets to the same state after installing a package or cloning a repository.
  2. This kind of environment configuration (.env) is quite useful in production and development environments but barely in test environment where the application is not always supposed to actually run and the environment is not provisioned, so there's basically nobody to write that .env (conceptually), so I usually make CI server set real environment variables while running tests rather than make it write .env and put it where the application usually looks for it.

Well, looks like a lot of typing for a really tiny feature that I envision as another optional argument for static load method. I would have created a PR by this time, but I doubt it makes a lot of sense until v2 (#44) is merged, so I'll probably revisit this tiket later or just kindly ask to add it to that massive set of v2 changes.

Feature request: makeMutable($variable)

Would be nice if we could make just a single ENV var mutable.

My use case would be to prefix a database name stored in ENV, because I don't want to override all my variables from .env I can't just makeMutable().

YAML loader

As I can see there are some new loaders, but YAML seems to be missing. I would be happy to contribute (using symfony/yaml as a suggested dependency) if you accept a PR for that.

Proposal

  • Create a 1.0 branch from the master, and set it as the default branch on github
  • Move the brightmachine-v2 branch to the master branch

That way, people can install v2 using ~2.0@dev as a version constraint.

Ability to clear an environment variable

It's nice to be able to set and get environment variables from .env when developing generally, but also nice to set and get specific environment variables when writing tests for functionality that behaves differently depending on config.

To write a test that sets an environment variable, then checks some "thing", then clears the environment variable, ready for the next test that just uses the Dotenv provided defaults, we have to do this in the first test as part of tearDown():

setenv('FOO');
unset($_ENV['FOO']);
unset($_SERVER['FOO']);

Not the end of the world, but maybe Dotenv could provide this method on the Loader as clearEnvironmentVariable (respecting the immutability-ability of it all).

Validation is impossible in 2.0 release without explicitly loading .env from disk

Previous version allowed to perform validation without having to load .env file from disk, which is very useful for production set-up, e.g. as discussed here:

// Load required environment variables from .env in development
$dotenv = new Dotenv\Dotenv();
if(BULLET_ENV == 'development') {
    $dotenv->load(dirname(__DIR__), 'dev.env');
}
// Required ENV vars for this app in production
$dotenv->required([
    'DATABASE_URL',
    'PATH_FILE_UPLOADS',
    'GOOGLE_PLACES_API_KEY',
    'RAVEN_DSN',
    'MANDRILL_USER', 'MANDRILL_PASS'
]);

However if you try to do the same with latest release (directory should now be specified in Dotenv constructor rather than loadmethod, but this is minor), PHP will throw an exception because it tries to initialize Validator by passing in loader which is null. That practically makes it impossible to use validation in production.. why was it done? How can I do validation without loading .env?

PHP Catchable fatal error:  Argument 2 passed to Dotenv\\Validator::__construct() must be an instance of Dotenv\\Loader, null given, called in /var/www/example.com/vendor/vlucas/phpdotenv/src/Dotenv.php on line 83 and defined in /var/www/example.com/vendor/vlucas/phpdotenv/src/Validator.php on line 34

`null` password

I'm using a DB_PASSWORD=null on a test server, and dotenv thinking that my password shouldn't be entered. Is there any way to provide it like a string "null"?

KEY=0 value is not "0"

Hi,

# .env config file

KEY=0 # ""
KEY="0" # "0"

The number zero 0 (not quoted) should assert to blank "", this is the bug or feature?

getenv() and _ENV/_SERVER not in sync

I'm trying to use a .env file together with a minimal Symfony project.

My problem is as follows:

  • Default production php.ini has variables_order = 'GPCS' (note: no E)
  • Default state of dotenv is immutable
  • Values from .env are retrievable using getenv() (combined with immutable flag this means dotenv does nothing)
  • Symfony does not use getenv() (looks at _ENV and _SERVER instead)
  • None of my variables are registered in _ENV and _SERVER though

What would be the best solution here?
Currently I just always set the state to mutable before calling load().

See also https://github.com/php/php-src/blob/master/php.ini-production#L166
and http://symfony.com/doc/current/cookbook/configuration/external_parameters.html#environment-variables

I know I can also change the ini setting, but I am not sure if that is a desirable approach.

Would it be acceptable for dotenv to sync any values from getenv() to _ENV/_SERVER if the former returns a value but the latter has no value for given key?

Question

I have a question, why do you populate the $_SERVER ? Is there a specific reason for this?

Nested Variables

It would be great to have nested variables so I can do something like

$_ENV[‘database’][‘connection_name’][‘username’]

in the .env file it could be something as simple as:

database.connection_name.username = johndoe

and then the package could read that into an array correctly when it loads the file.
Is that a possibility?

Not exploding by PHP_EOL

Here is an example of my .env file:

DB_NAME=example
DB_USER=root
DB_PASSWORD=
DB_HOST=

WP_ENV=development
WP_HOME=http://example.com
WP_SITEURL=http://example.com/wp

For some reason line 21 in Dotenv.php, $lines = explode(PHP_EOL, $fc);, doesn't explode the variables. If I replace PHP_EOL with "\n" it works just fine. Any ideas as to why this would be the case?

v2 Release Prep

First off -

Thanks everyone (especially @kelvinj) for all the hard work on v2 so far. I just updated the README file for it, as well as made some naming changes to the assertion methods to make them read better. Check the code and/or the README file to see what I mean.

My concerns before the release:
Now that we have alternate PHP and JSON loaders, I would like to change the variable nesting to match the bash-style syntax instead of the current PHP-style syntax. I would also like to remove support for spaced values that are not quoted.

The primary motivation for these changes is that I think if you use the bash-style syntax, there shouldn't be any features of phpdotenv that will break bash evaluation of the .env file.

For instance, pull down the latest v2 branch and run:

source tests/fixtures/env/nested.env && echo $NVAR4

Then run:

source tests/fixtures/env/nested.env && echo $NVAR3

And:

source tests/fixtures/env/commented.env

I also had to switch the example to double quotes instead of single quotes for the bash variable interpolation to work - the same thing that happens in PHP too. Perhaps we should also require double quotes? Is that going too far?

Make file loading optional

First time I use this, so first of all: thanks for the awesome library!

Secondly: I was thinking about if it is possible to make file loading optional. Let me explain with an example.

I am currently working on a few CLI tools where third party APIs are invlolved. In most cases the app needs an API key. To make this possible the user have a few possibilities to choose from:

  • Create a config.yaml in the working directory
  • Create a .config.yaml in the home directory
  • Pass a --key option along with the API key

In this case it is clear that only one of them is required.

Now let's change this to an environment variable based solution:

  • Create a .env file in the working directory
  • Add an API_KEY variable to your .bashrc, etc
  • Run the command with API_KEY variable included

But in this case the first one is required now, since Dotenv::load() (or $dotenv->load() in the new version) requires that file to be there.

Is there any solution to make it optional? Load it if exists. Since the check for required variables depends on ALL existing variable, not only the ones loaded from the file, this could be an easy change.

The obvious (but IMO ugly) solution would be to catch any thrown exception, if the file is not found.

What do you think?

Allows opening of remote files (in >=5.0.0) for configuration

Not sure if this was intended, but the methods currently being used to grab the file data (file_get_contents/file_exists) can be used with URL wrappers if enabled. This could allow for the loading of a remote file as the configuration.

This opens up the potential for an attacker to override settings with their own if they can get a value into the path of the file to load. If this isn't the intended behavior, an is_file check can ensure it's a local file.

1.08 breaks empty env vars

1.06 supported the use of empty string env vars. For example:

DB_USER=root
DB_PASSWORD=

This is used on development platforms that don't have any password for the root user.

1.08 gives this error: Fatal error: Uncaught exception 'RuntimeException' with message 'Required environment variable missing, empty, or value not allowed: 'DB_PASSWORD''

This seems like a major change that breaks the API. I did not expect this going from 1.06 to 1.08

[Proposal] add a lexical analyzer

When I add feature that variable resolve can be escaped, I found current shell analyzer is too simple and inconsistent with real shell. Maybe we can add a shell lexical analyzer into it.

Certain variables not being loaded

For some reason when Laravel calls Dotenv::load(), the skip on the following line is being called for just four of my .env variables: DB_HOST, DB_USERNAME, DB_PASSWORD, DB_NAME

This is the skip stopping the variable being loaded into $_ENV
https://github.com/vlucas/phpdotenv/blob/1.1/src/Dotenv.php#L83

After calling the load method, if I call print_r( $_ENV ) these four values aren't present.

This only happens intermittently, for most requests there is no issue.

The host contains dots and the password contains a quote (not at the beginning or end), I doubt this is causing the issue but I thought I'd mention it.

BEFORE calling load, I can get these values using getenv() even though they aren't present in $_ENV or $_SERVER.

I'm using PHP 5.6.8 on windows through XAMPP 3.2.1

one question about security

how is .env protected from being loaded from the web? Does every webserver hide those files? I am only sure about apache.

Instance methods?

Another nice-to-have would be instance methods instead of, or in addition to, static methods. Some of us start twitching when we see :: paired with $ or ().

Sudden breaking change between 1.0.8 and 1.0.9 with the {$FOO} syntax for nested variables

In 1.0.8, one would specify nested variables as ${FOO}, but in 1.0.9, it is specified as {$FOO}.

Relevant diff: v1.0.8...v1.0.9#diff-9fc34dc20f14743cc88df0c70b48555cL187

This breaks existing set-ups using the ${FOO} style syntax. I have two questions:

  1. Why use {$FOO} syntax? It is confusing imo to use something so different from how environment variables are specified in bash (without and with curly braces in order to protect it from other characters)
  2. Is this library using semantic versioning? I'd like to know what kind of version constraint to put in my composer.json

Composer issue on installation

Got this issues:

  • Installing vlucas/phpdotenv (dev-master d33518e)
    Loading from cache
    Failed to download vlucas/phpdotenv from dist: RecursiveDirectoryIterator::__construct(..
    nnot find the path specified. (code: 3)
    Now trying to download from source
  • Installing vlucas/phpdotenv (dev-master d33518e)
    Cloning d33518e

Optional exception on non-existent file

Would you be open to make the InvalidArgumentException exception thrown in the load method optional? Perhaps by a third parameter that defaults to true? The reason for this is that in many of my environments I want to use this supplementally, so that if the file doesn't exist it just moves on. The call I want to legitimately fail is the required() call so I've thus been wrapping this in a try-catch, but it'd be nice if I had the option to not raise the exception in the first place.

phpdotenv v2

Hi @vlucas

I know you've talked about v2, and moving towards a non-static, psr compliant interface.

Have you started yet? Happy to contribute or get it kick-started.

Update .env from php

Is there any way to actually update the .env file from PHP? I would use this to automatically update passwords from a cronjob.

Dotenv::required should check for empty values

Using a .env.example listing all the variables that need to be specified will mean that using ::required to check a variable is set will not catch missing variables as it doesn't check if they are empty as well as undefined.

I think ::required should also check if the value is empty.

Laravel 5 problem

I'm sure you are aware but it looks like your repo will be included Laravel 5. However, something in your code or how taylor configured it, but as background

Ran into a problem installing the latest Laravel 5 dev.

Kept getting a "Writing lock file Generating autoload files Script php artisan clear-compiled handling the post-update-cmd event returned with an error"

The result is it would not generate compiled.php. php artisan would not run - just kept returning back to the prompt with no message.

With much troubleshooting it seems that the .env.example causes problems. Renaming it did not work for me. Had to delete. Then create .env and copy the content from .env.example into the newly created file. Once saved everything worked again.

btw, great job on phpdotenv - starting to use it.

Nolan

[Proposal] make nested variables can be escaped

Now in phpdotenv v2, if i use a nonexistent variable in nesting, the variable will not be resolved. This behavior is kind of strange because if i source the file, the nested variable will be resolved as a empty value.

TEST="${NONEXIST}variable" 

If I source above file, TEST will be variable. But if i load above file using phpdotenv, $_ENV['TEST'] will be ${NONEXIST}variable.

EXIST="existent"
TEST="\${EXIST}variable" 

If I source above file, TEST will be ${EXIST}variable. But if i load above file, $_ENV['TEST'] will be \existentvariable.

So i think $ should be able to escaped by prefixing with backslash and if not escaped, nonexistent variable should be resolve as empty value.

If the feature is acceptable, I can send a pull request.

Detect and convert types

In my .env file I have values like:

APP_DEBUG=true
APP_DEV=false

But the type of these values is always string:

var_dump(getenv('APP_DEBUG')); // string(4) "true"
var_dump(getenv('APP_DEV')); // string(5) "false"

I think the values like true, false, null (or even numbers), without quotes, should be converted to the correct type (boolean, integers, etc), because in cases like this, APP_DEV returns "false" so it's evaluated as true:

if (getenv('APP_DEV')) {
    // do something
}

Using existing ENV vars in .env

I'd like to do this:

DATABASE_DSN=mysql:host=$DB_PORT_3306_TCP_ADDR;dbname=p4

Is there a way to reuse environment variables?

Create a smartLoad() method

With it, you will not need pass the .env directory, it'll transverse back directory until find the first .env (like the jQuery.closest() does). For instance:

/home/username/www/path/to/my/bootstrap.php <-- smartLoad() here
/home/username/.env

smartLoad() will transverse directories until find the first accessible .env file, or will fail.

/home/username/www/path/to/my/.env <-- fail
/home/username/www/path/to/.env <-- fail
/home/username/www/path/.env <-- fail
/home/username/www/.env <-- fail
/home/username/.env <-- found

Signature:

Dotenv::smartLoad(string $startDir = __DIR__, string $filename = ".env")
:: Can thrown InvalidArgumentException:
:: Dotenv: Environment file [filename] not found or not readable from [startDir]. 

It'll help a lot because you will not need specifiy two directories to local env and remote env, it'll load file smartly for you or thrown an exception if no .env is found.

Alternativaly, just turns load($path) optional. If you omit it, it'll transverse from caller path.

Tag a new release

You have made a few important changes since the last release, and it would be nice to have them here.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.