GithubHelp home page GithubHelp logo

php-dotenv's Introduction

Build Status Coverage Status Total Downloads Latest Stable Version

PHP Dotenv

A .env file parsing and loading library for PHP.

Requirements

  • PHP 5.5+

Installation

[Using Composer]

Run composer require josegonzalez/dotenv:

Or add the plugin to your project's composer.json - something like this:

  {
    "require": {
      "josegonzalez/dotenv": "3.3.0"
    }
  }

Usage

Create a new loader:

<?php
$Loader = new josegonzalez\Dotenv\Loader('path/to/.env');
// Parse the .env file
$Loader->parse();
// Send the parsed .env file to the $_ENV variable
$Loader->toEnv();
?>

Most methods return the loader directly, so the following is also possible:

<?php
$Loader = (new josegonzalez\Dotenv\Loader('path/to/.env'))
              ->parse()
              ->toEnv(); // Throws LogicException if ->parse() is not called first
?>

You can use a .env file with any of the following features:

# comments are allowed
FOO=bar # you can also have comments on the end of a line
export BAR=baz # you can optionally begin with an `export` statement

# both single and double quotes are allowed
BAZ='qux'
QUX="quux"

# as are escaped quotes or similar:
QUUX="corge \" grault"
CORGE='garply" waldo'

# unquoted values containing [null, true, false] are turned into
# their PHP equivalents
PHP_NULL=null
PHP_TRUE=true
PHP_FALSE=false

# when quoted, they are simply string values
STRING_NULL="null"
STRING_TRUE="true"
STRING_FALSE="false"

# spaces are allowed as well
# in a slightly more relaxed form from bash
 GRAULT =fred
GARPLY = plugh
SPACES=" quote values with spaces" # will contain preceding space

# When using newlines, you should use quoted values
QUOTED_NEWLINE="newline\\nchar"

# you can even have nested variables using `${VAR}` syntax
# remember to define the nested var *before* using it
WALDO=${xyzzy} # not yet defined, so will result in WALDO = `{}`
THUD=${GARPLY} # will be defined as `plugh`

# note that variables beginning with a character
# other than [a-zA-Z_] shall throw a ParseException
01SKIPPED=skipped

# However, numbers *are* allowed elsewhere in the key
NOT_SKIPPED1=not skipped # will have the value `not`

Example .env files are available in the fixtures directory.

Defining Constants

You can also define constants automatically from your env file:

<?php
$Loader = (new josegonzalez\Dotenv\Loader('path/to/.env'))
              ->parse()
              ->define(); // Throws LogicException if ->parse() is not called first
?>

Already defined constants will result in an immediate LogicException.

Adding to $_ENV

<?php
$overwriteENV = true;
$Loader = (new josegonzalez\Dotenv\Loader('path/to/.env'))
              ->parse()
              ->toEnv($overwriteENV); // Throws LogicException if ->parse() is not called first
?>

Already defined $_ENV entries will result in an immediate LogicException, unless $overwriteENV is set to true (default false).

Adding to $_SERVER

<?php
$overwriteSERVER = true;
$Loader = (new josegonzalez\Dotenv\Loader('path/to/.env'))
              ->parse()
              ->toServer($overwriteSERVER); // Throws LogicException if ->parse() is not called first
?>

Already defined $_SERVER entries will result in an immediate LogicException, unless $overwriteSERVER is set to true (default false).

Making available to apache_getenv()

This should be preferred over getenv when using the Apache web server with mod_php.

<?php
$overwrite = true;
$Loader = (new josegonzalez\Dotenv\Loader('path/to/.env'))
              ->parse()
              ->apacheSetenv($overwriteAPACHE); // Throws LogicException if ->parse() is not called first
                                                // May throw a PHP Error if either apache_setenv() or apache_putenv() are not available
?>

Already defined apache_getenv() entries will result in an immediate LogicException, unless $overwriteAPACHE is set to true (default false).

