Skip to content

Commit

Permalink
* Initial push
Browse files Browse the repository at this point in the history
  • Loading branch information
Andrew Welch committed Feb 2, 2017
0 parents commit 0bfc0da
Show file tree
Hide file tree
Showing 9 changed files with 477 additions and 0 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
@@ -0,0 +1,7 @@
# Craft3-Multi-Environment Changelog

## 1.0.0 -- 2017.02.1

* Ported to Craft 3

Brought to you by [nystudio107](https://nystudio107.com/)
21 changes: 21 additions & 0 deletions LICENSE
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2017 nystudio107

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.
142 changes: 142 additions & 0 deletions README.md
@@ -0,0 +1,142 @@
# Craft3-Multi-Environment for Craft CMS 3.x

Efficient and flexible multi-environment config for Craft CMS

## Overview

[Multi-Environment Configs](https://craftcms.com/docs/multi-environment-configs) let you easily run a Craft CMS project in local dev, staging, and production. They allow different people to work in different environments without painful setup or coordination. You can read a more in-depth discussion of it in the M[ulti-Environment Config for Craft CMS](https://nystudio107.com/blog/multi-environment-config-for-craft-cms) article.

### Why another multi-environment config?

There are a number of good approaches to implementing a multi-environment config in Craft CMS, but they each have drawbacks. There are two main approaches typically used are:

1. [Multi-Environment Configs](https://craftcms.com/docs/multi-environment-configs) - The problem with this approach is that it often results in data stored in a git repo (such as passwords, Stripe keys, etc.) that really shouldn't be.
2. [PHP dotenv](https://github.com/vlucas/phpdotenv) - The problem with this approach is that PHP dotenv is fairly heavy, and indeed the authors warn against using it in production. Instantiating the Composer auto-loader and reading in the `.env` file for every request adds unnecessary overhead.

Craft-Multi-Environment (CME) is my attempt to create something that finds a middle-ground between the two approaches.

### How does it work?

CME works by including a `.env.php` file (which is never checked into git) via the Craft `index.php` file that is loaded for every non-static request.

The `.env.php` file sets some globally-accessible settings via `putenv()` for common things like the database password, database user, base URL, etc. You're also free to add your own as you see fit. The `config/general.php` and `config/db.php` can thus remain abstracted, and each environment can have their own local settings.

This is more performant than auto-loading a class and reading a `.env` file for each request, but maintains the same flexibility. Additionally, since we are using `getenv()` to access the settings, these can be set directly by the webserver (without using the `.env.php` file at all) for additional security and performance.

Also, since we're using `getenv()`, these settings are globally accessible in the PHP session, and can for instance be used in a Craft Commerce `commerce.php` file, accessed via plugins, etc.

## Using Craft-Multi-Environment

### Assumptions

CME assumes that you have a folder structure such as this for your project root:

.env.php
config/
storage/
templates/
web/
index.php
craft

If your folder structure is different, that's fine. But you may need to adjust the path to `.env.php` in the `index.php` file, and you may need to adjust the way `CRAFTENV_BASE_PATH` is constructed in your `.env.php` (or just hardcode the path).

CME will also work fine with localized sites as well, you'll just need to adjust the aforementioned paths as appropriate.

### Setting it up

1. Copy `config/general.php` and `config/db.php` to your project's `config/` folder
2. Copy `web/index.php` to your project's `web/` folder
3. Copy the script `craft` to your project's root (this is the console bootstrap file for Craft)
4. Copy `example.env.php` to your project's root folder, then duplicate it, and rename the copy `.env.php`
5. Edit the `.env.php` file, replacing instances of `REPLACE_ME` with your appropriate settings
6. Add `/.env.php` to your `.gitignore` file

The `web/index.php` file included with CME just has the following that replaces the `Dotenv` lines (it is otherwise unchanged):

// Load the local craft3-multi-environment
if (file_exists($root . DIRECTORY_SEPARATOR . '.env.php'))
require_once $root . DIRECTORY_SEPARATOR . '.env.php';
// Default environment
if (!defined('CRAFT_ENVIRONMENT'))
define('CRAFT_ENVIRONMENT', getenv('CRAFTENV_CRAFT_ENVIRONMENT'));

You will need to create an `.env.php` file for each environment on which your Craft CMS project will be used (other team member's local dev, staging, production, etc.), but the `db.php`, `general.php`, and `index.php` are the same on all environments.

It's recommended that the `example.env.php` **is** checked into your git repo, so others can use it for a guide when creating their own local `.env.php` file.

### Local environments

CME suggests the following environments, each of which can have different Craft settings per environment, independent of the private settings defined in `.env.php`:

1. `*` - applies globally to all environments
2. `live` - your live production environment
3. `staging` - your staging or pre-production environment for client review, external testing, etc.
4. `local` - your local development environment

The `db.php` and `config.php` define each environment, and you can put whatever [Craft Config Settings](https://craftcms.com/docs/config-settings) you desire for each environment in each. The names of the environments and the default settings for each are just suggestions, however. You can change them to be whatever you like.

### Extending it

If you have additional settings that need to be globally accessible, you can just add them to the `.env.php`. For example, let's say we need a private key for Stripe, you can add this to `.env.php` by adding it to the `$craftenv_vars` array:

// The private Stripe key.
'STRIPE_KEY' => 'REPLACE_ME',

CME will auto-prefix all settings in the `$craftenv_vars` with `CRAFTENV_` for semantic reasons, and to avoid namespace collisions.

You should also update the `example.env.php` to include any settings you add, for reference and your team's reference.

### Accessing the settings in `general.php`

You can access any variables defined in the `general.php` file in Twig via `{{ craft.config }}`. e.g.:

{% if craft.config.craftEnv == "local" %}
{% endif %}

### Production via webserver config

It's perfectly fine to use CME as discussed above in a production environment. However, if you want an added measure of security and performance, you can set up your webserver to set the same globally accessible settings via webserver config.

It's slightly more secure, in that only a user with admin privileges should have access to the server config files. It's ever so slightly more performant, in that there's no extra `.env.php` file that is being processed with each request.

This is entirely optional, but if you're interested in doing it, here's how.

1. Use the `index.php` that comes with CME, but ensure that there is no `.env.php` file in your project root. CME will gracefully not attempt to load this file if it doesn't exist.
2. Configure your webserver as described below, and then restart it

#### Apache

Inside the `<VirtualHost>` block:

SetEnv CRAFTENV_CRAFT_ENVIRONMENT "REPLACE_ME"
SetEnv CRAFTENV_DB_DRIVER "mysql"
SetEnv CRAFTENV_DB_SERVER "localhost"
SetEnv CRAFTENV_DB_USER "REPLACE_ME"
SetEnv CRAFTENV_DB_PASSWORD "REPLACE_ME"
SetEnv CRAFTENV_DB_SCHEMA "public"
SetEnv CRAFTENV_DB_TABLE_PREFIX ""
SetEnv CRAFTENV_SITE_URL "REPLACE_ME"
SetEnv CRAFTENV_BASE_URL "REPLACE_ME"
SetEnv CRAFTENV_BASE_PATH "REPLACE_ME"

(...and any other custom config settings you've added)

#### Nginx

Inside the `server {}` or `location ~ \.php {}` block or in the `fastcgi_params` file:

fastcgi_param CRAFTENV_CRAFT_ENVIRONMENT "REPLACE_ME";
fastcgi_param CRAFTENV_DB_DRIVER "mysql";
fastcgi_param CRAFTENV_DB_SERVER "localhost";
fastcgi_param CRAFTENV_DB_USER "REPLACE_ME";
fastcgi_param CRAFTENV_DB_PASSWORD "REPLACE_ME";
fastcgi_param CRAFTENV_DB_SCHEMA "public";
fastcgi_param CRAFTENV_DB_TABLE_PREFIX "";
fastcgi_param CRAFTENV_SITE_URL "REPLACE_ME";
fastcgi_param CRAFTENV_BASE_URL "REPLACE_ME";
fastcgi_param CRAFTENV_BASE_PATH "REPLACE_ME";

(...and any other custom config settings you've added)

Brought to you by [nystudio107](https://nystudio107.com/)
35 changes: 35 additions & 0 deletions config/db.php
@@ -0,0 +1,35 @@
<?php

/**
* Database Configuration
*
* All of your system's database configuration settings go in here.
* You can see a list of the default settings in craft/app/etc/config/defaults/db.php
*/

// $_ENV constants are loaded by craft3-multi-environment from .env.php via web/index.php
return [

// All environments
'*' => [
'driver' => getenv('CRAFTENV_DB_DRIVER'),
'server' => getenv('CRAFTENV_DB_SERVER'),
'user' => getenv('CRAFTENV_DB_USER'),
'password' => getenv('CRAFTENV_DB_PASSWORD'),
'database' => getenv('CRAFTENV_DB_DATABASE'),
'schema' => getenv('CRAFTENV_DB_SCHEMA'),
'tablePrefix' => getenv('CRAFTENV_DB_TABLE_PREFIX'),
],

// Live (production) environment
'live' => [
],

// Staging (pre-production) environment
'staging' => [
],

// Local (development) environment
'local' => [
],
];
50 changes: 50 additions & 0 deletions config/general.php
@@ -0,0 +1,50 @@
<?php

/**
* General Configuration
*
* All of your system's general configuration settings go in here.
* You can see a list of the default settings in craft/app/etc/config/defaults/general.php
*/

// $_ENV constants are loaded by craft3-multi-environment from .env.php via web/index.php
return [

// All environments
'*' => [
'omitScriptNameInUrls' => true,
'usePathInfo' => true,
'cacheDuration' => false,
'useEmailAsUsername' => true,
'generateTransformsBeforePageLoad' => true,
'siteUrl' => getenv('CRAFTENV_SITE_URL'),
'craftEnv' => CRAFT_ENVIRONMENT,

// Set the environmental variables
'environmentVariables' => [
'baseUrl' => getenv('CRAFTENV_BASE_URL'),
'basePath' => getenv('CRAFTENV_BASE_PATH'),
],
],

// Live (production) environment
'live' => [
'devMode' => false,
'enableTemplateCaching' => true,
'allowAutoUpdates' => false,
],

// Staging (pre-production) environment
'staging' => [
'devMode' => false,
'enableTemplateCaching' => true,
'allowAutoUpdates' => false,
],

// Local (development) environment
'local' => [
'devMode' => true,
'enableTemplateCaching' => false,
'allowAutoUpdates' => true,
],
];
24 changes: 24 additions & 0 deletions craft
@@ -0,0 +1,24 @@
#!/usr/bin/env php
<?php
/**
* Craft console bootstrap file
*/

// Project root path
$root = __DIR__;

// Composer autoloader
require_once $root.'/vendor/autoload.php';

// Load the local craft3-multi-environment
if (file_exists($root . DIRECTORY_SEPARATOR . '.env.php'))
require_once $root . DIRECTORY_SEPARATOR . '.env.php';
// Default environment
if (!defined('CRAFT_ENVIRONMENT'))
define('CRAFT_ENVIRONMENT', getenv('CRAFTENV_CRAFT_ENVIRONMENT'));

// Craft
define('CRAFT_BASE_PATH', $root);
$app = require $root.'/vendor/craftcms/cms/bootstrap/console.php';
$exitCode = $app->run();
exit($exitCode);
90 changes: 90 additions & 0 deletions example.env.php
@@ -0,0 +1,90 @@
<?php
/**
* Craft-Multi-Environment (CMS)
* @author nystudio107
* @copyright Copyright (c) 2017 nystudio107
* @link https://nystudio107.com/
* @package craft3-multi-environment
* @since 1.0.0
* @license MIT
*
* This file should be renamed to '.env.php' and it should reside in your root
* project directory. Add '/.env.php' to your .gitignore. See below for production
* usage notes.
*/

// The $craftenv_vars are all auto-prefixed with CRAFTENV_ -- you can add whatever you want here
// and access them via getenv() using the prefixed name
$craftenv_vars = [
// The Craft environment we're running in ('local', 'staging', 'live', etc.).
'CRAFT_ENVIRONMENT' => 'REPLACE_ME',

// The database driver that will used ('mysql' or 'pgsql')
'DB_DRIVER' => 'mysql',

// The database server name or IP address (usually this is 'localhost' or '127.0.0.1')
'DB_SERVER' => 'localhost',

// The database username to connect with
'DB_USER' => 'REPLACE_ME',

// The database password to connect with
'DB_PASSWORD' => 'REPLACE_ME',

// The name of the database to select
'DB_DATABASE' => 'REPLACE_ME',

// The database schema that will be used (PostgreSQL only)
'DB_SCHEMA' => 'public',

// The prefix that should be added to generated table names (only necessary if multiple things are sharing the same database)
'DB_TABLE_PREFIX' => '',

// The site url to use; it can be hard-coded as well
'SITE_URL' => (isset($_SERVER['HTTPS']) ? 'https://' : 'http://') . $_SERVER['HTTP_HOST'] . '/',

// The base url environmentVariable to use for Assets; it can be hard-coded as well
'BASE_URL' => (isset($_SERVER['HTTPS']) ? 'https://' : 'http://') . $_SERVER['HTTP_HOST'] . '/',

// The base path environmentVariable for Assets; it can be hard-coded as well
'BASE_PATH' => realpath(dirname(__FILE__)) . '/public/',
];

// Set all of the .env values, auto-prefixed with `CRAFTENV_`
foreach ($craftenv_vars as $key => $value) {
putenv("CRAFTENV_$key=$value");
}

/**
* For production environments, this .env.php file can be used, or preferrably,
* (for security & speed), set the $_ENV variables directly from the server config.
*
* Apache - inside the <VirtualHost> block:
SetEnv CRAFTENV_CRAFT_ENVIRONMENT "REPLACE_ME"
SetEnv CRAFTENV_DB_DRIVER "mysql"
SetEnv CRAFTENV_DB_SERVER "localhost"
SetEnv CRAFTENV_DB_USER "REPLACE_ME"
SetEnv CRAFTENV_DB_PASSWORD "REPLACE_ME"
SetEnv CRAFTENV_DB_DATABASE "REPLACE_ME"
SetEnv CRAFTENV_DB_SCHEMA "public"
SetEnv CRAFTENV_DB_TABLE_PREFIX ""
SetEnv CRAFTENV_SITE_URL "REPLACE_ME"
SetEnv CRAFTENV_BASE_URL "REPLACE_ME"
SetEnv CRAFTENV_BASE_PATH "REPLACE_ME"
* Nginx - inside the server {} or location ~ \.php$ {} block:
fastcgi_param CRAFTENV_CRAFT_ENVIRONMENT "REPLACE_ME";
fastcgi_param CRAFTENV_DB_DRIVER "mysql";
fastcgi_param CRAFTENV_DB_SERVER "localhost";
fastcgi_param CRAFTENV_DB_USER "REPLACE_ME";
fastcgi_param CRAFTENV_DB_PASSWORD "REPLACE_ME";
fastcgi_param CRAFTENV_DB_DATABASE "REPLACE_ME";
fastcgi_param CRAFTENV_DB_SCHEMA "public";
fastcgi_param CRAFTENV_DB_TABLE_PREFIX "";
fastcgi_param CRAFTENV_SITE_URL "REPLACE_ME";
fastcgi_param CRAFTENV_BASE_URL "REPLACE_ME";
fastcgi_param CRAFTENV_BASE_PATH "REPLACE_ME";
*/

0 comments on commit 0bfc0da

Please sign in to comment.