网上经常拿Yii来类比ROR,从MVC角度,使用体验及代码风格上确实有很多相似的地方。不过看配置文件发现Yii2不止是受rails的影响,同样有不少spring的影子,最明显的就是配置文件中很多IOC和AOP的体现。Yii和spring都实现了一个IOC容器来管理对象依赖关系及其生命周期。Yii2使用了Service Locator(IOC的一种实现)与DI,通过config/web.php文件配置。spring则需要配置xml文件,其中AOP配置可通过xml文件或者代码注解(需要依赖AOP框架)实现,和hibernate类似 。
IOC是很好的设计模式,程序可方便接偶,具体参照经典
IoC 容器和 Dependency Injection 模式
对于AOP的实现(这个模式在WEB应用使用场景有限),PHP传统的实现方法是采用魔术方法,通过钩子函数来注入,java则基于反射性质,推荐下面几篇文章。
CI通过下面添加钩子函数也能实现AOP,不过不如Yii原生支持得好
#config/config.php $config['enable_hooks'] = TRUE; $config['acl_pass'] = array( 'testcontroller' => array('index'=>true,'getsecret'=>false), 'welcome' => array('login'=>true) ); #config/hook.php $hook['pre_controller'] = array( 'class' => 'My_acl', 'function' => 'hook_acl', 'filename'=> 'acl.php', 'filepath' => 'hooks', 'params' => array(), ); #hooks/acl.php <?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); class My_acl extends CI_Controller{ function hook_acl() { global $RTR; $controller = $RTR->class; $method = $RTR->method; $config = & load_class('Config'); $config->load('acl_pass',true,true); $acl_settings = $config->item('acl_pass'); if(!isset($acl_settings["$controller"]) or !isset($acl_settings[$controller][$method]) or $acl_settings[$controller][$method]==false){ $haslogin = $this->session->userdata('userid'); if(!$haslogin){ show_error('Access Forbidden', 403); } } } }