Сохранение связанных данных

Обсуждение документации. Переводы Cookbook и авторские рецепты.
Аватара пользователя
samdark
Администратор
Сообщения: 9353
Зарегистрирован: 2009.04.02, 13:46
Откуда: Воронеж
Контактная информация:

Сохранение связанных данных

Сообщение samdark »

Рецепт, показывающий, как реализовать автоматическое сохранение связанных данных при сохранении модели.

http://yiiframework.ru/doc/cookbook/ru/ ... lated.data

dimmer
Сообщения: 8
Зарегистрирован: 2009.11.07, 01:23

Re: Сохранение связанных данных

Сообщение dimmer »

Что-то у меня вообще не сохраняет связанные данные. Вот пример:

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

$book=new Book();
 $file=new File();
if(isset($_POST['Book'])){
$book->attributes=$_POST['Book'];
$book->user_id=$file->user_id=Yii::app()->user->id;
$file->magnetlink=123;
$file->id=123;
$file->book_id=123;
$book->files[]=$file;
if($book->save()) $this->redirect(array('show','id'=>$book->id));
}
$this->render('create',array('model'=>$book,'file'=>$file)); 
Во-первых не сохраняет запись файла, а во-вторых если писать со скобками $book->files[]=$file; то выдает
Indirect modification of overloaded property Book::$files has no effect
Это нормально?
Просьба сильно не ругать Yii начал изучать недавно, но он мне уже успел во многом понравиться!

Аватара пользователя
samdark
Администратор
Сообщения: 9353
Зарегистрирован: 2009.04.02, 13:46
Откуда: Воронеж
Контактная информация:

Re: Сохранение связанных данных

Сообщение samdark »

Покажите реализацию afterSave() вашей модели.

dimmer
Сообщения: 8
Зарегистрирован: 2009.11.07, 01:23

Re: Сохранение связанных данных

Сообщение dimmer »

То есть надо ещё добавить какую-то логику в модель? Yii сам не сохраняет связанные данные? В примере в AfterSafe только раздает id-шники.

Аватара пользователя
samdark
Администратор
Сообщения: 9353
Зарегистрирован: 2009.04.02, 13:46
Откуда: Воронеж
Контактная информация:

Re: Сохранение связанных данных

Сообщение samdark »

В примере есть строчка $member->save(), которая и сохраняет связанные модели.

makingfeels
Сообщения: 2
Зарегистрирован: 2010.04.10, 16:22

Re: Сохранение связанных данных

Сообщение makingfeels »

Всех приветствую. Что-то никак не пойму,что не так делаю.
это код в actionCreate:

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

  $node=new Node;
        $numericField=new NodeNumericField;
        $stringField=new NodeStringField;
        
        if(isset($_POST['Node']))
        {
            $node->attributes=$_POST['Node'];
            $numericField->attributes=$_POST['NodeNumericField'];
            $stringField->attributes=$_POST['NodeStringField'];
            
            $node->nodeNumericFields[] = $numericField;
            $node->nodeStringFields[] = $stringField;    
            
            if($node->save()) $this->redirect('index');
            
        } 
И соотвественно в модели:

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

protected function afterSave(){
        parent::afterSave();
        foreach($this->nodeStringFields as $nodeStringField) {
            $nodeStringField->node_id = $this->id;
            $nodeStringField->save();
        }
        
        foreach($this->nodeNumericFields as $nodeNumericField) {
            $nodeNumericField->node_id = $this->id;
            $nodeNumericField->save();
        }
    }
  
запись node сохраняется,а вложенные нет,ошибок никаких не выдается.

makingfeels
Сообщения: 2
Зарегистрирован: 2010.04.10, 16:22

Re: Сохранение связанных данных

Сообщение makingfeels »

Наконец-то победил это, вопщем вся проблема была в том,что у меня почему-то не работает как на примере

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

$team->members[] = $member1;
$team->members[] = $member2; 