Making available to getenv()

<?php
$overwrite = true;
$Loader = (new josegonzalez\Dotenv\Loader('path/to/.env'))
              ->parse()
              ->putenv($overwriteENV); // Throws LogicException if ->parse() is not called first
?>

Already defined getenv() entries will result in an immediate LogicException, unless $overwriteENV is set to true (default false).

Setting key prefixes

<?php
$environment = (new josegonzalez\Dotenv\Loader('path/to/.env'))
              ->parse()
              ->prefix('FOO')
              ->toServer(); // BAR=baz becomes FOOBAR=baz
?>

Return as array

<?php
$environment = (new josegonzalez\Dotenv\Loader('path/to/.env'))
              ->parse()
              ->toArray(); // Throws LogicException if ->parse() is not called first
?>

Return as json

<?php
$jsonEnvironment = (string)((new josegonzalez\Dotenv\Loader('path/to/.env'))->parse());
?>

Require environment variables

<?php
$Loader = (new josegonzalez\Dotenv\Loader('path/to/.env'))
              ->parse()
              ->expect('FOO', 'BAR', 'BAZ'); // Throws RuntimeException if variables are missing
?>

Turning off exceptions

<?php
$Loader = (new josegonzalez\Dotenv\Loader('path/to/.env'))
              ->raiseExceptions(false)
              ->parse()
              ->expect('FOO', 'BAR', 'BAZ'); // Returns false if variables are missing
?>

Skip existing environment variables

It is possible to skip existing enviroment variables (e.g. in a containerized / Docker setup).

<?php
$Loader = (new josegonzalez\Dotenv\Loader('path/to/.env'))
              ->parse()
              ->skipExisting() //Skip any environment variables that are already present
              ->putenv();
?>

Filtering environments

It is possible to optionally filter the environment data produced by php-dotenv through the use of filter classes. A filter class has an __invoke method like so:

<?php
class LollipopFilter
{
    /**
     * Sets every key's value to the string `lollipop`
     *
     * @param array $environment Array of environment data
     * @param array $config Array of configuration data that includes the callable
     * @return array
     */
    public function __invoke(array $environment, array $config)
    {
        $newEnvironment = [];
        foreach ($environment as $key => $value) {
            $newEnvironment[$key] = 'lollipop';
        }
        return $newEnvironment;
    }
}
?>

You can attach filters using the setFilters() method, which will override all currently specified filters. If an invalid filter is specified, a LogicException will be thrown.

<?php
$Loader = (new josegonzalez\Dotenv\Loader('path/to/.env'))
              ->setFilters(['LollipopFilter']); // Takes an array of namespaced class names
?>

Note that you can optionally set configuration for your filters. These are passed to the __invoke method as the second argument.:

<?php
$Loader = (new josegonzalez\Dotenv\Loader('path/to/.env'))
              ->setFilters([
                'LollipopFilter' => ['paintshop'],
              ]); // Takes an array of namespaced class names
?>

Filters can also be callables functions, which is useful in one-off situations. They are wrapped by the special CallableFilter.

<?php
$Loader = (new josegonzalez\Dotenv\Loader('path/to/.env'))
              ->setFilters([function ($data) {
                return $data;
              }]);
?>

If you need special configuration for your callable filters, you can prefix your callable with __callable__N, where N is the integer index the callable is in your array. The callable itself should be contained in a callable config key, as follows:

<?php
$Loader = (new josegonzalez\Dotenv\Loader('path/to/.env'))
              ->setFilters([
                '__callable__0' => [
                  'callable' => function ($data, $config) {
                    return $data;
                  },
                  'someKey' => 'value',
                ]
              ]);
?>

Finally, to invoke a filter, you must call filter() after calling parse().

<?php
$Loader = (new josegonzalez\Dotenv\Loader('path/to/.env'))
              ->setFilters(['LollipopFilter'])
              ->parse()
              ->filter();
?>

Available Filters

