您的位置:首页 > 其它

kohana分析之主程序加载流程

2016-04-18 20:51 337 查看
本文是要切入kohana的内部,分析其启动过程:

1.index.php

单一入口主文件,基本上是设置模块路径,全局变量等.如错误信息,系统模块路径,网站目录等.

其他工作转给 require SYSPATH.'core/Bootstrap'.EXT;完成。

值得提的是,如果我们想捕获整个程序的异常,那可以把他改成:

try{

     require SYSPATH.'core/Bootstrap'.EXT;

}catch($e){

     //处理错误,提示有好页面等等

}

 

 

2.Bootstrap.php

这个类用来加载一些必须的类库,初始化启动信息后,完成执行过程。并且记录部分流程的执行时间信息。

// Load benchmarking support

//这个类就是用于记录某个历程执行的时间,消耗的内存信息

require SYSPATH.'core/Benchmark'.EXT;

// Start total_execution 记录总执行时间

Benchmark::start(SYSTEM_BENCHMARK.'_total_execution');

// Start kohana_loading  记录加载类的时间

Benchmark::start(SYSTEM_BENCHMARK.'_kohana_loading');

// Load core files

require SYSPATH.'core/utf8'.EXT;

//event是在自己定义的一个事件里注册一些方法,一个事件可以叠加多个不同处理方法,然后通过Event::run来调用定义的事件

require SYSPATH.'core/Event'.EXT;

require SYSPATH.'core/Kohana'.EXT;

// Prepare the environment

Kohana::setup();  //初始化启动

// End kohana_loading  //停止记录

Benchmark::stop(SYSTEM_BENCHMARK.'_kohana_loading');

// Start system_initialization

Benchmark::start(SYSTEM_BENCHMARK.'_system_initialization');

// Prepare the system

Event::run('system.ready');//如果有,则执行ready事件

// Determine routing

Event::run('system.routing');//执行路由事件

// End system_initialization

Benchmark::stop(SYSTEM_BENCHMARK.'_system_initialization');

// Make the magic happen!

Event::run('system.execute');//执行主代码过程

// Clean up and exit

Event::run('system.shutdown');//执行完毕后的处理操作

 

3.konana类,这是核心类,php执行核心操作都在此定义,在此完成初始化

 

Kohana::setup()

