Yii Framework Forum: [Solved]Insert In 2 Tables With 1 Form - Yii Framework Forum

Jump to content

Page 1 of 1
  • You cannot start a new topic
  • You cannot reply to this topic

[Solved]Insert In 2 Tables With 1 Form [SOLVED] Rate Topic: -----

#1 User is offline   lagogz 

  • Advanced Member
  • PipPipPip
  • Yii
  • Group: Members
  • Posts: 421
  • Joined: 30-November 12
  • Location:Galiza

Posted 10 January 2013 - 10:49 AM

Good afternoon.

I've the following:

*** 3 tables ***

- Authors (IdAuthor, AuthorName)
- Books (IdBook, BookName)
- Authors_Books (IdAuthor, IdBook)

*** 2 models ***
- Authors
- Books

A books can have multiple authors.

In my Books view, I've a form with a dropdownlist for Authors.AuthorName and a textarea for Books.BookName.

I want:

1- Put 2 buttons (Add and Remove) and a CListView in the Books view's form. When I click on Add button, the Author selected in dropdownlist will be added to a bottom listview. When I click on Remove button, the author selected in listview will be removed from listview.

2- I want to save data in the Books table, and then I want save the data in the Authors_Books table (both in actionCreate in Books controller). From what I've read, I think I have to make a new model for Authors_Books and use it. But, should not this model have a controller?

How I can implement this?

I need help.

Thanks.
-----------------------------------------------------------------------------------------------
------------------------------- VISITEN FOCUCHASART --------------------------------
-----------------------------------------------------------------------------------------------
0

#2 User is offline   developer! 

  • Standard Member
  • PipPip
  • Yii
  • Group: Members
  • Posts: 110
  • Joined: 28-November 12

Posted 10 January 2013 - 12:53 PM

you can save into 2 Models(tables) with the controller you are working with.
but you need to have the model for every table you want to perform operations with in order to communicate with database.


--cheers
1

#3 User is offline   developer! 

  • Standard Member
  • PipPip
  • Yii
  • Group: Members
  • Posts: 110
  • Joined: 28-November 12

Posted 10 January 2013 - 01:01 PM

Hope this helps a bit. its rough idea to get on....