The following filters are built into php-dotenv.

  • josegonzalez\Dotenv\Filter\CallableFilter: Wraps a callable and invokes it upon the environment.
  • josegonzalez\Dotenv\Filter\LowercaseKeyFilter: Lowercases all the keys for an environment to a single-depth.
  • josegonzalez\Dotenv\Filter\NullFilter: Returns the environment data without any changes.
  • josegonzalez\Dotenv\Filter\RemapKeysFilter: Remaps specific keys in a $config array to a set of values at a single-depth.
  • josegonzalez\Dotenv\Filter\UnderscoreArrayFilter: Expands a flat array to a nested array. For example, ['0_Foo_Bar' => 'Far'] becomes [['Foo' => ['Bar' => 'Far']]].
  • josegonzalez\Dotenv\Filter\UppercaseFirstKeyFilter: Uppercases the first letter for all the keys for an environment to a single-depth..
  • josegonzalez\Dotenv\Filter\UrlParseFilter: When there is a key with the suffix _URL, this filter uses parse_url to add extra data to the environment.

Static Environment Definition

You can also call it via the static load method call, which takes an array of arguments. If a method name is specified, the method is called with the value in the $options array being sent into the method.

<?php
josegonzalez\Dotenv\Loader::load(array(
  'filepath' => 'path/to/.env',
  'expect' => array('FOO', 'BAR', 'BAZ'),
  'toEnv' => true,
  'toServer' => true,
  'define' => true,
));
?>

Validating External Environments

In some cases it may be necessary to validate that a given array of environment data matches your requirements. You can use the Loader->expect() functionality via the standalone Expect class:

<?php
use josegonzalez\Dotenv\Expect;

$expect = new Expect($env);
$expect('FOO'); // Raises a RuntimeException if `env` is missing FOO

// You can turn off exception raising using the second `raise` argument
$expect = new Expect($env, false);
$expect('FOO'); // Returns false if `env` is missing FOO
?>

What is it and why should I use it?

When developing and deploying your applications you are typically interacting with various environments - production and development for instance. These environments both execute your code, but will do so using different credentials. You may also wish to distribute your application to developers without accidentally giving them access to important external services.

Simple examples include authentication keys to your email provider or database connection credentials. You would never want to accidentally send testing emails to all your users, or run a DROP TABLE statement against production because you ran your unit tests.

How do you tackle these differing credentials? The php-dotenv helps solve this issue by allowing you to configure your environments in a universal fashion, making it easy to safely switch between environments, as well as share those environments with multiple projects/languages.

Need more reasons? Check out the twelve-factor app docs on configuration.

Rules to follow

When using php-dotenv, you should strive to follow the following rules:

  • Add your .env file to a gitignore and use a .env.default or .env.example to set defaults for your projects. This allows your development team to override defaults in a method that works for their local environment.

  • Always set sane development defaults for any credential. If necessary, disable features when those credentials are "invalid".

  • Where necessary, add comments to credentials with information as to what they are, how they are used, and how one might procure new ones.

  • As php-dotenv uses more lax procedures for defining environment variables, ensure your .env files are compatible with your shell. A good way to test this is to run the following:

    # source in your .env file
    source .env
    # check the environment
    env
  • Avoid running php-dotenv in production settings, and instead set environment variables in your webserver, process manager, or in bash before running your commands. A simple way to ensure this is to check for the existence of a sentinel environment variable that is only set in production:

    // APP_NAME isn't set in staging/dev
    if (!env('APP_NAME')) {
        $loader = new josegonzalez\Dotenv\Loader([
            __DIR__ '/.env',
            __DIR__ '/.env.default'
        ]);
        $loader->parse()->toEnv();
    }

General Security Information

If you configure php-dotenv to output configuration in any of the ways listed above and then dump them, they may be available to undesired users. For instance, using a project like filp/whoops in conjunction with $Loader->toServer() can result in outputting sensitive data to your users if you leave whoops enabled in production.

