many-to-many form partial

Hi!

I have to entries: book and authors, and book_has_authors in my DB.

How can I make my book / _form partial or my BookController so nice to have one (including the authors) form to create and update?


<div class="form">


<?php $form=$this->beginWidget('CActiveForm', array(

	'id'=>'book-form',

	'enableAjaxValidation'=>false,

)); ?>


	<p class="note">Pola z <span class="required">*</span> są wymagane.</p>


	<?php echo $form->errorSummary($model); ?>


	<div class="row">

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

		<?php echo $form->textField($model,'title',array('size'=>60,'maxlength'=>100)); ?>

		<?php echo $form->error($model,'title'); ?>

	</div>


	<div class="row">

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

		<?php echo $form->textField($model,'publication_year',array('size'=>4,'maxlength'=>4)); ?>

		<?php echo $form->error($model,'publication_year'); ?>

	</div>


	<div class="row">

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

		<?php echo $form->textField($model,'description',array('size'=>100,'maxlength'=>250)); ?>

		<?php echo $form->error($model,'description'); ?>

	</div>


	<div class="row">

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

		<?php echo $form->textField($model,'price'); ?>

		<?php echo $form->error($model,'price'); ?>

	</div>

        

        <div class="row">

            <?php echo $form->dropDownList($model, 'authors', $allAuthors); ?>

        </div>


	<div class="row buttons">

		<?php echo CHtml::submitButton($model->isNewRecord ? 'Utwórz' : 'Zapisz'); ?>

	</div>


<?php $this->endWidget(); ?>


</div><!-- form -->

Use the CAdvacedArBehavior in your Book model, and create a public variable

$authorIds = array();

in your Book model… then in afterFind:




public function afterFind() {

$this->authorIds = array_keys(CHtml::listData($this->Authors, 'id', 'name'));

return parent::afterFind();

}



in your form just use activeCheckBoxList with the newly introduced authorIds instead of the author relation (if needed enter it in attributeLabels aswell).

Then either in Controller after mass assignment of the attributes you just do:

$model->Authors = $_POST[‘Book’][‘authorIds’];

or write a magic getter / setter for it and add it as a safe attribute.

Hope that solves your problem

rhomb

Thanks, I will try tomorrow.

I’m just beginner and I still have problem. Please, help!

I’ve code:

Book.php:




        public $authorsAll = array();

        public $authorIds = array();

               

        public function afterFind() {

        $this->authorsAll = Author::model()->findAll();

        $this->authorIds = array_keys(CHtml::listData($this->authors, 'id', 'second_name'));

        return parent::afterFind();

        }



BookController.php:




	public function actionCreate()

	{

		$model=new Book;

                 

                 

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

		{

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

                        $model->authors = $_POST['Book']['authorIds'];

			if($model->save())

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

		}

                

                

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

			'model'=>$model,

		));

	}



_form.php:




           <?php echo CHtml::activeCheckBoxList(

              $model, 'authorIds', 

              CHtml::listData($model->authorsAll, 'id', 'name')        

            ); ?>



In “update” action I’ve chackbox with correctly check authors but any chcanges aren’t save. In “create” action I haven’t authors checkbox.

Second: what if user want create new authors whit a book, which is very likely? How to solve?

Thank you in advance.

Is some progres, I wrote in Book.php this code:




        public function afterConstruct() {

            $this->authorsAll = Author::model()->findAll();

            return parent::afterconstruct();

        }



and I have beautifull checkbox in create action too.

Help please…

Hi!

I have in action/update:




	public function actionUpdate($id)

	{

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


		// Uncomment the following line if AJAX validation is needed

		// $this->performAjaxValidation($model);

                

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

		{

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

                        $model->authors = $_POST['Book']['authorIds'];

                        $model->setAttribute('authors', '23');



and:

1/ model->authors is:




Array

(

    [0] => 1

    [1] => 2

    [2] => 3

)

it’s OK data from POST.

2/ $model->setAttribute(‘authors’, ‘23’); doesn’t work. I haven’t attribute “authors”.

3/ save() method don’t see $model->authors and don’t save it.

What now?

I’m do it manually this way:




        public function afterSave() {

            $command=Yii::app()->db->createCommand('

                DELETE FROM book_has_author WHERE book_id = '.$this->id)->execute();

            foreach ($this->authors as $author) {

                $command = Yii::app()->db->createCommand("

                INSERT INTO book_has_author (book_id, author_id) VALUES ($this->id, $author->id)")->execute();

            }

        }



Did you use the CAdvancedArBehavior?

First I didn’t (my mistake), now I try and it not works :(