Хабр Курсы для всех
РЕКЛАМА
Практикум, Хекслет, SkyPro, авторские курсы — собрали всех и попросили скидки. Осталось выбрать!
честно говоря в пример хорошо вписывается шаблон «декоратор»
миксы удобны для расширения одинаковой логики на разные объекты
< code class="php">
class Logger
{
protected $crud;
function __construct(MyCRUD $o)
{
$this->crud = $o; // ничего хитрого,запоминаем объект который декорируем
}
function save()
{
$this->addToLog(); // сохраняем данные
$this->crud->save(); //и запускаем родной метод
}
function __call($method,$args)
{
call_user_func_array(array($this->crud,$method),$args); //собственно проксируем вызовы
}
}
//пример юзания
$data = new MyCRUD();
$data->setField(42);
$data->save(); //сохранили без записи в логе
$log = new Logger($data);
$log->setField(100500);
$log->save(); //а вот теперь данные упадут в лог
< /code>В серьезном, не учебном проекте следует использовать только ту технику, которая вам наиболее знакома и привычна в профессиональном плане (или ту, которая наиболее знакома и привычна большинству программистов, которые в будущем будут работать над проектом)Эх, как же хочется, чтобы побольше людей так считало. Разумеется, это касается не только mixin'ов.
public function behaviors() {
return array(
'CTimestampBehavior' => array(
'class' => 'zii.behaviors.CTimestampBehavior',
'createAttribute' => 'createDate',
'updateAttribute' => 'updateDate',
'setUpdateOnCreate' => true,
),
);
}class CTimestampBehavior extends CActiveRecordBehavior {
// много кода
public function beforeSave($event) {
if ($this->getOwner()->getIsNewRecord() && ($this->createAttribute !== null)) {
$this->getOwner()->{$this->createAttribute} = $this->getTimestampByAttribute($this->createAttribute);
}
if ((!$this->getOwner()->getIsNewRecord() || $this->setUpdateOnCreate) && ($this->updateAttribute !== null)) {
$this->getOwner()->{$this->updateAttribute} = $this->getTimestampByAttribute($this->updateAttribute);
}
}
// много кода, где на основе модели вычисляется, какой таймстемп отдать
}
class Mixin1 {
public function doSomething1() {}
}
class Mixin2 {
public function doSomething2() {}
}
class Aggregator {
private $mixins = array();
function __construct() {
$this->mixins[] = new Mixin1();
$this->mixins[] = new Mixin2();
}
public function __call( $method, $params ) {
$result = null;
for( $q = 0; $q < count($this->mixins); $q++ )
{
if( method_exists( $this->mixin ) )
{
// находим первого делегата, отдаем ему полномочия и завершаем выполнение метода
$result = call_user_func_array( array( $this->mixins[$q], $method), $params );
break;
}
}
return $result;
}
}
$a = new AggregatorMixed ();
$a->doSomething();
Не важно ведь как Вы их добавляете, важно как оно работает. А принцип работы у обоих подходов один — передача полномочий
class Mixin1 {
public function doSomething1() { echo "1\n"; }
}
class Mixin2 {
public function doSomething2() { echo "2\n"; }
public static function doStatic() { echo "static\n"; }
}
class Aggregator {
private $mixins = array();
private static $staticMixins = array();
function __construct() {
$this->mixins[] = new Mixin1();
$this->mixins[] = new Mixin2();
self::$staticMixins[] = 'Mixin2';
}
public function __call( $method, $params ) {
$result = null;
for( $q = 0; $q < count($this->mixins); $q++ )
{
if( method_exists( $this->mixins[$q], $method ) )
{
// находим первого делегата, отдаем ему полномочия и завершаем выполнение метода
$result = call_user_func_array( array( $this->mixins[$q], $method), $params );
break;
}
}
return $result;
}
public static function __callStatic( $method, $params) {
$result = null;
for ($i = 0, $s = sizeof( self::$staticMixins); $i < $s; $i++) {
$class = self::$staticMixins[$i];
if (method_exists( $class, $method)) {
$result = call_user_func_array(
array( $class, $method),
$params
);
break;
}
}
return $result;
}
}
$a = new Aggregator();
$a->doSomething1();
$a->doSomething2();
Aggregator::doStatic();
Примеси VS делегирование: преимущества и недостатки при реализации «плагинов»