For this reason, php-dotenv never populates data to an environment variable by default and requires that the developer make a conscious decision about how they want to use loaded environment variables

Many error reporting tools have the option of whitelisting or blacklisting sensitive data, and you should familiarize yourself with said tooling.

License

The MIT License (MIT)

Copyright (c) 2013 Jose Diaz-Gonzalez

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

php-dotenv's People

Contributors

ad7six avatar commercial-hippie avatar davidyell avatar fr3nch13 avatar jadb avatar jamesdb avatar jeremyharris avatar josegonzalez avatar mbrevda avatar nubs avatar optiman avatar stefanvangastel avatar tanakahisateru 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

php-dotenv's Issues

Not getting in getenv

<?php
$loader = new josegonzalez\Dotenv\Loader(__DIR__ . '/.env');
// Parse the .env file
$loader->parse();
// Send the parsed .env file to the $_ENV variable
$loader->toEnv(true);
$loader->toServer(true);
echo ' ffv ' . getenv('HELLO');
var_dump($_ENV);

Used php's local server itself.

Why is .git included in the source?

After installing via composer, when I navigate to vendor\josegonzalez\dotenv the .git folder is present.

I cannot commit this folder to my own repo because this folder has its own repo.

Proposition from m1/env

Hey there,

Just saw your comment on reddit, I'm the author of m1/env

Well basically my proposition is basically what I say in my comment

My aim of building m1/env was that other .env libraries would then use my library for the parsing and their library could be used for the loading into superglobals and other stuff like that. Just wanted to do one thing and do it well. My inspiration behind this project was symfony/yaml

This will also mean less work for you to bring up to speed with my package, so therefore more time for you to spend on other features, also you won't have to worry about the parser as this will be my job.

If you would like to do this, would love to work with you. No worries if not.

Thanks,
Miles

Add a `filter` class

So that env vars can be filtered. You could register a filter and then the env vars would be run through that filter. For instance, the current type-casting can be moved to a filter.

One could also do something like move DATABASE_URL to ['database']['url'] in a filter, which could be useful in certain configuration contexts.

One thing I do in prod is turn anything with a _URL suffix into it's constituent scheme parts, so you get DATABASE_SCHEME, DATABASE_USERNAME, etc.

[Request] allow ->define() to accept a prefix

With this, I would have a .env file with:

FOO=bar

Then this:

$Loader = (new josegonzalez\Dotenv\Loader('path/to/.env'))
              ->parse()
              ->define('PREFIX');

would create the constant PREFIX_FOO instead of FOO. Statically, maybe this syntax:

