Skip to content

Commit

Permalink
Merge pull request #300 from GrahamCampbell/env-obj
Browse files Browse the repository at this point in the history
Refactored to use environment variables object
  • Loading branch information
GrahamCampbell committed Jan 2, 2019
2 parents dcf11a4 + 54cec64 commit 4f26ad7
Show file tree
Hide file tree
Showing 19 changed files with 889 additions and 196 deletions.
22 changes: 19 additions & 3 deletions README.md
Expand Up @@ -84,14 +84,14 @@ SECRET_KEY="abc123"
You can then load `.env` in your application with:

```php
$dotenv = new Dotenv\Dotenv(__DIR__);
$dotenv = Dotenv\Dotenv::create(__DIR__);
$dotenv->load();
```

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

```php
$dotenv = new Dotenv\Dotenv(__DIR__, 'myconfig');
$dotenv = Dotenv\Dotenv::create(__DIR__, 'myconfig');
$dotenv->load();
```

Expand Down Expand Up @@ -136,10 +136,26 @@ If you want Dotenv to overwrite existing environment variables, use `overload`
instead of `load`:

```php
$dotenv = new Dotenv\Dotenv(__DIR__);
$dotenv = Dotenv\Dotenv::create(__DIR__);
$dotenv->overload();
```

### Loader Customization

Need us to not set `$_ENV` but not `$_SERVER`, or have other custom requirements? No problem! Simply pass a custom implementation of `Dotenv\Environment\FactoryInterface` to `Dotenv\Loader` on construction. In practice, you may not even need a custom implementation, since our default implementation allows you provide an array of `Dotenv\Environment\Adapter\AdapterInterface` for proxing the underlying calls to.

For example, if you want us to only ever fiddle with `$_ENV` and `putenv`, then you can setup Dotenv as follows:

```php
$factory = new Dotenv\Environment\DotenvFactory([
new Dotenv\Environment\Adapter\EnvConstAdapter(),
new Dotenv\Environment\Adapter\PutenvAdapter(),
]);

$dotenv = Dotenv\Dotenv::create(__DIR__, null, $factory);
```


Requiring Variables to be Set
-----------------------------

