FuelPHPコードリーディング

この資料は [FuelPHP＆CodeIgniter ユーザの集い #9](https://atnd.org/events/70728) の発表資料です。

## FuelPHPとは

- PHP製のWebアプリケーションフレームワーク
- 現行バージョン（1系）はPHP5.3.3以上
- 次期バージョン（2系）はPHP5.5以上（デルデル詐欺気味・・・）
- Current Version 1.7.3
- Development Version 1.8
- MITライセンス
- 日本語ドキュメントや書籍多数
- 主要な特徴
  - HMVC（Hierarchial Model View Controller）
    - Modulesという仕組みで複数のMVCを階層構造に出来る
  - Rest Controller
  - ORM
  - DB Migration
  - 様々なテンプレートエンジンを利用可能
     - SimpleTags,Mustache,Twig,Haml,Jade,Haml,Smarty,Dwoo
  - Composer対応（独自パッケージ管理も付属）
  - Railsに影響されたOilスキャフォールド（コード自動生成）
  - oilタスク
  - テストはPHPUnitを統合
  - セキュリティ対策
     - 出力エンコーディング
     - CSRF 保護
     - XSS フィルタリング
     - 入力フィルタリング
     - SQL インジェクション

## FuelPHPコードリーディング

今日から何回かに分けてFuelPHPのコードリーディングを行います。

### コードリーディングの目的
- FuelPHPの仕組みを理解し、予期せぬトラブルや不測の事態に自ら対処できる技術力を身につける(中身のよくわからないフレームワークなんて、だれも仕事で使いたくないよね・・・)

※ このコードリーディングの対象バージョン： 1.7.3

### ●１日目「bootstrap」

今日はFuelPHPで開発者の作ったコードがどのようにぐごいているかを理解します。

#### 教材インストール

```
$ curl get.fuelphp.com/oil | sh
$ oil create day1
```

```
$ php composer.phar install
$ php composer.phar create-project fuel/fuel:dev-1.7/master day1
```

こんな感じでTokeを聞かれたら、書いているURLにアクセスしてトークンを生成して下さい。（レートリミットによる制限がかかっているらしいです）

```
Could not fetch https://api.github.com/repos/fuel/docs, please create a GitHub OAuth token to go over the API rate limit
Head to https://github.com/settings/tokens/new?scopes=repo&description=Composer+on+*******
to retrieve a token. It will be stored in "/Users/yusuke/.composer/auth.json" for future use by Composer.
Token (hidden):
```

こんな感じでログが流れます。

```
Token stored successfully.
Updating dependencies (including require-dev)
  - Installing composer/installers (v1.0.21)
    Downloading: 100%

  - Installing fuel/docs (dev-1.7/master 473174d)
    Cloning 473174da2cf503c60d4a9935b71acfc31f0906d0

  - Installing fuel/core (dev-1.7/master f614b30)
    Cloning f614b30e1f76389580c2d97991ab3f25c1533a29

  - Installing fuel/auth (dev-1.7/master aa9bd2e)
    Cloning aa9bd2e5104026814ff516aacf03258f62a94a55

  - Installing fuel/email (dev-1.7/master 8fbf378)
    Cloning 8fbf378d74bac170a96cad96ba0aed77e319a865

  - Installing fuel/oil (dev-1.7/master ea37c3a)
    Cloning ea37c3a7fe8675fb3327327213b2eca55303933a

  - Installing fuel/orm (dev-1.7/master 5e05c30)
    Cloning 5e05c3068562548657fea69850a23b23f65a5545

  - Installing fuel/parser (dev-1.7/master 0cacd10)
    Cloning 0cacd10d7b1b8f92a0eeddce75c6ba2c0c28112f

  - Installing fuelphp/upload (2.0.2)
    Downloading: 100%

  - Installing psr/log (1.0.0)
    Downloading: 100%

  - Installing monolog/monolog (1.5.0)
    Loading from cache

  - Installing michelf/php-markdown (1.4.0)
    Downloading: 100%

monolog/monolog suggests installing mlehner/gelf-php (Allow sending log messages to a GrayLog2 server)
monolog/monolog suggests installing raven/raven (Allow sending log messages to a Sentry server)
monolog/monolog suggests installing doctrine/couchdb (Allow sending log messages to a CouchDB server)
monolog/monolog suggests installing ext-amqp (Allow sending log messages to an AMQP server (1.0+ required))
monolog/monolog suggests installing ext-mongo (Allow sending log messages to a MongoDB server)
Writing lock file
Generating autoload files
	Made writable: /Users/yusuke/WebstormProjects/fuelphp_code_reding/day1/fuel/app/cache
	Made writable: /Users/yusuke/WebstormProjects/fuelphp_code_reding/day1/fuel/app/logs
	Made writable: /Users/yusuke/WebstormProjects/fuelphp_code_reding/day1/fuel/app/tmp
	Made writable: /Users/yusuke/WebstormProjects/fuelphp_code_reding/day1/fuel/app/config

```

#### ディレクトリ構造

FuelPHPの基本的なディレクトリ構成は以下のとおり。

```
Root                
 +                  
 ++fuel             
 |  +               
 |  +---+app ←開発用ディレクトリ       
 |  |     +         
 |  |     +---+class
 |  |     |      :     
 |  |     +---+bootstrap.php ←app用のbootstrap 
 |  |               
 |  +---+core ←コアクラス用ディレクトリ       
 |  |               
 |  +---+packages ←パッケージが格納されているディレクトリ  
 |  |               
 |  +---+Vendor ←外部ライブラリが格納されているディレクトリ　    
 |                  
 ++public           
    +               
    +---+assets ←js/css/imgを格納するディクレクトリ     
    |               
    +---+index.php  ←エントリーポイント
```

#### エントリーポイント「index.php」

index.php

```php
<?php
/**
 * Fuel is a fast, lightweight, community driven PHP5 framework.
 *
 * @package    Fuel
 * @version    1.7
 * @author     Fuel Development Team
 * @license    MIT License
 * @copyright  2010 - 2014 Fuel Development Team
 * @link       http://fuelphp.com
 */

/**
 * Set error reporting and display errors settings.  You will want to change these when in production.
 */
error_reporting(-1);
ini_set('display_errors', 1);

/**
 * Website document root
 */
define('DOCROOT', __DIR__.DIRECTORY_SEPARATOR);

/**
 * Path to the application directory.
 */
define('APPPATH', realpath(__DIR__.'/../fuel/app/').DIRECTORY_SEPARATOR);

/**
 * Path to the default packages directory.
 */
define('PKGPATH', realpath(__DIR__.'/../fuel/packages/').DIRECTORY_SEPARATOR);

/**
 * The path to the framework core.
 */
define('COREPATH', realpath(__DIR__.'/../fuel/core/').DIRECTORY_SEPARATOR);

// Get the start time and memory for use later
defined('FUEL_START_TIME') or define('FUEL_START_TIME', microtime(true));
defined('FUEL_START_MEM') or define('FUEL_START_MEM', memory_get_usage());

// Load in the Fuel autoloader
if ( ! file_exists(COREPATH.'classes'.DIRECTORY_SEPARATOR.'autoloader.php'))
{
	die('No composer autoloader found. Please run composer to install the FuelPHP framework dependencies first!');
}

// Activate the framework class autoloader
require COREPATH.'classes'.DIRECTORY_SEPARATOR.'autoloader.php';
class_alias('Fuel\\Core\\Autoloader', 'Autoloader');

// Exception route processing closure
$routerequest = function($route = null, $e = false)
{
	Request::reset_request(true);

	$route = array_key_exists($route, Router::$routes) ? Router::$routes[$route]->translation : Config::get('routes.'.$route);

	if ($route instanceof Closure)
	{
		$response = $route();

		if( ! $response instanceof Response)
		{
			$response = Response::forge($response);
		}
	}
	elseif ($e === false)
	{
		$response = Request::forge()->execute()->response();
	}
	elseif ($route)
	{
		$response = Request::forge($route, false)->execute(array($e))->response();
	}
	else
	{
		throw $e;
	}

	return $response;
};

// Generate the request, execute it and send the output.
try
{
	// Boot the app...
	require APPPATH.'bootstrap.php';

	// ... and execute the main request
	$response = $routerequest();
}
catch (HttpNoAccessException $e)
{
	$response = $routerequest('_403_', $e);
}
catch (HttpNotFoundException $e)
{
	$response = $routerequest('_404_', $e);
}
catch (HttpServerErrorException $e)
{
	$response = $routerequest('_500_', $e);
}

// This will add the execution time and memory usage to the output.
// Comment this out if you don't use it.
$response->body((string) $response);
if (strpos($response->body(), '{exec_time}') !== false or strpos($response->body(), '{mem_usage}') !== false)
{
	$bm = Profiler::app_total();
	$response->body(
		str_replace(
			array('{exec_time}', '{mem_usage}'),
			array(round($bm[0], 4), round($bm[1] / pow(1024, 2), 3)),
			$response->body()
		)
	);
}

// Send the output to the client
$response->send(true);

```

##### index.phpのやっていること要約

- エラーレベルの設定
  - 全てのPHPエラーを表示する
  - エラーのディスプレイ出力を有効にする

- 環境変数定義
  - DOCROOT
  - APPPATH
  - PKGPATH
  - COREPATH
  - FUEL_START_TIME
  - FUEL_START_MEM

- autoloader.phpの読み込み
  - coreのautoloader.phpをまず読む

- Requestクラスを使ってルーティング
  
- View内にメモリ使用量とロードタイムを埋め込む

##### core/bootstrap.php

```php
<?php
/**
 * Part of the Fuel framework.
 *
 * @package    Fuel
 * @version    1.7
 * @author     Fuel Development Team
 * @license    MIT License
 * @copyright  2010 - 2015 Fuel Development Team
 * @link       http://fuelphp.com
 */

define('DS', DIRECTORY_SEPARATOR);
define('CRLF', chr(13).chr(10));

setup_autoloader();

// Load the base functions
require COREPATH.'base.php';

/**
 * Do we have access to mbstring?
 * We need this in order to work with UTF-8 strings
 */
define('MBSTRING', function_exists('mb_get_info'));

/**
 * Load the Composer autoloader if present
 */
defined('VENDORPATH') or define('VENDORPATH', realpath(COREPATH.'..'.DS.'vendor').DS);
if ( ! is_file(VENDORPATH.'autoload.php'))
{
	die('Composer is not installed. Please run "php composer.phar update" in the root to install Composer');
}
require VENDORPATH.'autoload.php';

/**
 * Register all the error/shutdown handlers
 */
register_shutdown_function(function ()
{
	// reset the autoloader
	\Autoloader::_reset();

	// if we have sessions loaded, and native session emulation active
	if (\Config::get('session.native_emulation', false))
	{
		// close the name session
		session_id() and session_write_close();
	}

	// make sure we're having an output filter so we can display errors
	// occuring before the main config file is loaded
	\Config::get('security.output_filter', null) or \Config::set('security.output_filter', 'Security::htmlentities');

	try
	{
		// fire any app shutdown events
		\Event::instance()->trigger('shutdown', '', 'none', true);

		// fire any framework shutdown events
		\Event::instance()->trigger('fuel-shutdown', '', 'none', true);
	}
	catch (\Exception $e)
	{
		if (\Fuel::$is_cli)
		{
			\Cli::error("Error: ".$e->getMessage()." in ".$e->getFile()." on ".$e->getLine());
			\Cli::beep();
			exit(1);
		}
		else
		{
			logger(\Fuel::L_ERROR, 'shutdown - ' . $e->getMessage()." in ".$e->getFile()." on ".$e->getLine());
		}
	}
	return \Error::shutdown_handler();
});

set_exception_handler(function (\Exception $e)
{
	// reset the autoloader
	\Autoloader::_reset();

	// deal with PHP bugs #42098/#54054
	if ( ! class_exists('Error'))
	{
		include COREPATH.'classes/error.php';
		class_alias('\Fuel\Core\Error', 'Error');
		class_alias('\Fuel\Core\PhpErrorException', 'PhpErrorException');
	}

	return \Error::exception_handler($e);
});

set_error_handler(function ($severity, $message, $filepath, $line)
{
	// reset the autoloader
	\Autoloader::_reset();

	// deal with PHP bugs #42098/#54054
	if ( ! class_exists('Error'))
	{
		include COREPATH.'classes/error.php';
		class_alias('\Fuel\Core\Error', 'Error');
		class_alias('\Fuel\Core\PhpErrorException', 'PhpErrorException');
	}

	return \Error::error_handler($severity, $message, $filepath, $line);
});

function setup_autoloader()
{
	\Autoloader::add_namespace('Fuel\\Core', COREPATH.'classes/');

	\Autoloader::add_namespace('PHPSecLib', COREPATH.'vendor'.DS.'phpseclib'.DS, true);

	\Autoloader::add_classes(array(
        'Fuel\\Core\\Agent'                         => COREPATH.'classes/agent.php',

        'Fuel\\Core\\Arr'                           => COREPATH.'classes/arr.php',

        'Fuel\\Core\\Asset'                         => COREPATH.'classes/asset.php',
        'Fuel\\Core\\Asset_Instance'                => COREPATH.'classes/asset/instance.php',

        'Fuel\\Core\\Cache'                         => COREPATH.'classes/cache.php',
        'Fuel\\Core\\CacheNotFoundException'        => COREPATH.'classes/cache/notfound.php',
        'Fuel\\Core\\CacheExpiredException'         => COREPATH.'classes/cache.php',
        'Fuel\\Core\\Cache_Handler_Driver'          => COREPATH.'classes/cache/handler/driver.php',
        'Fuel\\Core\\Cache_Handler_Json'            => COREPATH.'classes/cache/handler/json.php',
        'Fuel\\Core\\Cache_Handler_Serialized'      => COREPATH.'classes/cache/handler/serialized.php',
        'Fuel\\Core\\Cache_Handler_String'          => COREPATH.'classes/cache/handler/string.php',
        'Fuel\\Core\\Cache_Storage_Driver'          => COREPATH.'classes/cache/storage/driver.php',
        'Fuel\\Core\\Cache_Storage_Apc'             => COREPATH.'classes/cache/storage/apc.php',
        'Fuel\\Core\\Cache_Storage_File'            => COREPATH.'classes/cache/storage/file.php',
        'Fuel\\Core\\Cache_Storage_Memcached'       => COREPATH.'classes/cache/storage/memcached.php',
        'Fuel\\Core\\Cache_Storage_Redis'           => COREPATH.'classes/cache/storage/redis.php',
        'Fuel\\Core\\Cache_Storage_Xcache'          => COREPATH.'classes/cache/storage/xcache.php',

        'Fuel\\Core\\Config'                        => COREPATH.'classes/config.php',
        'Fuel\\Core\\ConfigException'               => COREPATH.'classes/config.php',
        'Fuel\\Core\\Config_Db'                     => COREPATH.'classes/config/db.php',
        'Fuel\\Core\\Config_File'                   => COREPATH.'classes/config/file.php',
        'Fuel\\Core\\Config_Ini'                    => COREPATH.'classes/config/ini.php',
        'Fuel\\Core\\Config_Json'                   => COREPATH.'classes/config/json.php',
        'Fuel\\Core\\Config_Interface'              => COREPATH.'classes/config/interface.php',
        'Fuel\\Core\\Config_Php'                    => COREPATH.'classes/config/php.php',
        'Fuel\\Core\\Config_Yml'                    => COREPATH.'classes/config/yml.php',
        'Fuel\\Core\\Config_Memcached'              => COREPATH.'classes/config/memcached.php',

        'Fuel\\Core\\Controller'                    => COREPATH.'classes/controller.php',
        'Fuel\\Core\\Controller_Rest'               => COREPATH.'classes/controller/rest.php',
        'Fuel\\Core\\Controller_Template'           => COREPATH.'classes/controller/template.php',
        'Fuel\\Core\\Controller_Hybrid'             => COREPATH.'classes/controller/hybrid.php',

        'Fuel\\Core\\Cookie'                        => COREPATH.'classes/cookie.php',

        'Fuel\\Core\\DB'                            => COREPATH.'classes/db.php',
        'Fuel\\Core\\DBUtil'                        => COREPATH.'classes/dbutil.php',

        'Fuel\\Core\\Database_Connection'           => COREPATH.'classes/database/connection.php',
        'Fuel\\Core\\Database_Exception'            => COREPATH.'classes/database/exception.php',
        'Fuel\\Core\\Database_Expression'           => COREPATH.'classes/database/expression.php',
        'Fuel\\Core\\Database_Pdo_Connection'       => COREPATH.'classes/database/pdo/connection.php',
        'Fuel\\Core\\Database_Query'                => COREPATH.'classes/database/query.php',
        'Fuel\\Core\\Database_Query_Builder'        => COREPATH.'classes/database/query/builder.php',
        'Fuel\\Core\\Database_Query_Builder_Insert' => COREPATH.'classes/database/query/builder/insert.php',
        'Fuel\\Core\\Database_Query_Builder_Delete' => COREPATH.'classes/database/query/builder/delete.php',
        'Fuel\\Core\\Database_Query_Builder_Update' => COREPATH.'classes/database/query/builder/update.php',
        'Fuel\\Core\\Database_Query_Builder_Select' => COREPATH.'classes/database/query/builder/select.php',
        'Fuel\\Core\\Database_Query_Builder_Where'  => COREPATH.'classes/database/query/builder/where.php',
        'Fuel\\Core\\Database_Query_Builder_Join'   => COREPATH.'classes/database/query/builder/join.php',
        'Fuel\\Core\\Database_Result'               => COREPATH.'classes/database/result.php',
        'Fuel\\Core\\Database_Result_Cached'        => COREPATH.'classes/database/result/cached.php',
        'Fuel\\Core\\Database_Mysql_Connection'     => COREPATH.'classes/database/mysql/connection.php',
        'Fuel\\Core\\Database_MySQL_Result'         => COREPATH.'classes/database/mysql/result.php',
        'Fuel\\Core\\Database_Mysqli_Connection'    => COREPATH.'classes/database/mysqli/connection.php',
        'Fuel\\Core\\Database_MySQLi_Result'        => COREPATH.'classes/database/mysqli/result.php',

        'Fuel\\Core\\Fuel'                          => COREPATH.'classes/fuel.php',
        'Fuel\\Core\\FuelException'                 => COREPATH.'classes/fuel.php',

        'Fuel\\Core\\Finder'                        => COREPATH.'classes/finder.php',

        'Fuel\\Core\\Date'                          => COREPATH.'classes/date.php',

        'Fuel\\Core\\Debug'                         => COREPATH.'classes/debug.php',

        'Fuel\\Core\\Cli'                           => COREPATH.'classes/cli.php',

        'Fuel\\Core\\Crypt'                         => COREPATH.'classes/crypt.php',

        'Fuel\\Core\\Event'                         => COREPATH.'classes/event.php',
        'Fuel\\Core\\Event_Instance'                => COREPATH.'classes/event/instance.php',

        'Fuel\\Core\\Error'                         => COREPATH.'classes/error.php',
        'Fuel\\Core\\PhpErrorException'             => COREPATH.'classes/error.php',

        'Fuel\\Core\\Format'                        => COREPATH.'classes/format.php',

        'Fuel\\Core\\Fieldset'                      => COREPATH.'classes/fieldset.php',
        'Fuel\\Core\\Fieldset_Field'                => COREPATH.'classes/fieldset/field.php',

        'Fuel\\Core\\File'                          => COREPATH.'classes/file.php',
        'Fuel\\Core\\FileAccessException'           => COREPATH.'classes/file.php',
        'Fuel\\Core\\OutsideAreaException'          => COREPATH.'classes/file.php',
        'Fuel\\Core\\InvalidPathException'          => COREPATH.'classes/file.php',
        'Fuel\\Core\\File_Area'                     => COREPATH.'classes/file/area.php',
        'Fuel\\Core\\File_Handler_File'             => COREPATH.'classes/file/handler/file.php',
        'Fuel\\Core\\File_Handler_Directory'        => COREPATH.'classes/file/handler/directory.php',

        'Fuel\\Core\\Form'                          => COREPATH.'classes/form.php',
        'Fuel\\Core\\Form_Instance'                 => COREPATH.'classes/form/instance.php',

        'Fuel\\Core\\Ftp'                           => COREPATH.'classes/ftp.php',
        'Fuel\\Core\\FtpConnectionException'        => COREPATH.'classes/ftp.php',
        'Fuel\\Core\\FtpFileAccessException'        => COREPATH.'classes/ftp.php',

        'Fuel\\Core\\HttpException'                 => COREPATH.'classes/httpexception.php',
        'Fuel\\Core\\HttpNoAccessException'         => COREPATH.'classes/httpexceptions.php',
        'Fuel\\Core\\HttpNotFoundException'         => COREPATH.'classes/httpexceptions.php',
        'Fuel\\Core\\HttpServerErrorException'      => COREPATH.'classes/httpexceptions.php',

        'Fuel\\Core\\Html'                          => COREPATH.'classes/html.php',

        'Fuel\\Core\\Image'                         => COREPATH.'classes/image.php',
        'Fuel\\Core\\Image_Driver'                  => COREPATH.'classes/image/driver.php',
        'Fuel\\Core\\Image_Gd'                      => COREPATH.'classes/image/gd.php',
        'Fuel\\Core\\Image_Imagemagick'             => COREPATH.'classes/image/imagemagick.php',
        'Fuel\\Core\\Image_Imagick'                 => COREPATH.'classes/image/imagick.php',

        'Fuel\\Core\\Inflector'                     => COREPATH.'classes/inflector.php',

        'Fuel\\Core\\Input'                         => COREPATH.'classes/input.php',

        'Fuel\\Core\\Lang'                          => COREPATH.'classes/lang.php',
        'Fuel\\Core\\LangException'                 => COREPATH.'classes/lang.php',
        'Fuel\\Core\\Lang_Db'                       => COREPATH.'classes/lang/db.php',
        'Fuel\\Core\\Lang_File'                     => COREPATH.'classes/lang/file.php',
        'Fuel\\Core\\Lang_Ini'                      => COREPATH.'classes/lang/ini.php',
        'Fuel\\Core\\Lang_Json'                     => COREPATH.'classes/lang/json.php',
        'Fuel\\Core\\Lang_Interface'                => COREPATH.'classes/lang/interface.php',
        'Fuel\\Core\\Lang_Php'                      => COREPATH.'classes/lang/php.php',
        'Fuel\\Core\\Lang_Yml'                      => COREPATH.'classes/lang/yml.php',

        'Fuel\\Core\\Log'                           => COREPATH.'classes/log.php',

        'Fuel\\Core\\Markdown'                      => COREPATH.'classes/markdown.php',

        'Fuel\\Core\\Migrate'                       => COREPATH.'classes/migrate.php',

        'Fuel\\Core\\Model'                         => COREPATH.'classes/model.php',
        'Fuel\\Core\\Model_Crud'                    => COREPATH.'classes/model/crud.php',

        'Fuel\\Core\\Module'                        => COREPATH.'classes/module.php',
        'Fuel\\Core\\ModuleNotFoundException'       => COREPATH.'classes/module.php',

        'Fuel\\Core\\Mongo_Db'                      => COREPATH.'classes/mongo/db.php',
        'Fuel\\Core\\Mongo_DbException'             => COREPATH.'classes/mongo/db.php',

        'Fuel\\Core\\Output'                        => COREPATH.'classes/output.php',

        'Fuel\\Core\\Package'                       => COREPATH.'classes/package.php',
        'Fuel\\Core\\PackageNotFoundException'      => COREPATH.'classes/package.php',

        'Fuel\\Core\\Pagination'                    => COREPATH.'classes/pagination.php',

        'Fuel\\Core\\Presenter'                     => COREPATH.'classes/presenter.php',

        'Fuel\\Core\\Profiler'                      => COREPATH.'classes/profiler.php',

        'Fuel\\Core\\Request'                       => COREPATH.'classes/request.php',
        'Fuel\\Core\\Request_Driver'                => COREPATH.'classes/request/driver.php',
        'Fuel\\Core\\RequestException'              => COREPATH.'classes/request/driver.php',
        'Fuel\\Core\\RequestStatusException'        => COREPATH.'classes/request/driver.php',
        'Fuel\\Core\\Request_Curl'                  => COREPATH.'classes/request/curl.php',
        'Fuel\\Core\\Request_Soap'                  => COREPATH.'classes/request/soap.php',

        'Fuel\\Core\\Redis_Db'                      => COREPATH.'classes/redis/db.php',
        'Fuel\\Core\\RedisException'                => COREPATH.'classes/redis/db.php',

        'Fuel\\Core\\Response'                      => COREPATH.'classes/response.php',

        'Fuel\\Core\\Route'                         => COREPATH.'classes/route.php',
        'Fuel\\Core\\Router'                        => COREPATH.'classes/router.php',

        'Fuel\\Core\\Sanitization'                  => COREPATH.'classes/sanitization.php',

        'Fuel\\Core\\Security'                      => COREPATH.'classes/security.php',
        'Fuel\\Core\\SecurityException'             => COREPATH.'classes/security.php',

        'Fuel\\Core\\Session'                       => COREPATH.'classes/session.php',
        'Fuel\\Core\\Session_Driver'                => COREPATH.'classes/session/driver.php',
        'Fuel\\Core\\Session_Db'                    => COREPATH.'classes/session/db.php',
        'Fuel\\Core\\Session_Cookie'                => COREPATH.'classes/session/cookie.php',
        'Fuel\\Core\\Session_File'                  => COREPATH.'classes/session/file.php',
        'Fuel\\Core\\Session_Memcached'             => COREPATH.'classes/session/memcached.php',
        'Fuel\\Core\\Session_Redis'                 => COREPATH.'classes/session/redis.php',
        'Fuel\\Core\\Session_Exception'             => COREPATH.'classes/session/exception.php',

        'Fuel\\Core\\Num'                           => COREPATH.'classes/num.php',

        'Fuel\\Core\\Str'                           => COREPATH.'classes/str.php',

        'Fuel\\Core\\TestCase'                      => COREPATH.'classes/testcase.php',

        'Fuel\\Core\\Theme'                         => COREPATH.'classes/theme.php',
        'Fuel\\Core\\ThemeException'                => COREPATH.'classes/theme.php',

        'Fuel\\Core\\Uri'                           => COREPATH.'classes/uri.php',

        'Fuel\\Core\\Unzip'                         => COREPATH.'classes/unzip.php',

        'Fuel\\Core\\Upload'                        => COREPATH.'classes/upload.php',

        'Fuel\\Core\\Validation'                    => COREPATH.'classes/validation.php',
        'Fuel\\Core\\Validation_Error'              => COREPATH.'classes/validation/error.php',

        'Fuel\\Core\\View'                          => COREPATH.'classes/view.php',
        'Fuel\\Core\\Viewmodel'                     => COREPATH.'classes/viewmodel.php',
	));
};
``` 

##### app/bootstrap.php

```php
<?php
// Bootstrap the framework DO NOT edit this
require COREPATH.'bootstrap.php';

\Autoloader::add_classes(array(
	// Add classes you want to override here
	// Example: 'View' => APPPATH.'classes/view.php',
));

// Register the autoloader
\Autoloader::register();

/**
 * Your environment.  Can be set to any of the following:
 *
 * Fuel::DEVELOPMENT
 * Fuel::TEST
 * Fuel::STAGING
 * Fuel::PRODUCTION
 */
\Fuel::$env = (isset($_SERVER['FUEL_ENV']) ? $_SERVER['FUEL_ENV'] : \Fuel::DEVELOPMENT);

// Initialize the framework with the config file.
\Fuel::init('config.php');

```