This method also handles how the environment is detected at the beginning of the request.
#### Custom Detection
While the default detection rules are very simple (if the 'SERVER_ADDR' variable is set to
127.0.0.1, the environment is assumed to be 'development', or if the string 'test' is
found anywhere in the host name, it is assumed to be 'test', and in all other cases it
is assumed to be 'production'), you can define your own detection rule set easily using a
closure that accepts an instance of the Request object, and returns the name of the correct
environment, as in the following example:
embed:lithium\tests\cases\core\EnvironmentTest::testCustomDetector(1-9)
In the above example, the user-specified closure takes in a Request object, and using the
server data which it encapsulates, returns the correct environment name as a string.
#### Host Mapping
The most common use case is to set the environment depending on host name. For convenience,
the is() method also accepts an array that matches host names to environment names, where
each key is an environment, and each value is either an array of valid host names, or a
regular expression used to match a valid host name.
embed:lithium\tests\cases\core\EnvironmentTest::testDetectionWithArrayMap(1-5)
In this example, a regular expression is being used to match local domains
(i.e. localhost), as well as the built-in .console domain, for console requests. Note
that in the console, the environment can always be overridden by specifying the --env
option.
Then, one or more host names are matched up to 'test' and 'staging', respectively. Note
that no rule is present for production: this is because 'production' is the default value
if no other environment matches.
public static is ( mixed $detect ) : boolean | ||
$detect | mixed | Either the name of an environment to check against the current, i.e. `'development'` or `'production'`, or a closure which `Environment` will use to determine the current environment name, or an array mapping environment names to host names. |
Résultat | boolean | If `$detect` is a string, returns `true` if the current environment matches the value of `$detect`, or `false` if no match. If used to set a custom detector, returns `null`. |
/** * Constructor for this adapter - sets relevant default configurations for Twig to be used * when instantiating a new Twig_Environment and Twig_Loader_Filesystem. * * @param array $config Optional configuration directives. * Please see http://www.twig-project.org/book/03-Twig-for-Developers for all * available configuration keys and their description. * There are 4 settings that is set * - `cache`: Path to /resources/tmp/cache/templates/ where compiled templates will be stored * - `auto_reload`: If Environment is not production, templates will be reloaded once edited * - `base_template_class`: Overriden to the Template adapter, be carefull with changing this * - `autoescape`: Set to false because the way we inject content is with full html that should not be escaped * @return void */ public function __construct(array $config = array()) { /** * TODO Change hardcoded LITHIUM_APP_PATH to be dynamic */ $defaults = array('cache' => LITHIUM_APP_PATH . '/resources/tmp/cache/templates', 'auto_reload' => !Environment::is('production'), 'base_template_class' => 'li3_twig\\template\\view\\adapter\\Template', 'autoescape' => false); parent::__construct($config + $defaults); }
/** * * Determines if we should run any `newrelic_` methods. * * If the configuration for the plugin `shouldRun` does not exist, set * a generic one. * * @return bool */ public static function shouldRun() { if (!is_callable(Libraries::get('li3_newrelic', 'shouldRun'))) { $config = Libraries::get('li3_newrelic'); $config['shouldRun'] = function () { return Environment::is('production') && extension_loaded('newrelic'); }; Libraries::add('li3_newrelic', $config); } return Libraries::get('li3_newrelic', 'shouldRun')->__invoke(); }
/** * Create an entity manager * * @param array $params Parameters * @return object Entity manager * @filter */ protected function createEntityManager() { $configuration = Setup::createAnnotationMetadataConfiguration([$this->_config['models']], Environment::is('development'), $this->_config['proxies'], isset($this->_config['cache']) ? call_user_func($this->_config['cache']) : null); $configuration->setProxyNamespace($this->_config['proxyNamespace']); $eventManager = new EventManager(); $eventManager->addEventListener([Events::postLoad, Events::prePersist, Events::preUpdate], $this); $connection = $this->connectionSettings; $params = compact('connection', 'configuration', 'eventManager'); return $this->_filter(__METHOD__, $params, function ($self, $params) { return EntityManager::create($params['connection'], $params['configuration'], $params['eventManager']); }); }
public static function terminate() { static::initSession(); static::initAuth(); static::$_data['end'] = microtime(true); static::$_data['environment'] = Environment::get(); static::$_data['events.count'] = count(static::$_data['events']); static::$_data['db.count'] = count(static::$_data['db']); static::$_data['runtime'] = static::$_data['end'] - static::$_data['start']; static::$_data['memory.end'] = memory_get_usage(true); static::$_data['memory.usage'] = memory_get_peak_usage(true); static::$_data['log.count'] = count(static::$_data['log']); if (!Environment::is('production') && static::$_view) { try { echo static::$_view->render(array('element' => 'debug_bar')); } catch (\lithium\template\TemplateException $e) { $view = new View(array('paths' => array('element' => '{:library}/views/elements/{:template}.{:type}.php'))); echo $view->render(array('element' => 'debug_bar'), array(), array('library' => 'li3_debug')); } } }
/** * Create environment prefix location using `lihtium\net\http\Media::location` * Check if `lihtium\net\http\Media::asset` return the correct URL * for the test environement */ public function testEnvironmentAsset2() { Media::attach('appcdn', array('production' => array('absolute' => true, 'path' => null, 'scheme' => 'http://', 'host' => 'my.cdnapp.com', 'prefix' => 'assets'), 'test' => array('absolute' => true, 'path' => null, 'scheme' => 'http://', 'host' => 'my.cdntest.com', 'prefix' => 'assets'))); $env = Environment::get(); Environment::set('test'); $result = Media::asset('style', 'css', array('scope' => 'appcdn')); $expected = 'http://my.cdntest.com/assets/css/style.css'; $this->assertEqual($expected, $result); Environment::is($env); }
* * @see app\controllers\PagesController */ Router::connect('/', 'Index::index'); /** * Connect the rest of `PagesController`'s URLs. This will route URLs like `/pages/about` to * `PagesController`, rendering `/views/pages/about.html.php` as a static page. */ Router::connect('/pages/{:args}', 'Pages::view'); /** * Add the testing routes. These routes are only connected in non-production environments, and allow * browser-based access to the test suite for running unit and integration tests for the Lithium * core, as well as your own application and any other loaded plugins or frameworks. Browse to * [http://path/to/app/test](/test) to run tests. */ if (Environment::is('development')) { Router::connect('/test/{:args}', array('controller' => 'lithium\\test\\Controller')); Router::connect('/test', array('controller' => 'lithium\\test\\Controller')); } /** * ### Database object routes * * The routes below are used primarily for accessing database objects, where `{:id}` corresponds to * the primary key of the database object, and can be accessed in the controller as * `$this->request->id`. * * If you're using a relational database, such as MySQL, SQLite or Postgres, where the primary key * is an integer, uncomment the routes below to enable URLs like `/posts/edit/1138`, * `/posts/view/1138.json`, etc. */ // Router::connect('/{:controller}/{:action}/{:id:\d+}.{:type}', array('id' => null));
echo $this->html->charset(); ?> <title>Unhandled exception</title> <?php echo $this->html->style(array('debug', 'lithium')); ?> <?php echo $this->scripts(); ?> <?php echo $this->html->link('Icon', null, array('type' => 'icon')); ?> </head> <body class="app"> <?php if (\lithium\core\Environment::is('production')) { ?> <div style="width:100%;text-align: center;margin-top:42px"><h1>Error 404 :(</h1></div> <img src="http://www.ilovemeow.com/img/cats.jpg" alt="image_cat" height="336" width="500" style="position: relative; left: 50%; top: 10px; margin-left: -250px; "> <?php } else { ?> <div id="container"> <div id="header"> <h1>An unhandled exception was thrown</h1> </div> <div id="content"> <?php echo $this->content(); ?>
<?php use lithium\net\http\Router; use lithium\action\Response; use lithium\core\Environment; use li3_perf\extensions\util\Asset; use li3_perf\extensions\webgrind\library\Webgrind; use li3_perf\extensions\webgrind\library\FileHandler; // Assets (can't symlink in the VM because Windows host) Router::connect("/{:library}/{:asset_type:js|img|css}/{:args}", array(), function ($request) { // If not production, then return the asset with a "no-cache" cache-control, there won't be any 304's, etc. $no_cache = !Environment::is('production'); return Asset::render($request->params['library'], $request->params['asset_type'], join('/', $request->params['args']), compact('no_cache')); }); // This one is cool. It outputs the last few lines of a log file. // If CCZE is installed the log output will be in HTML and styles can be altered easily with CSS. Router::connect('/li3_perf/tail/{:file}/{:lines}', array('lines' => 25, 'file' => LITHIUM_APP_PATH . '/resources/tmp/logs/debug.log'), function ($request) { $lines = $request->params['lines']; $logfile = $request->params['file']; header("Content-type: text/html"); // echo `tail -n 50 /var/log/php-fpm/www-error.log | ccze -h`; $options = '-n ' . $lines; $command = 'tail ' . $options . ' ' . $logfile . ' | ccze -h'; $output = shell_exec($command); if ($output == null) { $output = ''; $command = 'tail ' . $options . ' ' . $logfile; $lines = explode("\n", shell_exec($command)); if (!empty($lines)) { foreach ($lines as $line) { $output .= $line . "<br />";
/** * renders a given widget element with given data * * @param string $widget name of widget to render * @param array $data additional data to be passed into element * @param array $options additional options: * - `hb`: set to false to disable handlebars rendering * - `target`: a string that defines which widgets to render, depending on widgets * target parameter * @return string the rendered markup from all widgets */ protected function parse($widget, array $data = array(), array $options = array()) { $defaults = array('target' => null, 'hb' => true); $options += $defaults; if ($options['target'] && (!!empty($data['target']) || $data['target'] != $options['target'])) { return; } if (!$options['hb']) { return $this->_context->view()->render(compact('widget'), $data, $options); } $hb = $this->_context->helper('handlebars'); try { return $hb->render(sprintf('../widgets/%s', $widget), $data, $options); } catch (TemplateException $e) { return Environment::is('development') ? $e->getMessage() : ''; // return $hb->render(sprintf('../widgets/%s', $widget), $data, $options); } return ''; }
* @see lithium\util\collection\Filters */ use lithium\core\Libraries; use lithium\net\http\Router; use lithium\core\Environment; use lithium\action\Dispatcher; /** * Define the basic environment detector * dev.* domains will be `development`, stage.* will be `staging` * and the rest as `production` */ Environment::is(function ($request) { $host = $request->env('HTTP_HOST'); if (strpos($host, "raymondjulin") !== false) { return 'development'; } if (strpos($host, "stage.") !== false) { return 'staging'; } return 'production'; }); /** * This filter intercepts the `run()` method of the `Dispatcher`, and first passes the `'request'` * parameter (an instance of the `Request` object) to the `Environment` class to detect which * environment the application is running in. Then, loads all application routes in all plugins, * loading the default application routes last. * * Change this code if plugin routes must be loaded in a specific order (i.e. not the same order as * the plugins are added in your bootstrap configuration), or if application routes must be loaded * first (in which case the default catch-all routes should be removed). * * If `Dispatcher::run()` is called multiple times in the course of a single request, change the
continue; } $file = "{$config['path']}/config/routes.php"; file_exists($file) ? include $file : null; } } Dispatcher::applyFilter('run', function ($self, $params, $chain) { if (defined('ENVIRONMENT')) { // 以上常量在 bootstrap.php 文件中设置, 但一般不这样做, 而是选择让它根据域名而加载不同的配置 Environment::is(function ($request) { $environment = environment_config(); return ENVIRONMENT; }); } else { Environment::is(function ($request) { $environment = environment_config(); return $environment['environment']; }); } Environment::set($params['request']); load_environment(); // CSRF // CSRF::init(); // if ($params['request']->is('post')) { // if (! CSRF::check_referer($params['request']->url)) { // throw new \Exception("CSRF验证失败"); // } // // POST method: check token // } return $chain->next($self, $params, $chain); });
} else { \ProfilerRenderer::setIncludeJquery(false); } // Set our prettify options. if ($options['prettify']) { \ProfilerRenderer::setIncludePrettify(true); \ProfilerRenderer::setPrettifyLocation($options['prettify']); } else { \ProfilerRenderer::setIncludePrettify(false); } /** * Due to the way the `Environment` class determines the current configuration * we need to wait for the `Dispatcher` to start up before we know where we are. */ Filters::apply('lithium\\action\\Dispatcher', '_callable', function ($self, $params, $chain) { if (!Environment::is(Libraries::get('li3_profiler', 'environment'))) { // Enable the profiler. \Profiler::disable(); } else { $controller = $chain->next($self, $params, $chain); if (Libraries::get('li3_profiler', 'inject')) { /** * If we have a `Controller` object we will filter it so that we can * inject our rendering HTML. */ if (is_a($controller, '\\lithium\\action\\Controller')) { $controller->applyFilter('__invoke', function ($self, $params, $chain) { $response = $chain->next($self, $params, $chain); if ($response->type === 'text/html') { /** * Here we tack in our rendering if the `Response` object happens
/** * Constructor for this adapter - sets relevant default configurations for Twig to be used * when instantiating a new Twig_Environment and Twig_Loader_Filesystem. * * @param array $config Optional configuration directives. * Please see http://www.twig-project.org/book/03-Twig-for-Developers for all * available configuration keys and their description. * There are 4 settings that is set * - `cache`: Path to /resources/tmp/cache/templates/ where compiled templates will be stored * - `auto_reload`: If Environment is not production, templates will be reloaded once edited * - `base_template_class`: Overriden to the Template adapter, be carefull with changing this * - `autoescape`: Set to false because the way we inject content is with full html that should not be escaped * @return void * @todo Change hardcoded LITHIUM_APP_PATH to be dynamic */ public function __construct(array $config = array()) { $defaults = array('cache' => Twig::cachePath(), 'auto_reload' => !Environment::is('production'), 'autoescape' => false); parent::__construct($config + $defaults); }
Uploads::applyFilter('save', function ($self, $params, $chain) { if ($params['data']) { $params['entity']->set($params['data']); $params['data'] = array(); } if (!$params['entity']->id) { $params['entity']->created = date('Y-m-d H:i:s'); } return $chain->next($self, $params, $chain); }); use lithium\util\Validator; Validator::add('usernameTaken', function ($value) { $success = false; if (strlen($value) != 0) { $success = count(Users::findByUsername($value)) == 0 ? false : true; } return !$success; }); use lithium\core\Libraries; Libraries::add('upload', array('path' => LITHIUM_APP_PATH . '/libraries/_source/upload/')); Libraries::add('captcha', array('path' => LITHIUM_APP_PATH . '/libraries/_source/captcha/', 'webroot' => LITHIUM_APP_PATH . '/libraries/_source/captcha/', "bootstrap" => "securimage.php")); define('_INSTALL', file_exists($_SERVER['DOCUMENT_ROOT'] . "/install") ? '1' : '0'); function getBaseUrl() { $protocol = isset($_SERVER["HTTPS"]) && $_SERVER['HTTPS'] != "off" ? "https" : "http"; return $protocol . "://" . $_SERVER['HTTP_HOST']; } use lithium\core\Environment; Environment::is(function ($request) { return in_array($request->env('SERVER_ADDR'), array('::1', '127.0.0.1')) ? 'development' : 'production'; });
public function resetPassword() { $redirectUrl = '/'; $email = null; if (isset($this->request->data['email'])) { $email = $this->request->data['email']; } else { if (isset($this->request->args[0])) { $email = $this->request->args[0]; } } $user = Users::first(array('conditions' => array('email_address' => new MongoRegex('/' . $email . '/i')))); if (!$user) { $this->flashMessage('User not found for password reset!', array('alertType' => 'error')); return $this->redirect($redirectUrl); } else { if (!isset($user->email_address)) { $this->flashMessage('That user does not have an email address on file. Please email the webmaster for assistance.', array('alertType' => 'error')); return $this->redirect($redirectUrl); } } $identity = PasswordIdentities::first(array('conditions' => array('user_id' => $user->_id, 'type' => 'password', 'prv_name' => 'afdc.com'))); if (!$identity) { $identity = PasswordIdentities::create(); $identity->user_id = $user->_id; $identity->prv_uid = strtolower($user->email_address); } $newPassword = $identity->generatePassword(); if ($identity->save()) { if (Environment::is('production')) { // Todo: replace this with something that doesn't suck $to = $user->email_address; $subject = '[AFDC.com] Password Reset'; $message = 'Your password has been reset. It is now: ' . $newPassword; $headers = implode("\n", array('From: system@leagues.afdc.com', 'Reply-To: webmaster@afdc.com', 'X-Mailer: PHP/' . phpversion())); mail($to, $subject, $message, $headers); $this->flashMessage('An email message has been sent with the new password. Please be sure to check your spam folder.', array('alertType' => 'info')); } else { $this->flashMessage("A new password generated: {$user->email_address} / {$newPassword}. Due to environment limitations, no email was sent.", array('alertType' => 'info')); } return $this->redirect($redirectUrl); } else { $this->flashMessage('A new password could not be saved; please try again or email the webmaster for assistance.', array('alertType' => 'error')); return $this->redirect($redirectUrl); } return compact('user', 'identity', 'newPassword'); }
/** * Tests using a custom detector to get the current environment. * * @return void */ public function testCustomDetector() { Environment::is(function ($request) { if ($request->env('HTTP_HOST') == 'localhost') { return 'development'; } if ($request->env('HTTP_HOST') == 'staging.server') { return 'test'; } return 'production'; }); $request = new MockRequest(array('HTTP_HOST' => 'localhost')); Environment::set($request); $this->assertTrue(Environment::is('development')); $request = new MockRequest(array('HTTP_HOST' => 'lappy.local')); Environment::set($request); $this->assertTrue(Environment::is('production')); $request = new MockRequest(array('HTTP_HOST' => 'staging.server')); Environment::set($request); $this->assertTrue(Environment::is('test')); $request = new MockRequest(array('HTTP_HOST' => 'test.local')); Environment::set($request); $this->assertTrue(Environment::is('production')); }
*/ Router::connect('/', 'Pages::view'); /** * Connect the rest of `PagesController`'s URLs. This will route URLs like `/pages/about` to * `PagesController`, rendering `/views/pages/about.html.php` as a static page. */ Router::connect('/pages/{:args}', 'Pages::view'); /** * ### Testing routes * * Add the testing routes. These routes are only connected in non-production environments, and allow * browser-based access to the test suite for running unit and integration tests for the Lithium * core, as well as your own application and any other loaded plugins or frameworks. Browse to * [http://path/to/app/test](/test) to run tests. */ if (!Environment::is('production')) { Router::connect('/test/{:args}', array('controller' => 'lithium\\test\\Controller')); Router::connect('/test', array('controller' => 'lithium\\test\\Controller')); } /** * ### Database object routes * * The routes below are used primarily for accessing database objects, where `{:id}` corresponds to * the primary key of the database object, and can be accessed in the controller as * `$this->request->id`. * * If you're using a relational database, such as MySQL, SQLite or Postgres, where the primary key * is an integer, uncomment the routes below to enable URLs like `/posts/edit/1138`, * `/posts/view/1138.json`, etc. */ // Router::connect('/{:controller}/{:action}/{:id:\d+}.{:type}', array('id' => null));
*/ use lithium\action\Dispatcher; use lithium\action\Request; use lithium\core\Environment; /** * This filter fakes the `Request` object to the correct base so that everything * works as expected without .htaccess rewrite rules. */ if (PHP_SAPI == 'cli-server') { Dispatcher::applyFilter('run', function ($self, $params, $chain) { $params['request'] = new Request(array('base' => '')); Environment::is(function ($request) { $isLocal = in_array($request->env('SERVER_NAME'), array('localhost')); switch (true) { case isset($request->env): return $request->env; case $isLocal: return 'development'; case $request->command == 'test': return 'test'; case preg_match('/^test\\//', $request->url) && $isLocal: return 'test'; case preg_match('/^test/', $request->env('HTTP_HOST')): return 'test'; default: return 'production'; } }); return $chain->next($self, $params, $chain); }); }