Expand Down
3 changes: 2 additions & 1 deletion composer.json
Expand Up @@ -11,7 +11,8 @@
}
],
"require": {
"php": "^5.4 || ^7.0"
"php": "^5.4 || ^7.0",
"phpoption/phpoption": "^1.5"
},
"require-dev": {
"phpunit/phpunit": "^4.8.35 || ^5.0 || ^6.0"
Expand Down
86 changes: 53 additions & 33 deletions src/Dotenv.php
Expand Up @@ -2,6 +2,8 @@

namespace Dotenv;

use Dotenv\Environment\DotenvFactory;
use Dotenv\Environment\FactoryInterface;
use Dotenv\Exception\InvalidPathException;

/**
Expand All @@ -13,36 +15,69 @@
class Dotenv
{
/**
* The file path.
* The loader instance.
*
* @var string
* @var \Dotenv\Loader
*/
protected $filePath;
protected $loader;

/**
* The loader instance.
* Create a new dotenv instance.
*
* @param \Dotenv\Loader $loader
*
* @var \Dotenv\Loader|null
* @return void
*/
protected $loader;
public function __construct(Loader $loader)
{
$this->loader = $loader;
}

/**
* Create a new dotenv instance.
*
* @param string $path
* @param string $file
* @param string $path
* @param string|null $file
* @param \Dotenv\Environment\FactoryInterface|null $envFactory
*
* @return void
* @return \Dotenv\Dotenv
*/
public static function create($path, $file = null, FactoryInterface $envFactory = null)
{
$loader = new Loader(
self::getFilePath($path, $file),
$envFactory ?: new DotenvFactory(),
true
);

return new Dotenv($loader);
}


/**
* Returns the full path to the file.
*
* @param string $path
* @param string|null $file
*
* @return string
*/
public function __construct($path, $file = '.env')
private static function getFilePath($path, $file)
{
$this->filePath = $this->getFilePath($path, $file);
$this->loader = new Loader($this->filePath, true);
if (!is_string($file)) {
$file = '.env';
}

$filePath = rtrim($path, DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR.$file;

return $filePath;
}

/**
* Load environment file in given directory.
*
* @throws \Dotenv\Exception\InvalidPathException|\Dotenv\Exception\InvalidFileException
*
* @return array
*/
public function load()
Expand All @@ -68,37 +103,22 @@ public function safeLoad()
/**
* Load environment file in given directory.
*
* @throws \Dotenv\Exception\InvalidPathException|\Dotenv\Exception\InvalidFileException
*
* @return array
*/
public function overload()
{
return $this->loadData(true);
}

/**
* Returns the full path to the file.
*
* @param string $path
* @param string $file
*
* @return string
*/
protected function getFilePath($path, $file)
{
if (!is_string($file)) {
$file = '.env';
}

$filePath = rtrim($path, DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR.$file;

return $filePath;
}

/**
* Actually load the data.
*
* @param bool $overload
*
* @throws \Dotenv\Exception\InvalidPathException|\Dotenv\Exception\InvalidFileException
*
* @return array
*/
protected function loadData($overload = false)
Expand All @@ -121,10 +141,10 @@ public function required($variable)
/**
* Get the list of environment variables declared inside the 'env' file.
*
* @return array
* @return string[]
*/
public function getEnvironmentVariableNames()
{
return $this->loader->variableNames;
return $this->loader->getEnvironmentVariableNames();
}
}
86 changes: 86 additions & 0 deletions src/Environment/AbstractVariables.php
@@ -0,0 +1,86 @@
<?php

namespace Dotenv\Environment;

use ArrayAccess;

/**
* This is the abstract variables implementation.
*
* Extend this as required, implementing "get", "set", and "clear".
*/
abstract class AbstractVariables implements VariablesInterface
{
/**
* Are we immutable?
*
* @var bool
*/
private $immutable;

/**
* Create a new environment variables instance.
*
* @param bool $immutable
*
* @return void
*/
public function __construct($immutable)
{
$this->immutable = $immutable;
}

/**
* Determine if the environment is immutable.
*
* @return bool
*/
public function isImmutable()
{
return $this->immutable;
}

/**
* Tells whether environment variable has been defined.
*
* @param string $name
*
* @return bool
*/
public function has($name)
{
return !is_null($this->get($name));
}

/**
* {@inheritdoc}
*/
public function offsetExists($offset)
{
return $this->has($offset);
}

/**
* {@inheritdoc}
*/
public function offsetGet($offset)
{
return $this->get($offset);
}

/**
* {@inheritdoc}
*/
public function offsetSet($offset, $value)
{
$this->set($offset, $value);
}

/**
* {@inheritdoc}
*/
public function offsetUnset($offset)
{
$this->clear($offset);
}
}
41 changes: 41 additions & 0 deletions src/Environment/Adapter/AdapterInterface.php
@@ -0,0 +1,41 @@
<?php

namespace Dotenv\Environment\Adapter;

interface AdapterInterface
{
/**
* Determines if the adapter is supported.
*
* @return bool
*/
public function isSupported();

/**
* Get an environment variable, if it exists.
*
* @param string $name
*
* @return \PhpOption\Option
*/
public function get($name);

/**
* Set an environment variable.
*
* @param string $name
* @param string|null $value
*
* @return void
*/
public function set($name, $value = null);

/**
* Clear an environment variable.
*
* @param string $name
*
* @return void
*/
public function clear($name);
}
64 changes: 64 additions & 0 deletions src/Environment/Adapter/ApacheAdapter.php
@@ -0,0 +1,64 @@
<?php

namespace Dotenv\Environment\Adapter;

use PhpOption\None;

class ApacheAdapter implements AdapterInterface
{
/**
* Determines if the adapter is supported.
*
* This happens if PHP is running as an Apache module.
*
* @return bool
*/
public function isSupported()
{
return function_exists('apache_getenv') && function_exists('apache_setenv');
}

/**
* Get an environment variable, if it exists.
*
* This is intentionally not implemented, since this adapter exists only as
* a means to overwrite existing apache environment variables.
*
* @param string $name
*
* @return \PhpOption\Option
*/
public function get($name)
{
return None::create();
}

/**
* Set an environment variable.
*
* Only if an existing apache variable exists do we overwrite it.
*
* @param string $name
* @param string|null $value
*
* @return void
*/
public function set($name, $value = null)
{
if (apache_getenv($name) !== false) {
apache_setenv($name, $value);
}
}

/**
* Clear an environment variable.
*
* @param string $name
*
* @return void
*/
public function clear($name)
{
// Nothing to do here.
}
}

0 comments on commit 4f26ad7

Please sign in to comment.