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.
Page 1 of 1
[Solved]Insert In 2 Tables With 1 Form [SOLVED]
#1
Posted 10 January 2013 - 10:49 AM
-- If your question has been resolved, write [SOLVED] in the title of it.
-- Si tu pregunta ha sido respondida, escribe [SOLUCIONADO] en el título de la misma.
-- Se a túa pregunta foi resolta, escribe [RESOLTA] no título da mesma.
-- Si tu pregunta ha sido respondida, escribe [SOLUCIONADO] en el título de la misma.
-- Se a túa pregunta foi resolta, escribe [RESOLTA] no título da mesma.
#2
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
but you need to have the model for every table you want to perform operations with in order to communicate with database.
--cheers
#3
Posted 10 January 2013 - 01:01 PM
Hope this helps a bit. its rough idea to get on....
dont mind if you find any errors..
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..
#4
Posted 11 January 2013 - 02:45 AM
developer!, on 10 January 2013 - 01:01 PM, said:
Hope this helps a bit. its rough idea to get on....
dont mind if you find any errors..
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.
-- If your question has been resolved, write [SOLVED] in the title of it.
-- Si tu pregunta ha sido respondida, escribe [SOLUCIONADO] en el título de la misma.
-- Se a túa pregunta foi resolta, escribe [RESOLTA] no título da mesma.
-- Si tu pregunta ha sido respondida, escribe [SOLUCIONADO] en el título de la misma.
-- Se a túa pregunta foi resolta, escribe [RESOLTA] no título da mesma.
#5
Posted 11 January 2013 - 03:29 AM
lagogz, 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
- I don't understand the code that comes after
I'll try and I commented.
Thanks for the replies.
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 !
#6
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:
Books model:
AuthorsBooks model:
Authors model:
"_form.php" Books:
"update.php" Books:
"admin.php" Books:
I will try things to see if I succeed. Any help is welcome, lol.
Thanks.
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,));
}
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.
-- If your question has been resolved, write [SOLVED] in the title of it.
-- Si tu pregunta ha sido respondida, escribe [SOLUCIONADO] en el título de la misma.
-- Se a túa pregunta foi resolta, escribe [RESOLTA] no título da mesma.
-- Si tu pregunta ha sido respondida, escribe [SOLUCIONADO] en el título de la misma.
-- Se a túa pregunta foi resolta, escribe [RESOLTA] no título da mesma.
#7
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
views/Books/_child.php
controllers/BooksController.php
AuthorsBooks model
AJAX--customFunctions.js
AJAX fails in line
It's what I need to get it!!. I need ideas!
Thanks.
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.
-- If your question has been resolved, write [SOLVED] in the title of it.
-- Si tu pregunta ha sido respondida, escribe [SOLUCIONADO] en el título de la misma.
-- Se a túa pregunta foi resolta, escribe [RESOLTA] no título da mesma.
-- Si tu pregunta ha sido respondida, escribe [SOLUCIONADO] en el título de la misma.
-- Se a túa pregunta foi resolta, escribe [RESOLTA] no título da mesma.
#8
Posted 16 January 2013 - 11:17 AM
Finally revolved.
I did following this Example for refresh the chil CGridView and go.
Thanks you all!!
I did following this Example for refresh the chil CGridView and go.
Thanks you all!!
-- If your question has been resolved, write [SOLVED] in the title of it.
-- Si tu pregunta ha sido respondida, escribe [SOLUCIONADO] en el título de la misma.
-- Se a túa pregunta foi resolta, escribe [RESOLTA] no título da mesma.
-- Si tu pregunta ha sido respondida, escribe [SOLUCIONADO] en el título de la misma.
-- Se a túa pregunta foi resolta, escribe [RESOLTA] no título da mesma.
Share this topic:
Page 1 of 1

Help