Работает вот так:

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

$team->members
Тоесть соотвественно в $team->members сохраняется уже массив.
(версия у меня кстати yii 1.1.1)

Аватара пользователя
Darth_Ixis
Сообщения: 105
Зарегистрирован: 2010.08.23, 10:03
Откуда: KZ, Almaty

Re: Сохранение связанных данных

Сообщение Darth_Ixis »

makingfeels писал(а):Наконец-то победил это, вопщем вся проблема была в том,что у меня почему-то не работает как на примере

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

$team->members[] = $member1;
$team->members[] = $member2; 
Аналогично.
Это нормальное поведение, что я не могу парными квадратными скобками создать массив / добавить элементов массиву?

Аватара пользователя
slavcodev
Сообщения: 3134
Зарегистрирован: 2009.04.02, 21:42
Откуда: Valencia
Контактная информация:

Re: Сохранение связанных данных

Сообщение slavcodev »

У меня тоже через квадратные скобки не хочет добавлять. Но решение есть:

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

$team->addRelatedRecord('members',$member1,count($team->members)); 
Жду Yii 3!

ezoterik
Сообщения: 8
Зарегистрирован: 2010.12.30, 18:59

Re: Сохранение связанных данных

Сообщение ezoterik »

Подскажите, а как мог бы выглядеть рецепт если нужно сохранить связи MANY_MANY? У меня скорее даже вопрос в том, что можно ли обойтись (в связывании данных при сохранении) без дополнительной модели на промежуточную таблицу в этом случае.

Аватара пользователя
samdark
Администратор
Сообщения: 9353
Зарегистрирован: 2009.04.02, 13:46
Откуда: Воронеж
Контактная информация:

Re: Сохранение связанных данных

Сообщение samdark »

Если вставлять через SQL — можно.

IStranger
Сообщения: 36
Зарегистрирован: 2011.11.04, 10:46
Контактная информация:

Re: Сохранение связанных данных

Сообщение IStranger »

Подскажите пожалуйста... Как быть, если число членов измеряется десятками-сотнями? Смущает как-то процедурная логика (многократное сохранение в цикле).

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

        foreach($this->members as $member) {
            ...
            $member->save();
        }
 
В данном случае в рамках AR возможно ли сохранение одним "массовым" запросом, или уже DAO нужно использовать?
G.Azamat { Web Development / Computer simulation }
Начинающий программист думает, что в килобайте 1000 байтов, а законченный уверен, что в километре 1024 метра.

Аватара пользователя
samdark
Администратор
Сообщения: 9353
Зарегистрирован: 2009.04.02, 13:46
Откуда: Воронеж
Контактная информация:

Re: Сохранение связанных данных

Сообщение samdark »

DAO.

Shlang
Сообщения: 4
Зарегистрирован: 2012.04.16, 10:00

Re: Сохранение связанных данных

Сообщение Shlang »

А как "лутше" поступить при создании новой записи? Без конструкции
$transaction=$model->dbConnection->beginTransaction();
try {
- - - -
$transaction->commit();
}
} catch (Exception $ex) {
$transaction->rollback();
return false;
}
похоже не обойтись?
Кошерный код длинным не бывает, может кто запостит чего...

yujin1st
Сообщения: 186
Зарегистрирован: 2012.03.26, 12:03

Re: Сохранение связанных данных

Сообщение yujin1st »

Подскажите как совместить данный способ вместе со связями описанными в relations()?
Ведь $team->members[] не работает при описанной связи.
К этому же вопросу можно и отнести табличные данные - хочется не "foreach" в контролере, а просто $team->attributes = $_POST['team']; $team->save();

Придумал такой костыль с объявлением свойства Team::_members, переименованием связи в membersRelated.

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

