Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Updated plugin with documentation and examples

- Added installation information
- Added docs on proper usage of `Environment::configure()`
- Added docs on recommended practices regarding database switching
- Added sample environment bootstrap files
- Added Environment class
- Updated Environment class to always consider `CAKE_ENV` first
  • Loading branch information...
commit dd90f39fee4eaea21566b29159d7fc1b939089b9 1 parent de7e3d3
@josegonzalez authored
View
12 Config/bootstrap/environments.php
@@ -0,0 +1,12 @@
+<?php
+CakePlugin::load('Environments');
+
+App::uses('Environment', 'Environments.Lib');
+
+include dirname(__FILE__) . DS . 'environments' . DS . 'production.php';
+include dirname(__FILE__) . DS . 'environments' . DS . 'staging.php';
+include dirname(__FILE__) . DS . 'environments' . DS . 'development.php';
+
+// run
+
+Environment::start();
View
25 Config/bootstrap/environments/development.php
@@ -0,0 +1,25 @@
+<?php
+
+Environment::configure('development',
+ true, // Defaults to development
+ array(
+ 'Settings.FULL_BASE_URL' => 'http://example.dev',
+
+ 'Email.username' => 'email@example.com',
+ 'Email.password' => 'password',
+ 'Email.test' => 'email@example.com',
+ 'Email.from' => 'email@example.com',
+
+ 'logQueries' => true,
+
+ 'debug' => 2,
+ 'Cache.disable' => true,
+ 'Security.salt' => 'SALT',
+ 'Security.cipherSeed' => 'CIPHERSEED',
+ ),
+ function() {
+ if (!defined('FULL_BASE_URL')) {
+ define('FULL_BASE_URL', Configure::read('Settings.FULL_BASE_URL'));
+ }
+ }
+);
View
68 Config/environments.php.example → Config/bootstrap/environments/production.php
@@ -1,7 +1,4 @@
<?php
-App::uses('Environment', 'Lib');
-
-// config
Environment::configure('production',
array(
@@ -18,7 +15,7 @@
// Debug should be off in production
'debug' => 0,
-
+
// Securty
'Security.level' => 'medium',
'Security.salt' => 'SALT',
@@ -59,65 +56,4 @@ function() {
define('FULL_BASE_URL', Configure::read('Settings.FULL_BASE_URL'));
}
}
-);
-
-Environment::configure('staging',
- array(
- 'server' => array('staging.example.com')
- ),
- array(
- // Site specific items
- 'Settings.FULL_BASE_URL' => 'http://staging.example.com',
-
- 'Email.username' => 'email@example.com',
- 'Email.password' => 'password',
- 'Email.test' => 'email@example.com',
- 'Email.from' => 'email@example.com',
-
- 'logQueries' => true,
-
- // App Specific functions
- 'debug' => 0,
-
- // Securty
- 'Security.level' => 'medium',
- 'Security.salt' => 'SALT',
- 'Security.cipherSeed' => 'CIPHERSEED',
- ),
- function() {
- date_default_timezone_set('UTC');
-
- Cache::config('default', array('engine' => 'File'));
- if (!defined('FULL_BASE_URL')) {
- define('FULL_BASE_URL', Configure::read('Settings.FULL_BASE_URL'));
- }
- }
-);
-
-Environment::configure('development',
- true, // Defaults to development
- array(
- 'Settings.FULL_BASE_URL' => 'http://example.dev',
-
- 'Email.username' => 'email@example.com',
- 'Email.password' => 'password',
- 'Email.test' => 'email@example.com',
- 'Email.from' => 'email@example.com',
-
- 'logQueries' => true,
-
- 'debug' => 2,
- 'Cache.disable' => true,
- 'Security.salt' => 'SALT',
- 'Security.cipherSeed' => 'CIPHERSEED',
- ),
- function() {
- if (!defined('FULL_BASE_URL')) {
- define('FULL_BASE_URL', Configure::read('Settings.FULL_BASE_URL'));
- }
- }
-);
-
-// run
-
-Environment::start();
+);
View
34 Config/bootstrap/environments/staging.php
@@ -0,0 +1,34 @@
+<?php
+
+Environment::configure('staging',
+ array(
+ 'server' => array('staging.example.com')
+ ),
+ array(
+ // Site specific items
+ 'Settings.FULL_BASE_URL' => 'http://staging.example.com',
+
+ 'Email.username' => 'email@example.com',
+ 'Email.password' => 'password',
+ 'Email.test' => 'email@example.com',
+ 'Email.from' => 'email@example.com',
+
+ 'logQueries' => true,
+
+ // App Specific functions
+ 'debug' => 0,
+
+ // Securty
+ 'Security.level' => 'medium',
+ 'Security.salt' => 'SALT',
+ 'Security.cipherSeed' => 'CIPHERSEED',
+ ),
+ function() {
+ date_default_timezone_set('UTC');
+
+ Cache::config('default', array('engine' => 'File'));
+ if (!defined('FULL_BASE_URL')) {
+ define('FULL_BASE_URL', Configure::read('Settings.FULL_BASE_URL'));
+ }
+ }
+);
View
129 Lib/Environment.php
@@ -0,0 +1,129 @@
+<?php
+/**
+ * Singleton class to handle environment specific configurations.
+ *
+ * Auto-detect environment based on specific configured params and
+ * allow per environment configuration and environment emulation.
+ *
+ * Environment. Smart Environment Handling.
+ * Copyright 2008 Rafael Bandeira - rafaelbandeira3
+ *
+ * Licensed under The MIT License
+ * Redistributions of files must retain the above copyright notice.
+ */
+class Environment {
+
+ public $environments = array();
+
+ protected $_configMap = array(
+ 'security' => 'Security.level'
+ );
+
+ protected $_paramMap = array(
+ 'server' => 'SERVER_NAME'
+ );
+
+ static function &getInstance() {
+ static $instance = array();
+ if (!isset($instance[0])) {
+ $Environment = 'Environment';
+ if (config('app_environment')) {
+ $Environment = 'App' . $Environment;
+ }
+ $instance[0] = new $Environment();
+ Configure::write('Environment.initialized', true);
+ }
+ return $instance[0];
+ }
+
+ static function configure($name, $params, $config = null, $callable = null) {
+ $_this = Environment::getInstance();
+ $_this->environments[$name] = compact('name', 'params', 'config', 'callable');
+ }
+
+ static function start($environment = null) {
+ $_this =& Environment::getInstance();
+ $_this->setup($environment);
+ }
+
+ static function is($environment) {
+ $_this =& Environment::getInstance();
+ return ($_this->name === $environment);
+ }
+
+ public function __construct() {
+ if (Configure::read('Environment.initialized')) {
+ throw new Exception('Environment can only be initialized once');
+ return false;
+ }
+ }
+
+ public function setup($environment = null) {
+ if (Configure::read('Environment.setup')) {
+ return;
+ }
+
+ $current = ($environment === null) ? 'development' : $environment;
+ if (empty($environment)) {
+ foreach ($this->environments as $name => $config) {
+ if ($this->_envMatch($name) || $this->_match($name, $config['params'])) {
+ $current = $name;
+ break;
+ }
+ }
+ }
+
+ $config = array_merge(
+ $this->environments[$current]['config'],
+ array('Environment.name' => $current)
+ );
+ foreach ($config as $param => $value) {
+ if (isset($this->_configMap[$param])) {
+ $param = $this->_configMap[$param];
+ }
+ Configure::write($param, $value);
+ }
+
+ if (is_callable($this->environments[$current]['callable'])) {
+ $this->environments[$current]['callable']();
+ }
+
+ if (Configure::read('debug') > 0) {
+ App::uses('CakeLog', 'Log');
+ if (class_exists('CakeLog')) {
+ CakeLog::write(LOG_INFO, $current);
+ Configure::write('Environment.setup', true);
+ }
+ }
+ }
+
+ protected function _envMatch($environment) {
+ return (isset($_SERVER['CAKE_ENV']) && $_SERVER['CAKE_ENV'] == $environment);
+ }
+
+ protected function _match($environment, $params) {
+ if ($params === true) {
+ return true;
+ }
+
+ foreach ($params as $param => $value) {
+ if (isset($this->_paramMap[$param])) {
+ $param = $this->_paramMap[$param];
+ }
+
+ if (function_exists($param)) {
+ $match = call_user_func($param, $value);
+ } elseif (is_array($value)) {
+ $match = in_array(env($param), $value);
+ } else {
+ $match = (env($param) === $value);
+ }
+
+ if (!$match) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+}
View
177 README.md
@@ -1,4 +1,175 @@
-cakephp-environments
-====================
+# cakephp-environments
-CakePHP Environments Library as a plugin
+CakePHP Environments Library as a plugin
+
+## Requirements
+
+* CakePHP 2.x
+
+## Installation
+
+_[Manual]_
+
+* Download this: [https://github.com/OctoBear/cakephp-environments/zipball/master](https://github.com/OctoBear/cakephp-environments/zipball/master)
+* Unzip that download.
+* Copy the resulting folder to `app/Plugin`
+* Rename the folder you just copied to `Environments`
+
+_[GIT Submodule]_
+
+In your app directory type:
+
+ git submodule add git://github.com/OctoBear/cakephp-environments.git Plugin/Environments
+ git submodule init
+ git submodule update
+
+_[GIT Clone]_
+
+In your plugin directory type
+
+ git clone git://github.com/OctoBear/cakephp-environments.git Environments
+
+### Enable plugin
+
+Before using, you MUST enable the plugin:
+
+ CakePlugin::load('Environments');
+
+If you are already using `CakePlugin::loadAll();` before usage, then this is not necessary.
+
+## Usage
+
+Setup a directory structure as follows:
+
+ app/Config/bootstrap/environments.php
+ app/Config/bootstrap/environments/production.php
+ app/Config/bootstrap/environments/staging.php
+ app/Config/bootstrap/environments/development.php
+
+We specify multiple **environment** files to separate the various configurations and make it easy to inspect a given environment. This is not necessary, but useful if you are configuring a large amount of information.
+
+Your `environments.php` should contain the following:
+
+ <?php
+ CakePlugin::load('Environments');
+ App::uses('Environment', 'Environments.Lib');
+
+ include dirname(__FILE__) . DS . 'environments' . DS . 'production.php';
+ include dirname(__FILE__) . DS . 'environments' . DS . 'staging.php';
+ include dirname(__FILE__) . DS . 'environments' . DS . 'development.php';
+
+ Environment::start();
+
+This will:
+
+- Load the environments plugin in cases where it may not already be loaded
+- Include every environment, in order of specificity (development is usually last)
+- Start the environment
+
+### Environment Configuration
+
+Each environment may be configured as follows:
+
+ Environment::configure($name, $params, $config = null, $callable = null);
+
+Example usage of the `Environment::configure()` call is available in the `Config/bootstrap/environments` folder of this plugin.
+
+- `$name`: Usually something like `production` or `development`. Good practice is to name it the same as the file it was in, so that there isn't any confusion as to what a given env file contains
+- `$params`: An array or boolean of environment variables used to check whether this environment applies. If a boolean and set to true, this environment is automatically initiated. A value of `true` should only be used for development:
+
+ # If a previous environment is not enabled, this one will be set
+ Environment::configure('development', true, array('debug' => true));
+
+ If an array, the **keys** may be function names that are called, with the **values** being passed to it:
+
+ Environment::configure('development', true, array(
+ 'some_function' => 'aValueForThisCheck',
+ 'another_function' => 'aDifferentValueForThisCheck',
+ ));
+
+ In all other cases, we simply check the environment:
+
+ Environment::configure('octo_development', true, array(
+ 'SERVER_NAME' => 'octo-example.dev',
+ ));
+
+ Environment::configure('bear_development', true, array(
+ 'SERVER_NAME' => 'bear-example.dev',
+ ));
+
+ Environment::configure('development', true, array(
+ 'CAKE_ENV' => 'development',
+ ));
+
+ If we are running in CLI, the only check enforced is `CAKE_ENV`, and the value MUST be the name of the environment:
+
+ CAKE_ENV=production Console/cake bake all
+
+ If the `CAKE_ENV` environment variable is set at all, it takes precedence over everything, including a boolean value for `$params`.
+- `$config`: If set, an array of `keys` => `values` that are set via `Configure::write()`. Useful for batch-setting api keys, database connection information, etc.
+- `$callable`: A PHP callable, such as `array('ClassName', 'functionName')`. In PHP53+, it is also possible to use an anonymous function. This is the preferred method of setting information that might depend upon the value of some function call.
+
+### Database Switching
+
+You may wish to set database connection information based upon the current environment. The following is the preferred method:
+
+ <?php
+ class DATABASE_CONFIG {
+
+ public $default;
+
+ public function __construct() {
+ $this->default = array(
+ 'datasource' => 'Database/Mysql',
+ 'persistent' => false,
+ 'host' => $this->read('MYSQL_DB_HOST'),
+ 'login' => $this->read('MYSQL_USERNAME'),
+ 'password' => $this->read('MYSQL_PASSWORD'),
+ 'database' => $this->read('MYSQL_DB_NAME'),
+ 'prefix' => $this->read('MYSQL_PREFIX'),
+ 'encoding' => 'utf8',
+ );
+ }
+
+ public function read($key, $default = null) {
+ $value = env($key);
+ if ($value !== null) {
+ return $value;
+ }
+
+ $value = Configure::read($key);
+ if ($value !== null) {
+ return $value;
+ }
+
+ return $default;
+ }
+ }
+
+This way, the only place necessary to view connection information is in your configured environment. It is also possible to set the connection information via a `CLI` wrapper, `nginx` or `apache` configuration, or even in your cloud provider's env settings, such as Heroku or PHPFog.
+
+## Todo
+
+* Unit Tests
+
+## License
+
+Copyright (c) 2010-2012 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.
Please sign in to comment.
Something went wrong with that request. Please try again.