josegonzalez\Dotenv\Loader::load(array(
  'filepath' => 'path/to/.env',
  'expect' => array('FOO', 'BAR', 'BAZ'),
  'define' => true,
  'define_prefix' => 'PREFIX',
);

Spaces between =

When .env files have a space between = things are missed.

HELLO = jello

When you keep without spaces $_ENV will get the values.

Stable Release?

Hey there -- I'd like to start moving Radar to a stable release, but good practice suggests that Radar can't be stable until its dependencies are. Since we use php-dotenv, what are the chances of php-dotenv going stable in near future?

NOT EVEN ONE EXAMPLE

Now I know why this is not popular because you don't even have one example on how to call the variables like just one to **RETRIEVE a VALUE ** from the damn .env file !!!
are we using getenv() or env()
I'm a beginner and there's no shame in that I can't use your library what so ever and it's so obvious why there's not even one stackoverflow issue with your library

Load Variables from array instead of .env file

I am wondering if it is possible to load a list of key value pairs from an array instead of a file. To explain why I want to do this, i'll explain my use case (basicly caching the config to enable opcache performance gains):

First Request:

  • Load/parse .env file normally
  • (IF environment = production): Extract config as array (with toArray()) and store it as php file with var_export
  • Populate $_ENV, $_SERVER, ...

Next Request:

  • The .env file isn't parsed because the php-cache file with the array is required instead.
  • A DotEnv Loader is created and filled with the variables from the cache file.
  • Populate $_ENV, $_SERVER, ...

-> In both cases i could proceeed the same way, no matter where the variables came from (checking Expections, put them to $_ENV etc.).

Currently I haven't found a way to load the variables from an array to work with them the same way as I do with the .env-loaded variables.

A 5x branch?

Looks like your requirements went up to PHP 7.0. Not sure why that would be the minimum required version for your plugin, but it seemed to work just fine for 5.x versions?

Regardless, if you're going to continue developing with a 7.0 requirement, can you please also provide a 5.x branch for those of us who want it?

Allow source .env.default in .env files

It would be good if source .env.default could either be ignored when parsing, or used to include the definitions from that file as well.

It would make it possible to just source .env and get the default environment plus any overrides or additions.

Why is ext-ftp extension required ?

is there any reason PHP extension ext-ftp has to be enabled ?

> composer require vlucas/phpdotenv
Using version ^3.6 for vlucas/phpdotenv
./composer.json has been updated
Loading composer repositories with package information
Updating dependencies (including require-dev)
Your requirements could not be resolved to an installable set of packages.

  Problem 1
    - The requested PHP extension ext-ftp * is missing from your system. Install or enable PHP's ftp extension.


Installation failed, reverting ./composer.json to its original content.

Comments aligned with tabs are treated as extensions of a string

If you configure your file like this:

MAINTENANCE_MODE 				= false 					# Is in maintenance mode?

instead of

MAINTENANCE_MODE 				= false # Is in maintenance mode?

the first one when dumped will actually be a string of "false # Is in maintenance mode?" which boolean implicitly evals as true because it's indented (to align with other line's comments) using tabs. Changing it to a space causes it to be corrected evaluated as bool false.

This is sort of unexpected, and it'd be nice if you could indent comments using tabs since it makes longer config files a lot easier to read.

Loader:load() fails if passed a path instead of a file

This works:

$loader = (new josegonzalez\Dotenv\Loader('/path/to/.env'))
    ->parse()
    ->toArray();

This fails silently (returns an empty array):

$loader = (new josegonzalez\Dotenv\Loader('/path/to/'))
    ->parse()
    ->toArray();

Make php-dontenv work with older php versions

This extension used to work for php 5.3+.
It would be nice if we could make it work with other php versions than php 7.0+.
This way we could integrate php-dontenv in other frameworks. e.g. testing-frameworks.

Parse a string containing .env content

I'd like the php-dotenv library to consume .env content as a string, rather than a file which is read from a path. Is there any way I'm not seeing to do this currently, or could that functionality be added?

rais doesn't respect raiseExceptions(false)

Parse throws errors for lots of FS related issues. Shouldn't these be silenceable by raiseExceptions(false)? I.e. if a .env file isn't found, let parse() fail gracefully and without making a fuss.

Don't use PHP_EOL as a limiter for explode

Nearly every editor (beside notepad) saves files with UNIX line endings (\r\n). As PHP_EOL defaults to \r\n on Windows, saving the file once in an editor of your choice means that splitting lines won't work.
Consider using preg_split instead:

$lines = preg_split('/\r\n|\r|\n/', $fc);

Untested, but should work.

expect after to... function

I want to load my databbase credential (for example) from env. and they are important so I put them in expect array. in development every thing is ok, since I have all of them inside my .env file but in production there is an env variable out there with the correct value.
I want to remove the line from my .env file, but I get exception on load. I think, the correct place for check that is after toEnv (in my case and toServer and other toMethods)
I mean after toEnv if there is no "expected" variable in $_ENV (or $_SERVER in toServer and ...) I should get an exception, not becuse I have none of them inside my .env file.

This is simple to implement but I want to know if you have anything else in mind?

Make file loading optional

Extracting the bits where we do expect could be interesting. Not sure how it would lookup what config there is (maybe a callable?).

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.