При Редактировании - Удалить Все Записи, И Добавить По Одной

Добрый день!

Не могу решить проблему, казалось бы мелочь, но не продвигаюсь с мертвой точки.

Во вьюшке при создании пользователя user/create есть поля для заполнения пользователя (такие как логин, пароль, емаил…) и есть чекбоксы (айдишники из таблицы lpu). При создании пользователя - создается строка в соответствующей таблице. Помимо этого вставляю строки в таблицу lpususers(id, user_id, lpu_id) со значениями id, user_id-наш будущий id созданного пользователя, и lpu_id- айдишники выбранных чекбоксов.

Все работает. Но при редактировании другая схема. Нужно сперва очистить поля в таблице lpususers, где user_id-айди редактируемого пользователя, а потом заново добавить строки.

Сделал, чтоб все строки удалялись перед каждым сохранением в базу. Но получается так, что вносится лишь последняя запись. Как сделать, чтоб сперва все его записи удалились, а потом все нужные добавились.

Код контроллера UserController


public function actionUpdate($id)

    {

        $model=$this->loadModel($id);        

        if(isset($_POST['User']))

        {

            $model->attributes=$_POST['User'];

            if($model->save()) {

                foreach($_POST["userLpuIds"] AS $id)

                {

                    $lpu=new Lpususers();

                    $lpu->lpu_id =  $id;

                    $lpu->user_id = $model->id;

                    //$lpu->loadModel($model->id)->delete();

                    Lpususers::model()->deleteAllByAttributes(array(

                    'user_id'=>$lpu->user_id));

                    $lpu->save(false);

                }

                return $this->redirect(array('view','id'=>$model->id));

            }

        }

        $lpu=new Lpususers();        

        $this->render('update',array(

            'model'=>$model, 'lpu'=>$lpu

        ));

    } 

и код формочки редактирования


<div class="row">    

<?php echo $form->labelEx($model,'LpuIds');

$lpus = Lpu::model()->findAll(array('order'=>'id ASC'));

$lpususers = Lpususers::model()->findAllByAttributes(array('user_id'=>18));

?>

<?php foreach($lpus As $lpu) {


    echo $lpu->id?>

    <input type="checkbox" name="userLpuIds[]" value="<?php echo $lpu->id?>"/>

    <?php

    }

?>

</div>

Ну так и удаляйте один раз, зачем же Вы в цикле-то Lpususers::model()->deleteAllByAttributes()?

Советский Союз, как обычно, всю ночь программит, а потом вот такое :lol:

Ок, я думал об этом, но пробовал-не работает.


public function actionUpdate($id)

	{

		$lpu=new Lpususers();	

		Lpususers::model()->deleteAllByAttributes(array(

					'user_id'=>$lpu->user_id));

		

		$model=$this->loadModel($id);		

		if(isset($_POST['User']))

		{

			$model->attributes=$_POST['User'];

			if($model->save()) {

				foreach($_POST["userLpuIds"] AS $id)

				{

					$lpu=new Lpususers();

					$lpu->lpu_id =  $id;

					$lpu->user_id = $model->id;

					//$lpu->loadModel($model->id)->delete();

					

					$lpu->save(false);

				}

				return $this->redirect(array('view','id'=>$model->id));

			}

		}

			

		$this->render('update',array(

			'model'=>$model, 'lpu'=>$lpu

		));

	}

Теперь не удаляет вовсе, а лишь добавляет.

Вот не надо только отмазываться, я красноглазиков на раз вычисляю :D

Вот в этом куске кода


$lpu=new Lpususers();   

Lpususers::model()->deleteAllByAttributes(array('user_id'=>$lpu->user_id));

чему равен $lpu->user_id? :)

А засунуть нужно после $model->save() (когда $model->id уже станет ясен) но перед foreach().

Город спит, просыпаются программисты…

Неа :(


public function actionUpdate($id)

	{

		$lpu=new Lpususers();	

		

		

		$model=$this->loadModel($id);		

		if(isset($_POST['User']))

		{

			$model->attributes=$_POST['User'];

			if($model->save()) {

				Lpususers::model()->deleteAllByAttributes(array(

					'user_id'=>$lpu->user_id));

				foreach($_POST["userLpuIds"] AS $id)

				{

					$lpu=new Lpususers();

					$lpu->lpu_id =  $id;

					$lpu->user_id = $model->id;

					//$lpu->loadModel($model->id)->delete();

					

					$lpu->save(false);

				}

				return $this->redirect(array('view','id'=>$model->id));

			}

		}

			

		$this->render('update',array(

			'model'=>$model, 'lpu'=>$lpu

		));

	}

$lpu->user_id ============> $model->id

СПАТЬ, КОМУ ГОВОРЮ!!

Upd: так, сразу, на всякий случай :)

