Страница 5 из 6

Re: WithRelatedBehavior

Добавлено: 2012.11.18, 12:33
mlapko
Код теста абстрактный, но передаёт смысл

Код: Выделить всё

class FooBehavior
{
    public function events()
    {
        return array(
            'onAfterConstruct'=>'afterConstruct',
            'onBeforeValidate'=>'beforeValidate',
            'onAfterValidate'=>'afterValidate',
            'onBeforeSave'=>'beforeSave',
            'onAfterSave'=>'afterSave',
            'onBeforeDelete'=>'beforeDelete',
            'onAfterDelete'=>'afterDelete',
            'onBeforeFind'=>'beforeFind',
            'onAfterFind'=>'afterFind',
        );
    }
    
    protected function afterConstruct($event) {}

    protected function beforeValidate($event) {}

    protected function afterValidate($event) {}
    
    protected function beforeSave($event) {}

    protected function afterSave($event) {}

    protected function beforeDelete($event) {}

    protected function afterDelete($event) {}

    protected function beforeFind($event) {}

    protected function afterFind($event) {}
    
    public function attach()
    {
        $class = new ReflectionClass($this);
        foreach ($this->events() as $event => $handler) {
            if (!$class->getMethod($handler)->isProtected())
                echo $handler;
        }
    }    
}

class EmptyBehavior extends FooBehavior
{
    public function events() { return array(); }
}

class GeneralBehavior extends FooBehavior {}

// EmptyBehavior
$start = microtime(true);
for ($i = 0; $i < 1000; ++$i) {
    $object = new EmptyBehavior();
    $object->attach();
}
echo microtime(true) - $start, '<br/>';
// GeneralBehavior
$start = microtime(true);
for ($i = 0; $i < 1000; ++$i) {
    $object = new GeneralBehavior();
    $object->attach();
}
echo microtime(true) - $start;
 

Re: WithRelatedBehavior

Добавлено: 2012.11.18, 16:04
creocoder
Это только аттач. При реальной вставке/чтении записей время, которое будет затрачено на аттач станет незначительным. На трекере проводились реальные практические тесты. Таким образом незначительная потеря в скорости в общей картине при аттаче (за возможность не думать о перекрытии events()) это вполне допустимо.

Re: WithRelatedBehavior

Добавлено: 2012.11.18, 20:58
slavcodev
creocoder писал(а):
creocoder, отнаследуйтесь от CBehavior, повысит производительность, в вашем behavior'е CActiveRecordBehavior не нужен.
Во первых это было бы идеологически неправильно, во вторых в версии 1.1.13 появится мой и mc-bear фикс расхода памяти поведениями. Поэтому уже не актуально.
Что это за идеология такая? Мне кажется тебя запутали названия классов. Но нет ничего запрещающего использовать cbehavior с активными записями. учитывая что не юзается ни одно стандартное событие.

Re: WithRelatedBehavior

Добавлено: 2012.11.19, 16:53
creocoder
Что это за идеология такая? Мне кажется тебя запутали названия классов. Но нет ничего запрещающего использовать cbehavior с активными записями. учитывая что не юзается ни одно стандартное событие.
Сегодня не юзается, завтра юзается. ИМХО все поведения которые работают с AR должны наследовать CActiveRecordBehavior. Отсутствие событий это НЕ КРИТЕРИЙ делать у класса другого родителя. Тем более в целях какой то экономии на спичках. А после фикса это вообще уже не актуально.

Re: WithRelatedBehavior

Добавлено: 2012.11.19, 17:03
slavcodev
creocoder писал(а):Сегодня не юзается, завтра юзается. ИМХО все поведения которые работают с AR должны наследовать CActiveRecordBehavior
Да ладно. Откуда такие выводы? Только потому что у СActiveRecord и CActiveRecordBehavior есть приставка у класса? Что помешает конкретно этому поведению, когда завтра будет юзатся ивенты, поменять родителя? Да и когда появится завтра другая логика, то и поведение будет уже другое.

ЗЫ: Я предпочитаю не назвать то что сделали с поведениями фиксом, скорее это хак. Для меня фикс - это когда проблему убирают, в данном случае просто придумали как ее обойти :)

Re: WithRelatedBehavior