public function AfterFind(){
  if (hasRelation('membersRelated'){
  $this->_members = $this->membersRelated();
  }
}
public function getMembers(){
  return $this->_members;
}
// для того чтобы работало с табличным вводом при создании модели: $team->attributes= $_POST['Team']
public function setMembers($newMembers){
      if (is_array($newMembers) && count ($newMembers) {
      foreach ($newMembers as  $m) {
        $member = new Member();

        $member->attributes  = $m
        $this->_rentServices[] = $rs;
      }
    }
}
// вместо $team->members[] = $newMember будет $team->addMember($member)
public function addMember($member){
  $this->_members[]=$member
}
//и в afterSave() мы сохраняем
 
Но здесь:
- нет гибкости
- легко запутаться в именах
- облом при табличном редактировании тех же данных - приходиться только по одному...
- я не знаю как добавить валидацию в контроллере? Переопределять Team::validate()?
Я предполагаю, что изобретаю очередной велосипед, и наверняка есть более просто решение...

areshetnikov
Сообщения: 6
Зарегистрирован: 2012.11.08, 05:52

Re: Сохранение связанных данных

Сообщение areshetnikov »

ezoterik писал(а):Подскажите, а как мог бы выглядеть рецепт если нужно сохранить связи MANY_MANY? У меня скорее даже вопрос в том, что можно ли обойтись (в связывании данных при сохранении) без дополнительной модели на промежуточную таблицу в этом случае.
Всем привет!

подниму вопрос по поводу связывания двух сущностей MANY_MANY.
Как в этом случае стоит реализовать afterSave()? Писать в таблицу связки напрямую? Есть ли в YII готовое решение? Сколько не курю форум этот и общий - не могу найти ответа.

areshetnikov
Сообщения: 6
Зарегистрирован: 2012.11.08, 05:52

Re: Сохранение связанных данных

Сообщение areshetnikov »

В догонку:
Есть класс Tournament и его relations

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

    public function relations()
    {
        // NOTE: you may need to adjust the relation name and the related
        // class name for the relations automatically generated below.
        return array(
            'teams'=>array(self::MANY_MANY, 'Team', 'tr_tournament_teams(id_tournament, id_team)'),
            'teamsCount' => array(self::STAT, 'Team', 'tr_tournament_teams(id_tournament, id_team)'),
        );
    }
Есть класс Team и его relations

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

    public function relations()
    {
        // NOTE: you may need to adjust the relation name and the related
        // class name for the relations automatically generated below.
        return array(
            'tournaments'=>array(self::MANY_MANY, 'Tournament', 'tr_tournament_teams(id_team, id_tournament)'),    
        );
    }
В контроллере пишу:

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

class TournamentController extends Controller

    protected function addTeam($tournament)
    {
        $team=new Team();
        if(isset($_POST['Team']))
        {
            $team->attributes=$_POST['Team'];
            
            $team->save();
            array_push($tournament -> teams(), $team);
            array_push($team -> tournaments(), $tournament);
            $tournament->save();            
            $team->save();
        }
        return $tournament;
    }
При этом новые экземпляры Team в базе сохраняются, а связи между Team и Tournament.

Аватара пользователя
samdark
Администратор
Сообщения: 9353
Зарегистрирован: 2009.04.02, 13:46
Откуда: Воронеж
Контактная информация:

Re: Сохранение связанных данных

Сообщение samdark »

Нет, в Yii готового на тему нет, но есть http://yiiext.github.com/extensions/wit ... me.ru.html

areshetnikov
Сообщения: 6
Зарегистрирован: 2012.11.08, 05:52

Re: Сохранение связанных данных

Сообщение areshetnikov »

Посмотрел, простой пример собрал за 5 минут.
Спасибо, все работает. Буду встраивать в своё приложение.

areshetnikov
Сообщения: 6
Зарегистрирован: 2012.11.08, 05:52

Re: Сохранение связанных данных

Сообщение areshetnikov »

Отчего данная функциональность все еще не встроена в стандарт YII?
Кажется ведь столь полезной. Или это только с MANY_MANY такие сложности?

Ответить