问题描述
我希望使用我创建的扩展版本覆盖默认的 Model \yii\base\Model
类。为了争论,可以说我在 backend\components\Model
我尝试将这两个都放在引导配置文件中,但没有任何变化 - 它继续使用旧类
Yii::$container->set('yii\base\Model','backend\components\Model');
Yii::$classMap['yii\base\Model'] = 'backend\components\Model';
在后端\模型文件中:
<?PHP
namespace backend\components;
use Yii;
use yii\base\InvalidConfigException;
use yii\base\UserException;
use yii\helpers\ArrayHelper;
class Model extends \yii\base\Model
{
/**
* Adds a new error to the specified attribute.
* @param string $attribute attribute name
* @param string $key attribute index
* @param string $error new error message
*/
public function addCustomError($attribute,$key,$error = '')
{
$this->_errors[$attribute][$key][] = $error;
}
}
'container' => [
'deFinitions' => [
'yii\base\model'=>
['class'=>'backend\components\model']
]
],
无论我做什么 - 当我创建一个新的 ActiveRecord 时,它仍然拥有相同的 yii\base\model 类。
我花了一个下午的大部分时间试图解决这个问题,并且浏览了 Yii 文档以及 StackOverflow 上已有的问题。似乎有一个反复出现的主题,即 Container 函数不起作用,人们转向 ClassMap 函数 - 但似乎两者都不起作用。
感谢您的帮助。
解决方法
如果您使用容器来实例化被覆盖的类(如 Yii::$container->get('yii\base\Model');
),则通过容器覆盖会起作用。如果你有 class MyModel extends \yii\base\Model
你没有使用容器,yii\base\Model
无论如何都会被用作基类,因为这是 PHP 的工作方式,框架无法改变它。如果您想这样做,您至少有 4 个选择:
- 首选:只需将
class MyModel extends \backend\components\Model
用于您的模型,并避免替换 hacky 类。 - Desperate 1:将
vendor/yiisoft/yii2/base/Model.php
复制到overridden/Model.php
,更改其源代码,并覆盖自动加载配置以将overridden/Model.php
用于yii\base\Model
- 添加:
要么Yii::$classMap['yii\base\Model'] = __DIR__ . '/../overridden/Model.php';
后require __DIR__ . '/../overridden/Model.php';
您需要在框架更新后将require __DIR__ . '/../vendor/autoload.php'; require __DIR__ . '/../vendor/yiisoft/yii2/Yii.php
vendor/yiisoft/yii2/base/Model.php
中的所有更改同步到您的副本。通常这应该是最后的手段,因为很容易忘记它并获得完全意外的行为。 - Desperate 2:直接使用
cweagans/composer-patches
修补vendor/yiisoft/yii2/base/Model.php
。这比第二种选择更容易维护,但一段时间后仍然可能令人惊讶。此外,在某些时候,您的补丁程序可能会在框架更新后发生冲突,需要了解正在发生的事情的人对此进行查看。 - Desperate 3:fork
yiisoft/yii2
并做任何你想做的事——它现在是你的框架。对于大型且活跃的项目,它可能非常有用,但在其他情况下,您最终可能会得到完全过时的框架,因为没人关心从上游获取更改。