1.我需要重写某个Yii的类方法,譬如:yii\helpers\ArrayHelper
我需要新建一个类,继承,然后覆盖这个类的方法。
如果我的系统都成型了,然后我在调用这个类的地方,需要将
use yii\helpers\ArrayHelper
改成
use xxxxxx\yii\helpers\ArrayHelper
2.现在用classMap
Yii::$classMap['yii\helpers\ArrayHelper'] = '@xxxxxx/yii/helpers/ArrayHelper.php';
直接就行了,对yii的文件不需要改动,调用的地方也不用改动。
可能是我在做fecshop考虑重写的事情,看到这个,真的豁然开朗的感觉,
这样可以在不改动yii2文件,和不改动我的fecshop文件的前提下,重写任何文件了
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
下面是代码举例说明的详细步骤:
- 下面是我写的一个类,内容如下:
<?php /** * FecShop file. * * @link http://www.fecshop.com/ * @copyright Copyright (c) 2016 FecShop Software LLC * @license http://www.fecshop.com/license/ */ namespace fecshop\app\appfront\helper\test; use Yii; use fec\helpers\CConfig; use fec\controllers\FecController; use yii\base\InvalidValueException; /** * @author Terry Zhao <2358269014@qq.com> * @since 1.0 */ class My { public static function test(){ echo 'this is my first test php file'; } }
2. 然后我在controller中对这个类的静态方法进行了调用:
<?php /** * FecShop file. * * @link http://www.fecshop.com/ * @copyright Copyright (c) 2016 FecShop Software LLC * @license http://www.fecshop.com/license/ */ namespace fecshop\app\appfront\modules\Customer\controllers; use Yii; use fec\helpers\CModule; use fec\helpers\CRequest; use fecshop\app\appfront\modules\AppfrontController; use fecshop\app\appfront\helper\test\My; /** * @author Terry Zhao <2358269014@qq.com> * @since 1.0 */ class AccountController extends AppfrontController { public function actionLogin() { My::test(); exit; } }
然后我在很多地方对My::test进行了调用,然后我想对这个My类的test的内容进行重写,但是前提是My这个文件是库包文件,我不能直接进行修改,否则,以后的升级会出现问题,那么我需要用一个类继承这个My类,然后重写test()方法,然后在各个调用My::test()的地方修改use部分,改成新的类的namespaces,这种方式的坏处是修改量大,对于维护起来很费劲,下面介绍另外一种方法,通过在Yii::classMap中配置:
Yii::$classMap['yii\helpers\ArrayHelper'] = '@app/components/ArrayHelper.php';
官网部分的介绍为:
http://www.yiiframework.com/doc-2.0/guide-helper-overview.html#customizing-helper-classes
下面是代码步骤:
1.原来的类的内容为:
<?php /** * FecShop file. * * @link http://www.fecshop.com/ * @copyright Copyright (c) 2016 FecShop Software LLC * @license http://www.fecshop.com/license/ */ namespace fecshop\app\appfront\helper\test; use Yii; use fec\helpers\CConfig; use fec\controllers\FecController; use yii\base\InvalidValueException; /** * @author Terry Zhao <2358269014@qq.com> * @since 1.0 */ class My { public static function test(){ echo 'this is my first test php file'; } }
2.我写一个新类: 文件路径为: appfront/helper/My.php ,我想让controller调用的类为下面的类
<?php /** * FecShop file. * * @link http://www.fecshop.com/ * @copyright Copyright (c) 2016 FecShop Software LLC * @license http://www.fecshop.com/license/ */ namespace fecshop\app\appfront\helper\test; use Yii; use fec\helpers\CConfig; use fec\controllers\FecController; use yii\base\InvalidValueException; /** * @author Terry Zhao <2358269014@qq.com> * @since 1.0 */ class My{ public static function test(){ echo 'this is my appfront test php file'; } }
注意:namespace和上面的那个My类的要一样,而不是按照 appfront/helper/My.php 写成 namespace appfront\helper ,这样会报错的。
3. 我添加Yii::classMap 数组的值的新的My类的文件路径
Yii::$classMap['fecshop\app\appfront\helper\test\My'] = ['@appfront/helper/My.php'];
然后调用后,发现调用的是新的My类。
4. 需要注意的是,新的类的名字必须和之前的类的名字一样,否则会出错,另外,namespace要一致,一样。
5. 我们希望通过配置文件的方式,这样比较方面,我们可以这样做。
5.1 在app/config/下面添加文件 YiiClassMap.php ,内容如下:
<?php return [ 'fecshop\app\appfront\helper\test\My' => '@appfront/helper/My.php', ];
在web/index.php的代码
$application = new yii\web\Application($config); 上面添加代码:
/** * yii class Map Custom * */ $yiiClassMap = require(__DIR__ . '/../config/YiiClassMap.php'); if(is_array($yiiClassMap) && !empty($yiiClassMap)){ foreach($yiiClassMap as $namespace => $filePath){ Yii::$classMap[$namespace] = $filePath; } }
这样,通过上面的配置文件,就可以把classMap执行了,以后如果添加classMap,直接在文件
app/config/YiiClassMap.php 文件里面的数组中添加一条数据就可以了。
您也可以把yii2的库包文件,yii2的某个扩展库包里面的几个文件,通过这种方式进行重写。这个是非常非常非常方便的,尤其对于你写了一个扩展,让大家用,你的扩展需要升级,因此别人不能直接动你的库包文件,不然升级后,修改的会被覆盖,通过这种方式就可以解决这个问题。
总之,这个功能是更好的进行文件重写。
对于Yii2的自动加载的原理,可以参看:http://www.digpage.com/autoload.html,这里不多写了。