Поменять нужно только во одном месте


Lpususers::model()->deleteAllByAttributes(array('user_id'=>$model->id));

Ну и вообще, поглядывайте на запросы, которые Yii генерит, особенно на те, что updateAll, deleteAll и аналоги. Продолбаете случайно аргумент - и хана всей базе.

Спасибо огромное! :) Выручил!

Сон для слабаков :rolleyes:

Да у меня на этом подфоруме целая ветка где-то была, куда я перлы неспящих собирал.

Первое место уверенно занимает softark с его точкой с запятой, засунутой между foreach и {}, вот так:

foreach (…); { … }

Сколько он по времени искал ошибку? :)

12 часов, кажется.

К бессонной ночи он добавил еще 12 часов яростных поисков баги :)

По своей части. Хочу прикрутить фишку - в форме редактирования пользователя чтоб чекбоксы (для которых есть записи в бд) отображались выбранными.

Такая вот штука есть для этого

http://www.yiiframework.com/doc/api/1.1/CHtml#activeCheckBoxList-detail

Единственное мерзкое (возможно) место тут - значение атрибута модели.

Начните с названия many_many отношения. Для activeListBox это работало, а вот для checkboxList был баг, не позволяющий принимать на вход массив AR-записей, приходилось предварительно преобразовывать. Но, вроде, его исправляли.

Отработать нужно следующие ситуации:

  1. начальная загрузка формы (выбранные значение берутся из БД при помощи many_many отношения)

  2. сабмит формы с ошибкой валидации (выбранные значения берутся из $_POST, представляют собой массив айдишников)

Есть таблица user: id, login, password, role (employer | admin).

Есть таблица lpu: id, name, text.

Есть таблица lpususers: id, user_id, lpu_id

В форме редактирования user/update мне нужно было вывести чекбоксы со всевозможными значениями id из таблицы lpu. Причем, выбранными должны быть те чекбоксы, id которых уже есть в таблице lpususers (это будет поле lpu_id)

Вывел таким образом пока:

Прошелся поиском по lpuusers where user_id=$id редактируемого пользователя, вывел его отмеченные чекбоксы.

Затем прошелся поиском по lpu и вывел все значения id. Таким образом есть наложение значений. Как бы сделать без повторений?!


public function actionUpdate($id)

	{

		$lpu=new Lpususers();

		$lpususers = Lpususers::model()->findAllByAttributes(array(

                'user_id'=>$id,

            ));

		

		

		$model=$this->loadModel($id);		

		if(isset($_POST['User']))

		{

			$model->attributes=$_POST['User'];

			if($model->save()) {

				Lpususers::model()->deleteAllByAttributes(array(

					'user_id'=>$model->id));

				foreach($_POST["userLpuIds"] AS $id)

				{

					$lpu=new Lpususers();

					$lpu->lpu_id =  $id;

					$lpu->user_id = $model->id;

					//$lpu->loadModel($model->id)->delete();

					

					$lpu->save(false);

				}

				return $this->redirect(array('view','id'=>$model->id));

			}

		}

			

		$this->render('update',array(

			'model'=>$model, 'lpu'=>$lpu, 'lpususers'=>$lpususers

		));

	}

Форма


<div class="row">    

<?php echo $form->labelEx($model,'LpuIds');

$lpus = Lpu::model()->findAll(array('order'=>'id ASC'));


foreach($lpususers As $lpu1) {

	echo $lpu1->lpu_id?>

<input type="checkbox" checked="checked" name="userLpuIds[]" value="<?php echo $lpu1->lpu_id?>"/>

<?php }


foreach($lpus As $lpu) {	

    echo $lpu->id?>

	<input type="checkbox" name="userLpuIds[]" value="<?php echo $lpu->id?>"/>

    <?php

    }

?>

</div>

Привел внешний вид этих чекбоксов

5199

snimok.png

Хотите за один заход выгрести и чекбоксы, и отмеченные значения?

Ну, с точки зрения sql это решается левым джойном с проверкой на null.

Спасибо! буду думать над реализацией

Я тут всё спать призывал, а сам-то :(

Одна буква пропущена, и все, htaccess не работает.

Хоть бы какое предупреждение вывели, что директория-то не существует…

И кто нам мешает спать, себе дороже?! :slight_smile:

Ну типа закончил один проект, думаю: а дай-ка сервер для нового проекта еще настрою быстренько, чтобы с утра начать кодить.

Ну и настроил, ага.

На самом деле, удивительно, что апач не жалуется на отсутствие папки.

Вот если DocumentRoot неверный - сразу выкатывает предъяву, а на Directory пофиг, выходит?.. Неправильно это.