Добавлено: 2012.11.19, 17:08
creocoder
Но нет ничего запрещающего использовать cbehavior с активными записями.
И что? Нет ничего запрещающего делать ещё много нехороших с точки зрения ООП вещей в Yii. С Zend философией я уверен, что юзер пытающийся так сделать получал бы exception с трехэтажным матом. Но у нас не Zend, совершенно другая философия по поводу обработки ошибок. Поэтому всё на совести разработчиков расширений и конечных пользователей. Но иногда, вот от таких предложений "сэкономить на спичках" я жалею, что у нас такая политика обработки ошибок.
Я предпочитаю не назвать то что сделали с поведениями фиксом, скорее это хак. Для меня фикс - это когда проблему убирают, в данном случае просто придумали как ее обойти
Проблему именно устранили, а не обошли.

Re: WithRelatedBehavior

Добавлено: 2013.01.05, 19:02
karpo518
creocoder Спасибо вам за расширение. С ним код обработки сложных форм сократился до приятного размера. Скажите, не планируете ли вы добавить в поведение подобный метод для инициализации? Было бы здорово передавать модели один массив для инициализации её и связанных моделей. Особенно изящно это решение может использоваться при обработке вложенных форм.

Re: WithRelatedBehavior

Добавлено: 2013.02.03, 19:56
saygo
Хороший Behavior, как раз искал нечто подобное, часть задачи решил. Теперь другая часть, может поможете.

Есть
Users{
contract_id (PK)
.............
}

и Ip{
id (PK)
user_id (contract_id из предыдущей таблицы)
ip
}

У одного юзера может быть несколько Ip (минимум 1)
в users _form добавил
$ips=CHtml::listData(Ip::model()->findAll('user_id=:user_id', array(':user_id' => $model->contract_id)), 'id', 'ip');
foreach($ips as $i=>$ip)
{
echo CHtml::TextField('ip['.$i.']',$ip);
}
echo CHtml::TextField('ip['.$i.']','');
Что выводит инпуты с существующими IP + 1 поле, если нужно добавить еще

Подскажите, что нужно поменять, чтобы на этих инпутах работала валидация из Ip (регулярка по правильности + unique(это между собой не обязательно, визуально видно дубликат при 1-3 IP)).
Правильно сформировать массив $_POST, который использовать потом в контроллере вместо

$ip1 = new Ip;
$ip1->ip = "192.168....";
$ip1->user_id = $model->contract_id;

$model->ip = array($ip1,$ip2....);

Re: WithRelatedBehavior

Добавлено: 2013.02.12, 23:36
alexanoid
непонятно, при помощи этого расширения можно делать только save новой модели или можно также сделать и update. Если да - то как ? Спасибо.

Re: WithRelatedBehavior

Добавлено: 2013.02.12, 23:47
slavcodev
а разве update это не частный случай save? ты вызываешь update? смысл?

Re: WithRelatedBehavior

Добавлено: 2013.02.13, 00:00
alexanoid
mc-bear писал(а):а разве update это не частный случай save? ты вызываешь update? смысл?
смысл в том, что я Java программист и например в одном из джавишных ORM под названием Hibernate используется три метода - save, update and saveOrUpdate()

По старой привычке я стал искать аналоги здесь и не нашел. Отсюда и возник данный вопрос.

Re: WithRelatedBehavior

Добавлено: 2013.02.13, 00:56
slavcodev
Если подсмотреть в API метода save, можно увидеть что фреймворк автоматически сделает insert для новых записей и update для старых. Поэтому insert и update редко используется по каким-то слишком частным задачам.

Re: WithRelatedBehavior

Добавлено: 2013.02.13, 01:46
alexanoid
mc-bear писал(а):Если подсмотреть в API метода save, можно увидеть что фреймворк автоматически сделает insert для новых записей и update для старых. Поэтому insert и update редко используется по каким-то слишком частным задачам.
а в чем была трудность реализовать базовый сценарий с удалением из базы данных отсутствующих потомков в модели при ее апдейте ? Зачем эту рутину на программиста перекладывать ? Фактически теперь приходится писать каждый раз код для этого в beforeSave..

Re: WithRelatedBehavior

