yii - сохранение связки типа MANY_MANY (many to many) - пример сохранения и вывода табличной обработки данных связанных моделей

вроде как стандартных средств для разруливания подобных "сложных" отношений в Yii нет, а потому предлагается использовать это расширение

-и ещё - по слухам надо указать, в правилах валидации, что отношение безопасно, например ,для categories,это выглядит как-то так:

public function rules()
{
        return array(
                array('categories', 'safe'),                    
        );
}

Расширение ESaveRelatedBehavior

Опять вернёмся к расширению, которое мы собрались использовать - вообще-то о том как это делать уже написано здесь

Далее качаем архив - в моё (на странице он справа - берите последнюю версию) - название файла будет вроде:

 ESaveRelatedBehavior-v1.5.zip

ну и в модели, в которой собираемся использовать это прекрасное расширение напишем "публичный" метод:

// необходимо для использования расширения ESaveRelatedBehavior
	// которое позвляет созранять отношения типа MANY_MANY
	public function behaviors()
	{
		return array('ESaveRelatedBehavior' => array(
			'class' => 'application.components.ESaveRelatedBehavior')
		);
	}

затем нам стоит вспомнить про обработку табличного ввода (рассмотрим ситуацию, когда к странице привязана целая туча человек - и вот их мы будем выводить в виде таблицы - например страница - это конференция + массив сущностей "участник конференции" - но при этом нам надо организовать на одной странице как редактирование самой странице(информация о конференции) - так и списка участников - их как минимум, надо уметь добавлять)

Сохранение связанной('привязанной') сущности из формы

Пусть в модели страницы, связь с участниками определена следующим образом:

public function relations() //  задаём отношения с другими классами 
	{
		return array(
			// связи
			'persons' => array(self::MANY_MANY, 'Person', 'page_person(page_id, person_id)'),
		);
	}

тогда вывести поле для имени одного из участников(пусть первого в списке) можно так:

<?php echo CHtml::activeTextField($model,'persons[1][info]'); ?>

то есть мы просто как бы говорим yii по средством html что будем использовать массив -
далее при сохранении модели страницы - мы можем проверить что хотя бы один из элементов массива определён и сохранить
экземпляры моделей всех привязанных к данной странице участников - при этом одновременно заполним таблицу отношения многие-ко многим.

У меня нет времени особенно вдаваться в возможности модуля - так как это моё первое рабочее приложение на Yii, а потому я предлагаю вам, друзья, такой вот пример обхода массива связанных сущностей ,который мы концептуально рассматриваем как одно из полей основной модели -
привожу фрагмент кода действия editPage :

function actionEditPage($id) // получаем через GET id редактируемой страницы
	{
		// сначала проверка прав доступа
		if (!Yii::app()->user->checkAccess('updatePost')) {
			throw new CHttpException(403, 'Forbidden');
		}


		// подгружаем модель по id
//		подгрузку модели в принципе можно заменить
//		созданием новой
		$page = Page::model()->with('persons')->findByPk($id);

		// если не нашли по id
		if (!$page)
			throw new Exception('Bad id.');
		// если форма отправлена
		if (isset($_POST['Page'])) { // если данные из формы пришли
			$page->attributes = $_POST['Page'];
			// сохраняем модель
			$persons = array(); // сюда будем созранять индексы имеющихся моделей
			if ($_POST['Page']['persons']){ // проверяем что хоть что-то пришло
				// раз пришло -начинаем "обходить" массив
				foreach ($_POST['Page']['persons'] as $key => $value)
				{
					$person = new Person();
					$person->attributes = $value;
					$person->save();
					$persons[] = $person->id; // собираем id-шники созранённых моделей в массив
					Yii::trace("добавляем персону ))", 'info' ); // просто трассировка
				}
				$page->persons = $persons;// сохраняем сведения о номерах связанных сущностей
			}
			if ($page->validate()) // проыеряем форму (да проверку вообще надо раньше делать)
				$page->saveWithRelated('persons'); // ВОТ ОНО! сохраняем данные в доп. талблицу
			// для разруливания MANY_MANY
				$this->redirect(array('perfomance/pageslist')); // переходим к списку страниц
		}
      // если данные от формы не отправлены  -
		$this->render('editpage', array('model' => $page)); // То просто выводим форму редактирования
	}

при этом следует помнить что вызов ->saveWithRelated('persons') - затрёт в таблице все старые элементы привязанные к данной странице и добавит новые - чтобы старые элементы не стирались надо написать вызов обновления в виде:

$model->saveWithRelated( array('relationName1' => array('append' => true)));

append = 'прилагать, добавлять'. То есть в для приведённого выше примера можно было бы написать:

$page->saveWithRelated( array('persons' => array('append' => true)));

вот так-то )))