public static function setup()

 {

  static $run;

  // This function can only be run once

  if ($run === TRUE)

   return;

  // Start the environment setup benchmark

  Benchmark::start(SYSTEM_BENCHMARK.'_environment_setup');

  // Define Kohana error constant

  define('E_KOHANA', 42);

  // Define 404 error constant

  define('E_PAGE_NOT_FOUND', 43);

  // Define database error constant

  define('E_DATABASE_ERROR', 44);

  //缓存内部信息,包括所有配置文件数组(省去每次都要读文件),用到的类的所在路径(省去每次都要查找)

  if (self::$cache_lifetime = self::config('core.internal_cache'))

  {

   // Are we using encryption for caches?

   self::$internal_cache_encrypt = self::config('core.internal_cache_encrypt');

   

   if(self::$internal_cache_encrypt===TRUE)

   {

    self::$internal_cache_key = self::config('core.internal_cache_key');

    

    // Be sure the key is of acceptable length for the mcrypt algorithm used

    self::$internal_cache_key = substr(self::$internal_cache_key, 0, 24);

   }

   

   // Set the directory to be used for the internal cache

   if ( ! self::$internal_cache_path = self::config('core.internal_cache_path'))

   {

    self::$internal_cache_path = APPPATH.'cache/';

   }

   // Load cached configuration and language files

   self::$internal_cache['configuration'] = self::cache('configuration', self::$cache_lifetime);

   self::$internal_cache['language']      = self::cache('language', self::$cache_lifetime);

   // Load cached file paths

   self::$internal_cache['find_file_paths'] = self::cache('find_file_paths', self::$cache_lifetime);

   // Enable cache saving

   Event::add('system.shutdown', array(__CLASS__, 'internal_cache_save'));

  }

  // Disable notices and "strict" errors

  $ER = error_reporting(~E_NOTICE & ~E_STRICT);

  // Set the user agent

  self::$user_agent = ( ! empty($_SERVER['HTTP_USER_AGENT']) ? trim($_SERVER['HTTP_USER_AGENT']) : '');

  if (function_exists('date_default_timezone_set'))

  {

   $timezone = self::config('locale.timezone');

   // Set default timezone, due to increased validation of date settings

   // which cause massive amounts of E_NOTICEs to be generated in PHP 5.2+

   date_default_timezone_set(empty($timezone) ? date_default_timezone_get() : $timezone);

  }

  // Restore error reporting

  error_reporting($ER);//指定错误级别

  // Start output buffering

  //设置缓冲输出,加速总输出速度

  ob_start(array(__CLASS__, 'output_buffer'));

  // Save buffering level

  //记录缓冲等级,便于控制缓存,清除的时候可以定位到哪个级别

  self::$buffer_level = ob_get_level();

  // Set autoloader

  //自动加载类的方法,在include不存在的类的时候,调用这个方法查找,找不到则抛出异常

  spl_autoload_register(array('Kohana', 'auto_load'));

  // Set error handler

  //自定义错误函数

  set_error_handler(array('Kohana', 'exception_handler'));

  // Set exception handler

  //自定义异常处理函数

  set_exception_handler(array('Kohana', 'exception_handler'));

  // Send default text/html UTF-8 header

  header('Content-Type: text/html; charset=UTF-8');

  // Load locales

  //获取设置的语言种类,array类型

  $locales = self::config('locale.language');

  // Make first locale UTF-8

  $locales[0] .= '.UTF-8';

  // Set locale information

  //设置默认为第一种

  self::$locale = setlocale(LC_ALL, $locales);

  //日志记录级别如果>0则表示记录日志,1,2,3等级分别会记录不同范围的日志

  if (self::$configuration['core']['log_threshold'] > 0)

  {

   // Set the log directory

   self::log_directory(self::$configuration['core']['log_directory']);

   // Enable log writing at shutdown

   //在程序结束的时候,把内存中的$log一次性保存

   register_shutdown_function(array(__CLASS__, 'log_save'));

  }

  //下面均是注册事件处理函数

  // Enable Kohana routing

  //分析出请求字符串如http://localhost:82/index.php/sy/pdtdetail/id/5/c/1

  //则得到sy/pdtdetail/id/5/c/1

  //find_uri 分不同模式下的处理操作

  Event::add('system.routing', array('Router', 'find_uri'));

  //此方法主要是获取controll和method,并调用System.post_routing 钩子,此钩子在用户类实例化前被执行

  Event::add('system.routing', array('Router', 'setup'));

  // Enable Kohana controller initialization

  Event::add('system.execute', array('Kohana', 'instance'));

  // Enable Kohana 404 pages

  Event::add('system.404', array('Kohana', 'show_404'));

  // Enable Kohana output handling

  Event::add('system.shutdown', array('Kohana', 'shutdown'));

  //如果开启,那加载自定义事件处理函数

  if (self::config('core.enable_hooks') === TRUE)

  {

   // Find all the hook files

   //找到所有定义事件的文件

   $hooks = self::list_files('hooks', TRUE);

   foreach ($hooks as $file)

   {

    // Load the hook

    //直接把内容包含进来

    include $file;

   }

  }

  // Setup is complete, prevent it from being run again

  $run = TRUE;//确保只执行一次

  // Stop the environment setup routine

  Benchmark::stop(SYSTEM_BENCHMARK.'_environment_setup');

 }

 

回到Bootstap.php

 

 剩下的就是Event.run了,调用各个处理程序,这些函数的注册过程参见kohana::setup();

 

// Prepare the system

// 如果有,则执行ready事件,默认为空,我们可以同过hook来注册函数

Event::run('system.ready');

// Determine routing

Event::run('system.routing');//执行路由事件

// End system_initialization

