Such a solution should meet some requirements:
1. It should not alter framework files
2. It should be easy to upgrade to another Yii version
To solve this, i used this approach:
1. Override CHtml
CHtml is a core class which gets autoloaded by Yii. So in order to prevent Yii from using its own class, i just have to load my custom CHtml class before Yii does. Fortunately this is very simple and Yii even provides a way how to do is. The key is to add your custom class to the import configuration:
<?php
'import'=>array(
'application.components.CHtml',
...
So now you can have your custom CHtml class in components/CHtml.php. So far so good. But ...
2. Inherit from original CHtml
I don't want to copy the original CHtml.php from Yii and alter it. I would have to do the same changes again, each time a new version is released and it's very likely that i miss to redo some of my changes. So i want some kind of inheritance. My first idea was to use namespaces inside components/CHtml.php like this:
<?php
/* BELOW CODE DOES NOT WORK: */
// Load CHtml into yii namespace to have it under yii\Chtml
namespace yii {
include(Yii::getPathOfAlias('system.web.helpers.CHtml').'.php');
}
// Create CHtml in global namespace
namespace yii {
class CHtml extends yii\CHtml { /* override things here */ }
}
But this does not work! When you include a file from inside a namespace, PHP will not use the same namespace for the included file. Or to put it in other words: Every PHP file must define its own namespace. If it does not, then it will always be importet to the global namespace. Yii's files do not declare a namespace, so every code inside them will be in the global namespace as soon as you include it.
So i ended up with an acceptable workaround to reach my above goals. The pattern goes like this:
<?php
namespace yii {
use \Yii as Yii; // Required for every core class used inside the code below
class CHtml
{
/* copy the original CHtml code here. If Yii gets upgraded, replace the code in here */
}
}
namespace {
class CHtml extends yii\CHtml
{
/* override CHtml methods here */
}
}The solution is not perfect, but at least it works and still i can upgrade without too much fuss.
If someone has a better idea for how to solve (2) i'm glad to hear it. Maybe we can find the perfect pattern and have a nice wiki article for it.

Help















