通过配置的方式重写某个Yii2 文件 或第三方扩展文件

技巧库 · fecommerce · 于 1年前 发布 · 1333 次阅读

介绍一种比较好的用Yii2 classMap的方式重写的方法

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文件的前提下,重写任何文件了

FancyEcommerce.com 原文链接: 通过配置的方式重写某个Yii2 文件 或第三方扩展文件

下面是代码举例说明的详细步骤:

下面是我写的一个类,内容如下:

<?php
/**
 * FecShop file.
 *
 * [@link](/member/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';
  }
  
}

  1. 然后我在controller中对这个类的静态方法进行了调用:
<?php
/**
 * FecShop file.
 *
 * [@link](/member/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](/member/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](/member/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 ,这样会报错的。

  1. 我添加Yii::classMap 数组的值的新的My类的文件路径

Yii::$classMap['fecshop\app\appfront\helper\test\My'] = ['@appfront/helper/My.php'];

然后调用后,发现调用的是新的My类。

  1. 需要注意的是,新的类的名字必须和之前的类的名字一样,否则会出错,另外,namespace要一致,一样。

  2. 我们希望通过配置文件的方式,这样比较方面,我们可以这样做。

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 ,这里不多写了。


微信

本帖已被设为精华帖!
共收到 6 条回复 Yii2 重写
fecommerce#110个月前 0 个赞

最后,推荐一下我的Fecshop ,开源商城,github地址:https://github.com/fancyecommerce/yii2_fecshop

演示地址:http://fecshop.appfront.fancyecommerce.com/

截止到2016-11-12号,产品,分类,首页,评论,用户中心,搜索,多语言,多货币 等功能已经做完,除了购物车和支付部分,其他的基本都已经完成,关注fecshop的 在等2-3个月,也就是明年2,3月份,版本已经就可以出来,2017年4,5月份在把手机web 做一下,预计到明年5月份,后台,pc前台,手机web前台 ,命令控制台 这几个入口 基本可以完善,多谢大家关注和你们的Star,谢谢,我会坚持把他写好。

作者QQ:2358269014

forecho#210个月前 0 个赞

@fecommerce #1楼 可以单独开一篇帖子介绍 Fecshop

fecommerce#310个月前 0 个赞

@forecho #2楼 恩,pc端小雏形出来了,还需要1-2个月完善pc端功能,还有文档,做好后在做手机web端页面。

xjdata#410个月前 0 个赞

额...... 麻烦代码高亮部分的css换一个吧. 现在的太暗了,暗的都需要仔细盯着看了.

图片

forecho#510个月前 0 个赞

@xjdata #4楼 已经处理了 :smile:

xjdata#610个月前 0 个赞

@forecho #5楼 多谢,现在分明多了.

添加回复 (需要登录)
需要 登录 后方可回复, 如果你还没有账号请点击这里 注册