Benchmark::stop(SYSTEM_BENCHMARK.'_system_initialization');

// Make the magic happen!

Event::run('system.execute');//执行主代码过程

// Clean up and exit

Event::run('system.shutdown');//执行完毕后的处理操作

 

 'system.routing'对应的注册方法有2个:Router.find_uri,Router.setup,作用在Kohana.setup里已经介绍过了,这里重点介绍

system.execute对应的函数是Kohana.instance,此方法的任务是创建唯一的控制器对象,调用控制器的方法,中间会调用一些钩子时间,方便我们想在某个环节做一些处理,还做了方法的私有化判断。

 

public static function & instance()

 {

  //确保只实例化一次controller

  if (self::$instance === NULL)

  {

   Benchmark::start(SYSTEM_BENCHMARK.'_controller_setup');

   // Include the Controller file

   require Router::$controller_path;

   //包含contrller的源文件

   try

   {

    // Start validation of the controller

    //用此类来初始化controller的好处是可以知道该类定义的方法和属性等信息

    $class = new ReflectionClass(ucfirst(Router::$controller).'_Controller');

   }

   catch (ReflectionException $e)

   {

    // Controller does not exist

    Event::run('system.404');

   }

   if ($class->isAbstract() OR (IN_PRODUCTION AND $class->getConstant('ALLOW_PRODUCTION') == FALSE))

   {

    // Controller is not allowed to run in production

    Event::run('system.404');

   }

   // Run system.pre_controller

   //创建构造函数前的钩子

   Event::run('system.pre_controller');

   // Create a new controller instance

   //实例化controller

   $controller = $class->newInstance();

   // Controller constructor has been executed

   //实例建立完毕后,但未调用方法状态,调用钩子

   Event::run('system.post_controller_constructor');

   try

   {

    // Load the controller method

    //判断是否有该方法

    $method = $class->getMethod(Router::$method);

    // Method exists

    //这里Konhan把 _ 开头的方法视为私有方法

    if (Router::$method[0] === '_')

    {

     // Do not allow access to hidden methods

     Event::run('system.404');

    }

    //判断方法本身是否有限制

    if ($method->isProtected() or $method->isPrivate())

    {

     // Do not attempt to invoke protected methods

     throw new ReflectionException('protected controller method');

    }

    // Default arguments

    $arguments = Router::$arguments;

   }

   catch (ReflectionException $e)

   {

    // Use __call instead

    $method = $class->getMethod('__call');

    // Use arguments in __call format

    $arguments = array(Router::$method, Router::$arguments);

   }

   // Stop the controller setup benchmark

   Benchmark::stop(SYSTEM_BENCHMARK.'_controller_setup');

   // Start the controller execution benchmark

   Benchmark::start(SYSTEM_BENCHMARK.'_controller_execution');

   // Execute the controller method

   //这里开始执行控制器的方法了

   $method->invokeArgs($controller, $arguments);

   // Controller method has been executed

   //执行后的事件钩子

   Event::run('system.post_controller');

   // Stop the controller execution benchmark

   Benchmark::stop(SYSTEM_BENCHMARK.'_controller_execution');

  }

  //返回唯一的实例

  return self::$instance;

 }

回到Bootsarp.php,之后执行的是Event::run('system.shutdown');调用的是Kohana.shutdown,做一些清理工作:刷新缓冲,再把缓冲里面的数据进行全局替换.

 

public static function shutdown()

 {

  // Close output buffers

  //把缓冲里的数据写到self::$output里面

  self::close_buffers(TRUE);

  // Run the output event

  //调用处理输出缓冲的事件

  Event::run('system.display', self::$output);

  // Render the final output

  //全部变量替换,压缩处理

  self::render(self::$output);

 }

 

ob函数是php内部缓冲处理模块:

function out($a){

 global $html;

 $html = '<div style="color:red">'.$a.'</div>';//file_put_contents('c:/2.txt',$a);die;

 return $html;

}

//开启缓冲,并且设置缓冲函数为out

ob_start('out');

 

 

未完待续
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: