让CI框架支持traits新特性

Posted SuperAvalon

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了让CI框架支持traits新特性相关的知识,希望对你有一定的参考价值。

为了对标java等编程语言的多继承特性,php官方从5.4版本起,推出了一种新的代码复用机制traits,熟悉使用traits的同学,应该都会喜欢使用它。对不不熟悉它的同学,官网解释已经很简洁了,我直接引用之:

Trait 是为类似 PHP 的单继承语言而准备的一种代码复用机制。Trait 为了减少单继承语言的限制,使开发人员能够自由地在不同层次结构内独立的类中复用 method。Trait 和 Class 组合的语义定义了一种减少复杂性的方式,避免传统多继承和 Mixin 类相关典型问题。

Trait 和 Class 相似,但仅仅旨在用细粒度和一致的方式来组合功能。 无法通过 trait 自身来实例化。它为传统继承增加了水平特性的组合;也就是说,应用的几个 Class 之间不需要继承。

详细了解可点击:

http://php.net/manual/zh/language.oop5.traits.php

CI框架目前还没有完美支持traits,代码复用大都还是通过古老的helpers,我们在编程时,类里面如果要做代码复用,大概率会选择它,但它并不够友好,破坏了类的封装美感,如果在编写helper函数时不够严谨,容易引起公共耦合,严重影响系统结构的可读性、可维护性,怎么让CI框架支持traits特性,可以自动加载它,跟我一起做吧:

一,修改system\\core\\Loader.php脚本

对CI_Loader新增两个类属性,以及一个类方法,代码如下:


class CI_Loader 

	/**
	 * List of loaded traits
	 *
	 * @var	array
	 */
	protected $_ci_traits =	array();

	/**
	 * List of paths to load traits from
	 *
	 * @var	array
	 */
	protected $_ci_trait_paths =	array(APPPATH);


	/**
	 * Traits Loader
	 *
	 * @param	string|string[]	$traits	trait name(s)
	 * @return	object
	 */
	public function traits($traits = array())
	
		is_array($traits) OR $traits = array($traits);
		foreach ($traits as &$trait)
		
			$filename = basename($trait);
			$filepath = ($filename === $trait) ? '' : substr($trait, 0, strlen($trait) - strlen($filename));
			$filename = strtolower(preg_replace('#(_trait)?(\\.php)?$#i', '', $filename));
			$trait   = $filepath.$filename;

			if (isset($this->_ci_traits[$trait]))
			
				continue;
			

			// Is this a helper extension request?
			$ext_trait = config_item('subclass_prefix').$filename;
			$ext_loaded = FALSE;
			foreach ($this->_ci_trait_paths as $path)
			
				if (file_exists($path.'traits/'.$ext_trait.'.php'))
				
					include_once($path.'traits/'.$ext_trait.'.php');
					$ext_loaded = TRUE;
				
			

			// If we have loaded extensions - check if the base one is here
			if ($ext_loaded === TRUE)
			
				$base_trait = BASEPATH.'traits/'.$trait.'.php';
				if ( ! file_exists($base_trait))
				
					show_error('Unable to load the requested file: traits/'.$trait.'.php');
				

				include_once($base_trait);
				$this->_ci_traits[$trait] = TRUE;
				log_message('info', 'Trait loaded: '.$trait);
				continue;
			

			// No extensions found ... try loading regular traits and/or overrides
			foreach ($this->_ci_trait_paths as $path)
			
				if (file_exists($path.'traits/'.$trait.'.php'))
				
					include_once($path.'traits/'.$trait.'.php');

					$this->_ci_traits[$trait] = TRUE;
					log_message('info', 'Trait loaded: '.$trait);
					break;
				
			

			// unable to load the helper
			if ( ! isset($this->_ci_traits[$trait]))
			
				show_error('Unable to load the requested file: traits/'.$trait.'.php');
			
		

		return $this;
	

 

二、新建application\\traits目录

三、编写trait类,application\\traits\\Payment_utils.php示例代码如下:

<?php
defined('BASEPATH') OR exit('No direct script access allowed');

/**
 * Payment_utils
 *
 * PHP 5.4 compatibility interface
 *
 * @package	CodeIgniter
 * @subpackage	Libraries
 * @category	Payment
 * @author	Eric <think2017@gmail.com>
 * @link	https://zhuanlan.zhihu.com/paycenter
 */
trait Payment_utils 
    
    
	/**
	 * DES加密    ECB模式
	 *
	 * @param   string    $value    明文
	 * @return  string    $ret      密文
	 */
    function encrypt($value)
    
        $td = mcrypt_module_open(MCRYPT_DES, '', MCRYPT_MODE_ECB, '');
        $iv = mcrypt_create_iv(mcrypt_enc_get_iv_size($td), MCRYPT_DEV_RANDOM);
        $key = substr(PAY_SECRET_KEY, 0, mcrypt_enc_get_key_size($td));
        mcrypt_generic_init($td, $key, $iv);
        $ret = base64_encode(mcrypt_generic($td, $value));
        mcrypt_generic_deinit($td);
        mcrypt_module_close($td);
        return $ret;
    
    
    
	/**
	 * DES解密    ECB模式
	 *
	 * @param   string    $ret      密文
	 * @return  string    $value    明文
	 */
    function decrypt($value)
    
        $td = mcrypt_module_open(MCRYPT_DES, '', MCRYPT_MODE_ECB, '');
        $iv = mcrypt_create_iv(mcrypt_enc_get_iv_size($td), MCRYPT_DEV_RANDOM);
        $key = substr(PAY_SECRET_KEY, 0, mcrypt_enc_get_key_size($td));
        mcrypt_generic_init($td, $key, $iv);
        $ret = trim(mdecrypt_generic($td, base64_decode($value))) ;
        mcrypt_generic_deinit($td);
        mcrypt_module_close($td);
        return $ret;
    

四、修改配置文件 application\\config\\autoload.php,新增以下代码:

<?php

     $autoload['traits'] = array('Payment_utils');

 

五、Testing

<?php


abstract class Wechat_driver implements PaymentHandlerInterface 
    
    use Payment_utils;
    
	protected $_config;

    //...

 

 

以上是关于让CI框架支持traits新特性的主要内容,如果未能解决你的问题,请参考以下文章

PHP 新特性:如何善用接口与Trait

面向对象第八天 -----新特性Trait

新Jenkins实践-第1章 开篇-为什么要做CI/CD?

php新特性:trait 关键字使用

PHP之Trait特性

Scala 学习之「trait 」