Добавлено: 2013.02.13, 01:49
alexanoid
alexanoid писал(а):
mc-bear писал(а):Если подсмотреть в API метода save, можно увидеть что фреймворк автоматически сделает insert для новых записей и update для старых. Поэтому insert и update редко используется по каким-то слишком частным задачам.
а в чем была трудность реализовать базовый сценарий с удалением из базы данных отсутствующих потомков в модели при ее апдейте ? Зачем эту рутину на программиста перекладывать ? Фактически теперь приходится писать каждый раз код для этого в beforeSave..
либо в таком случае можно было добавить дополнительным параметром сценарий требуемого поведения в метод save

Re: WithRelatedBehavior

Добавлено: 2013.04.10, 14:04
XAKEPEHOK
Похоже, что я где-то туплю, но не могу понять где. Есть 2 модели: Users и Advertisers, где Users HAS_ONE Advertisers, и соответственно, Advertisers BELONGS_TO Users

Код: Выделить всё

<?php
/**
 * @property integer $userID
 * ...
 * The followings are the available model relations:
 * @property Users $user
 */
class Users extends CActiveRecord
{
  //... подключаю поведение

  public function relations()
  {
    return array(
      'advertiser' => array(self::HAS_ONE, 'Advertisers', 'userID'),
    );
  }
}

Код: Выделить всё

<?php
/**
 * @property integer $id
 * ...
 * The followings are the available model relations:
 * @property Advertisers $advertiser
 */
class Advertisers extends CActiveRecord
{
  //... подключаю поведение

  public function relations()
  {
    return array(
      'user' => array(self::BELONGS_TO, 'Users', 'userID'),
    );
  }
}
В действии контроллера

Код: Выделить всё

    $user = new Users('fromRequest');
    $user->email = $advRequest->email;
    $user->login = substr($advRequest->email,0,strpos($advRequest->email,'@'));
    ...

    $user->advertiser = new Advertisers();
    $user->advertiser->name = $advRequest->name;
    $user->advertiser->phone = $advRequest->phone;    
    ...

    $user->withRelated->save(true,array('advertiser'));
В общем, при попытке сохранить получаю: Не определено свойство "Users.userID". - связи вроде указаны правильно. Ни в событиях моделей, ни в контроллере обращений к Users.userID нет.
Вылетает следующий exception:
C:\WebServer\domains\onelead\protected\extensions\wr\WithRelatedBehavior.php(239): CActiveRecord->__get("userID")

Код: Выделить всё

234         switch($relationClass)
235         {
236           case CActiveRecord::HAS_ONE:
237             $map = $this->getDependencyAttributes($fks, $ownerTableSchema, $relatedTableSchema);
238             foreach ($map as $fk => $pk) {
239               $related->$fk = $owner->$pk; // <<--- выделена эта срока
240             }
241 
242             if($data===null)
243               $related->getIsNewRecord() ? $related->insert() : $related->update();
244             else

Re: WithRelatedBehavior

Добавлено: 2013.04.10, 14:22
XAKEPEHOK
Извиняюсь, действительно мой косяк. У меня в модели advertisers поле userID было как PRIMARY, а не как INDEX. Проблема решена

Re: WithRelatedBehavior

Добавлено: 2013.04.25, 16:09
Adept
Подскажите, как лучше всего решить ситуацию:
таблицы post, tag
связаны через posts_to_tags
tag_name - уникальный индекс
Надо чтобы при сохранении поста создавалось соответствие с тегом в таблице связей, но сами теги сохранялись только, если уникальные.
Сейчас при сохраненни тегов, мускул выдает ошибку если тег есть уже. Надо как то реализовать on duplicate key ignore для тегов.

Re: WithRelatedBehavior

Добавлено: 2013.04.25, 16:33
XAKEPEHOK
Попробуйте посмотреть в сторону taggable-behavior

Re: WithRelatedBehavior

Добавлено: 2013.04.25, 17:33
Adept
Я просто думал что это расширение реализует сохранение в таблицы со связями многие к многим, а сейчас идет попытка создать дубликат в поле тег и выходит что 1 полю пост соответствует несколько тегов, но одной записы таблицы тегов соответствует 1 пост, т.е. 1 к моногим.

Re: WithRelatedBehavior

Добавлено: 2013.04.25, 22:14
Adept
XAKEPEHOK, спасибо! Эта штука работает как надо)