public function actionCreate()
	{
		$model1=new Model1;
		
		$model2  = Model2::model()->findAll();

		if(isset($_POST['Model1']))
		{
			//var_dump($_REQUEST);die;
			

				if($model->save()){
					//save the record into Model2
					$model2->model1_id  = $model->id;
					
					$model2->model1_name_  = $_POST['Model3']['name'];
					$model2->save();
					

		$this->render('create',array(
				'model1'=>$model1,
				'model2'=>$model2,
				'another3'=>anotherModel::model()->findAll(),

		));

	}



dont mind if you find any errors..
1

#4 User is offline   lagogz 

  • Advanced Member
  • PipPipPip
  • Yii
  • Group: Members
  • Posts: 421
  • Joined: 30-November 12
  • Location:Galiza

Posted 11 January 2013 - 02:45 AM

View Postdeveloper!, on 10 January 2013 - 01:01 PM, said:

Hope this helps a bit. its rough idea to get on....


public function actionCreate()
	{
		$model1=new Model1;
		
		$model2  = Model2::model()->findAll();

		if(isset($_POST['Model1']))
		{
			//var_dump($_REQUEST);die;
			

				if($model->save()){
					//save the record into Model2
					$model2->model1_id  = $model->id;
					
					$model2->model1_name_  = $_POST['Model3']['name'];
					$model2->save();
					

		$this->render('create',array(
				'model1'=>$model1,
				'model2'=>$model2,
				'another3'=>anotherModel::model()->findAll(),

		));

	}



dont mind if you find any errors..


Thanks for the clarification, developer!.

But i don't understand your code very well.

- $model1-> Is it Books model?
- $model2-> Is it Authors model?
- Should not write this
$model1->attributes=$_POST['Model1'];
before save?
- I don't understand the code that comes after
if($model->save()){
.

I'll try and I commented.

Thanks for the replies.
-----------------------------------------------------------------------------------------------
------------------------------- VISITEN FOCUCHASART --------------------------------
-----------------------------------------------------------------------------------------------
0

#5 User is offline   nath-0 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 81
  • Joined: 12-October 12
  • Location:switzerland

Posted 11 January 2013 - 03:29 AM

View Postlagogz, on 11 January 2013 - 02:45 AM, said:

Thanks for the clarification, developer!.

But i don't understand your code very well.

- $model1-> Is it Books model?
- $model2-> Is it Authors model?
- Should not write this
$model1->attributes=$_POST['Model1'];
before save?
- I don't understand the code that comes after
if($model->save()){
.

I'll try and I commented.

Thanks for the replies.


yes $model1 is like Books model.

But you have a model book, isn't? in your folder model.

so at the place of $model1 you write $books, so after the code is :


yes you should do that before saving :
$books->attributes=$_POST['books']

if you save 2 models you can do a transaction, I have a exemple for you :

public function actionCreate() {
        $model = new PePersonne;
        $modelAdresse = new PeAdresse;
        $adresseCreation = false;
        // Uncomment the following line if AJAX validation is needed
        $this->performAjaxValidation(array($model, $modelAdresse));
        
        if (isset($_POST['PeAdresse']) || isset($_POST['PePersonne'])) {
            $transaction = $model->dbConnection->beginTransaction();
            try {
                if (isset($_POST['PeAdresse'])) {
                    $modelAdresse->attributes = $_POST['PeAdresse'];
                    $valid = $modelAdresse->validate();

                    if ($valid && PeAdresse::AdresseIsSet($modelAdresse->attributes)) {
                        $modelAdresse->adresse_id = PeAdresse::getNewUID();
                        $modelAdresse->save();
                        $adresseCreation = true;
                    }
                }
                if (isset($_POST['PePersonne'])) {
                    
                    $model->attributes = $_POST['PePersonne'];
                    $valid = $model->validate();
                    if ($valid) {
                        if ($adresseCreation) {
                            $model->fk_adresse_priv = $modelAdresse->adresse_id;
                        }
                        $model->personne_id = PePersonne::getNewUID();
                        $model->fk_type_pers = UTILISATEUR;
                        $model->save();
                    }
                }
                // gestion des profils
                if (!empty($_POST['PePersonne']['listProfils'])){                  
                    AdPersonneProfil::model()->deleteAll(array('condition' => 'fk_personne=:personneId', 'params' => array(':personneId' => $model->personne_id)));
                    foreach ($_POST['PePersonne']['listProfils'] as  $value) {          
                        $modelProfil = new AdPersonneProfil;                       
                        $modelProfil->fk_profil = $value;                        
                        $modelProfil->fk_personne = $model->personne_id;                      
                        $modelProfil->save();
                    }
                       
                }
                // FIN -- gestion des profils
 
                $transaction->commit();
                Yii::app()->user->setFlash('messageToDisplay', yii::t('messages', 'okCreation'));
                $this->redirect(array('admin', 'id' => $model->personne_id));
            } catch (Exception $e) {
                $transaction->rollback();
                Yii::app()->user->setFlash('messageToDisplay', yii::t('messages', 'erreurCreation'));
            }
        }

        $this->render('create', array(
            'model' => $model,
            'modelAdresse' => $modelAdresse,
        ));
    }


yon can use $model->save(); for create and update.
as you did $books->attributes=$_POST['books'], $model->save() will create or update your table books with new values.

I hope I have help you even if my english is very bad !
1

#6 User is offline   lagogz 

  • Advanced Member
  • PipPipPip
  • Yii
  • Group: Members
  • Posts: 421
  • Joined: 30-November 12
  • Location:Galiza

Posted 14 January 2013 - 02:44 AM

Good morning!!

Thanks for replies!

Thanks to them and to this thread Multiple Models I get save the data.

But still not working as I want.

1- The data is saved correctly, but I need a list with buttons for adding and removing some IdAuthors in Authors_Books table.

2- When I update the data, I have to re-pass all three models to update form, how is it right?

3- In admin form I must show all AuthorName related with IdBook, and I don't display them.

My code:

BooksController:

public function actionCreate()
    {
$modelBooks=new Books;       
        $modelAB=new AuthorsBooks();          
        $modelAuthors=new Authors;     
        
        if (isset($_POST['Books']) || 
                isset($_POST['AuthorsBooks']))
        {
            $transaction = $Books->dbConnection->beginTransaction();
            
            try 
            {
                $Books->attributes=$_POST['Books'];

                if($Books->save())            
                {
                    $AuthorsBooks->attributes=$_POST['AuthorsBooks'];
                    $AuthorsBooks->IdBook=$Books->IdBook;
                    
                    if($AuthorsBooks->save())
                    {
                        $transaction->commit();
                        $this->redirect(array('view','id'=>$Books->IdBook));
                    }
                }
            } catch (Exception $e) {
                $transaction->rollback();
                Yii::app()->user->setFlash('Error.', yii::t('messages', 'erreurCreation'));
            }
        }
        
        $this->render('create',array(
                                    'Books'=>$Books,
                                    'AuthorBooks'=>$AuthorBooks,
                                    'Authors'=>$Authors,
                    ));
}


public function actionUpdate($id)
    {
$Books=$this->loadModel($id);

        // Uncomment the following line if AJAX validation is needed
        // $this->performAjaxValidation($model);

        if(isset($_POST['Books']))
        {
            $Books->attributes=$_POST['Books'];
            
            if($Books->save())
                $this->redirect(array('view','id'=>$Books->IdBooks));
        }

        $this->render('update',array('Books'=>$Books,));
}



Books model:
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(
                    'FK_MPA_books' => array(self::MANY_MANY, 'Authors', 
                                                    'Authors_Books(IdBook, IdAuthor)'),
        );
    }

public function search()
    {
        // Warning: Please modify the following code to remove attributes that
        // should not be searched.

        $criteria=new CDbCriteria;
        
        $criteria->with = array('FK_MPA_books');           
        $criteria->compare('FK_MPA_books',$this->IdAuthor);
        $criteria->compare('BookName',$this->BookName,true);

        return new CActiveDataProvider($this, array(
                                                    'criteria'=>$criteria,
        ));
    }


AuthorsBooks model:

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(
        );
    }


Authors model:

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(
                    'FK_Authors' => array(self::MANY_MANY, 'Books', 'Authors_Books(IdAuthor, IdBook)'),
        );
    }


"_form.php" Books:

<div class="row">
            <?php 
                echo $form->labelEx($AuthorsBooks,'IdAuthor'); 
                echo $form->dropDownList($AuthorsBooks, 'IdAuthor', CHtml::listData(
                                        AuthorsBooks::model()->findAll(), 'IdAuthor', 'AuthorName'),
                                        array('prompt' => 'Select')); 
                echo $form->error($AuthorsBooks,'IdAuthor'); 
            ?>
        </div>


"update.php" Books:

echo $this->renderPartial('_form', array('Books'=>$Books)); 


"admin.php" Books:

    $this->widget('application.components.GridView', array(
                        'id'=>'books-grid',
                        'dataProvider'=>$model->search(),
                        'filter'=>$model,
                        'columns'=>array(
                                        array('name'=>'IdAuthor', 
                                                'value'=>'(isset($data->FK_MPA_books->IdAuthor)) ? 
                                                            $data->FK_MPA_books->IdAuthor : ""' ),
                                        'BookName',
                                        array('class'=>'CButtonColumn',),
                                    ),
    )); 


I will try things to see if I succeed. Any help is welcome, lol.

Thanks.
-----------------------------------------------------------------------------------------------
------------------------------- VISITEN FOCUCHASART --------------------------------
-----------------------------------------------------------------------------------------------
0

#7 User is offline   lagogz 

  • Advanced Member
  • PipPipPip
  • Yii
  • Group: Members
  • Posts: 421
  • Joined: 30-November 12
  • Location:Galiza

Posted 15 January 2013 - 02:37 AM

Good morning again!

Well, after I following this example Example, I got almost what I want.

But the AJAX code fail.

When I click in gridview A, I get an error: "Request failed: error." and I don't know why. Therefore, the B gridview doesn't refresh.

Here my code:

views/Books/admin.php

<?php
    /* @var $this BooksController */
    /* @var $model Books */

    $this->breadcrumbs=array(
                            'Books'=>array('index'),
                            'Manage',
    );

    $this->menu=array(
                    array('label'=>'List', 'url'=>array('index')),
                    array('label'=>'New', 'url'=>array('create')),
    );

    Yii::app()->clientScript->registerScript('search', "
                                            $('.search-button').click(function(){
                                                    $('.search-form').toggle();
                                                    return false;
                                            });
                                            $('.search-form form').submit(function(){
                                                    $.fn.yiiGridView.update('books-grid', {
                                                            data: $(this).serialize()
                                                    });
                                                    return false;
                                            });
    ");
?>

<h1>Manage Books</h1>

<div class="span-5 last operations_ads">
    <div id="sidebar">
        <?php
            $this->widget('zii.widgets.CMenu', array(
                                                    'items'=>$this->menu,
                                                    'htmlOptions'=>array('class'=>'operations'),
            ));
        ?>
    </div><!-- sidebar -->
</div>

<?php 
    echo CHtml::link('Advanced Search','#',array('class'=>'search-button')); 
?>

<div class="search-form" style="display:none">
    <?php 
        $this->renderPartial('_search',array('modelBooks'=>$modelBooks,)); 
    ?>
</div><!-- search-form -->

<div id="parentView">
    <?php 
        $this->widget('application.components.GridView', array(
                'id'=>'books-grid',
                'dataProvider'=>$modelBooks->search(),
                'filter'=>$modelBooks,
                'columns'=>array(
                                'IdBook',
                                'Book',
                                array('class'=>'CButtonColumn',),
                            ),
                'ajaxUpdate' => 'child-grid',
        )); 
    ?>
</div>

<!-- Use this paragraph to display the loading.gif icon above the Child Gridview,
while waiting for the ajax response -->
<p id="loadingPic"></br></p>

<!-- The childView <div>, renders the _child form, which contains the Child Gridview.
The ajax response will replace/update the whole <div> and not just the gridview. -->
<div id="childView">
    <?php
        $this->renderPartial('_child', array(
                                            'modelAuthorsBooks' => $modelAuthorsBooks, /* New */
                                            'IdBook' => $IdBook, /* New */
        ))
    ?>
</div>

<?php
    /*Load the javascript file that contains the ajax function*/
    $path = Yii::app()->baseUrl.'/js/customFunctions.js';
    Yii::app()->clientScript->registerScriptFile($path, CClientScript::POS_END);
?>


views/Books/_child.php

<p id="subsectionheading">Related Authors</p>
<div class="hint">(Please note: If no Book is selected, the Authors of the top-most Book are displayed.)</div>
 
<?php
    $this->widget('application.components.GridView', array(
                            'id'=>'child-grid',
                            'dataProvider'=>$modelAuthorsBooks->searchIncludingAuthors($IdBook),
                            'filter'=>$modelAuthorsBooks,
                            'columns'=>array(
                                            array(
                                                'name'=>'AuthorName',
                                                'value'=>'($data->FK_AB_Authors)?$data->
                                                    FK_AB_Authors->AuthorName:""', 
                                                    /* Test for empty related fields not to crash the 
                                                     * program */
                                                'header'=>'Author Name',
                                                'filter' => CHtml::activeTextField($modelAuthorsBooks,'AuthorName'),
                                            ),
                                            array(
                                                'class'=>'CButtonColumn',
                                                'template'=>'{view}{update}{delete}',
                                                'viewButtonUrl' => 'array("Authors/view",
                                                "id"=>$data->IdAuthor)',
                                                'updateButtonUrl' => 'array("Authors/update",
                                                "id"=>$data->IdAuthor)',
                                                'deleteButtonUrl' => 'array("Authors/delete",
                                                "id"=>$data->IdAuthor)',
                ),
    ),
));
?>


controllers/BooksController.php

public function actionAdmin()
    {
        $modelBooks=new Books('search');
        $modelBooks->unsetAttributes();  
        
        if(isset($_GET['Books']))
            $modelBooks->attributes=$_GET['Books'];
        
        if(!isset($_GET['IdBook']))
        {
            $group = "A";

            $criteria=new CDbCriteria;
 
            $criteria->compare('IdBook',$modelBooks->IdBook,true);
            $criteria->compare('BookName',$modelBooks->BookName,true);
 
            $dataProvider = new CActiveDataProvider('Books', 
                                                        array(
                                                            'criteria'=>$criteria,
                ));
 
            /* Test if the dataProvider found any data (filtering 
                parameters might have excluded all records)*/
            If (count($dataProvider->getData()) > 0) 
            {
                /* Extract the first model from the dataprovider */
                $first_model=$dataProvider->getData();
 
                /* Extract the record's PK, to be used to generate 
                the child-gridview's data records.*/
                $IdBook= $first_model[0]->IdMedicamento;
            }
            else
            {
                /* Set $IdBook to 0, to return an empty child-
                grid.*/
                $IdBook= 0;
            }
        }
        else
        {
            /* The event using this action, is from Group B: */
            $group = "B";
 
            /* Get the IdBook, which the event passed to this 
            action.*/
            $IdBook= $_GET['IdBook'];
        }
        
        $modelAuthorsBooks = new AuthorsBooks("searchIncludingAuthors($IdBook)");
        $modelAuthorsBooks ->unsetAttributes();
        $modelAuthorsBooks ->scenario = 'searchIncludingAuthors';
        
        if(isset($_GET['AuthorsBooks']))
            $modelAuthorsBooks ->attributes=$_GET['AuthorsBooks'];
        
        if($group == "A"){
            $this->render('admin',array(
                'modelBooks'=>$modelBooks,
                'modelAuthorsBooks '=>$modelAuthorsBooks ,
                'IdBook' => $IdBook,
            ));
        }
        else{
            $this->renderPartial('_child', array(
                'modelAuthorsBooks '=>$modelAuthorsBooks ,
                'IdBook' => $IdBook,
            ));
        }
    }



AuthorsBooks model

    public $AuthorName; 

    public function rules()
    {
        // NOTE: you should only define rules for those attributes that
        // will receive user inputs.
        return array(
                    array('IdAuthor, IdBook', 'required'),
                    array('IdAuthor, IdBook', 'numerical', 'integerOnly'=>true),
                    // The following rule is used by search().
                    // Please remove those attributes that should not be searched.
                    array('AuthorName, IdBook', 'safe', 'on'=>'search, 
                            searchIncludingAuthors'),
        );
    }

    /**
     * @return array relational rules.
     */
    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(
            'FK_AB_Books' => array(self::BELONGS_TO, 'Books', 'IdBook'),
            'FK_AB_Authors' => array(self::BELONGS_TO, 'Authors', 
                                                'IdAuthor'),
        );
    }

public function search()
    {
        // Warning: Please modify the following code to remove attributes that
        // should not be searched.

        $criteria=new CDbCriteria;

        $criteria->compare('IdAuthor',$this->IdAuthor);
        $criteria->compare('IdBook',$this->IdBook);

        return new CActiveDataProvider($this, array(
                                                    'criteria'=>$criteria,
        ));
    }
    
    public function searchIncludingAuthors($IdBook)
    {
        /* This function creates a dataprovider with RolePermission
        models, based on the parameters received from the controller. It
        also includes related Permission models, obtained via the
        relPermission relation. */
        $criteria=new CDbCriteria;
        $criteria->with=array('FK_AB_Authors');
        $criteria->together = true;
 
 
        /* filter on books-grid PK ($IdBook) received from the 
        controller*/
        $criteria->compare('t.IdBook',$IdBook,false); 
 
        /* Filter on default Model's column if user entered parameter*/
        $criteria->compare('t.IdAuthor',$this->IdAuthor,true);
 
        /* Filter on related Model's column if user entered parameter*/
        $criteria->compare('FK_AB_Authors.AuthorName',
            $this->AuthorName,true);
 
        /* Sort on related Model's columns */
        $sort = new CSort;
        $sort->attributes = array(
            'AuthorName' => array(
            'asc' => 'AuthorName',
            'desc' => 'AuthorName DESC',
            ), '*', /* Treat all other columns normally */
        );
        /* End: Sort on related Model's columns */
 
        return new CActiveDataProvider($this, array(
            'criteria'=>$criteria,
            'sort'=>$sort, /* Needed for sort */
        ));
    }


AJAX--customFunctions.js

$('#parentView').on("click", "table tbody td:not(td:.button-column)", function(event){
    
    try{
        /*Extract the Primary Key from the CGridView's clicked row.
        "this" is the CGridView's clicked column or <td>.
        Go up one parent - which gives you the row.
        Go down to child(1) - which gives you the first column,
            containing the row's PK. */
        var gridRowPK = $(this).parent().children(':nth-child(1)').text();
        /*Display the loading.gif file via jquery and CSS*/
        $("#loadingPic").addClass("loadGIF");
 
        /* Call the Ajax function to update the Child CGridView via the
        controller’s actionAdmin */
        var request = $.ajax({ 
          url: "Admin",
          type: "GET",
          cache: false,
          data: {IdMedicamento : gridRowPK},
          dataType: "html" 
        });
 
        request.done(function(response) { 
            try{
                /*since you are updating innerHTML, make sure the
                received data does not contain any javascript - 
                for security reasons*/
                if (response.indexOf('<script') == -1)
                {
                    /*update the view with the data received 
                    from the server*/       
                    document.getElementById('childView').innerHTML = response;
                }
                else 
                {
                    throw new Error('Invalid Javascript in Response - possible hacking!');
                }
            }
            catch (ex){
                alert(ex.message); /*** Send this to the server 
                for logging when in production ***/
            }
            finally{
                /*Remove the loading.gif file via jquery and CSS*/
                $("#loadingPic").removeClass("loadGIF");
 
                /*clear the ajax object after use*/
                request = null;
            };
        });

        request.fail(function(jqXHR, textStatus) {
            try{
                throw new Error('Request failed: ' + textStatus );
            }
            catch (ex){
                alert(ex.message); /*** Send this to the server 
                for logging when in production ***/
            }
            finally{
                /*Remove the loading.gif file via jquery and CSS*/
                $("#loadingPic").removeClass("loadGIF");
 
                /*clear the ajax object after use*/
                request = null;
            }
        });
    }
    catch (ex){
        alert(ex.message); /*** Send this to the server for logging when 
        in production ***/
    }
});



AJAX fails in line
request.done(function(response) { 


It's what I need to get it!!. I need ideas!

Thanks.
-----------------------------------------------------------------------------------------------
------------------------------- VISITEN FOCUCHASART --------------------------------
-----------------------------------------------------------------------------------------------
0

#8 User is offline   lagogz 

  • Advanced Member
  • PipPipPip
  • Yii
  • Group: Members
  • Posts: 421
  • Joined: 30-November 12
  • Location:Galiza

Posted 16 January 2013 - 11:17 AM

Finally revolved.

I did following this Example for refresh the chil CGridView and go.

Thanks you all!!
-----------------------------------------------------------------------------------------------
------------------------------- VISITEN FOCUCHASART --------------------------------
-----------------------------------------------------------------------------------------------
0

Share this topic:


Page 1 of 1
  • You cannot start a new topic
  • You cannot reply to this topic

1 User(s) are reading this topic
0 members, 1 guests, 0 anonymous users