首先,我为编写的任何错误道歉
好吧,让我解释一下
我有3个模型,音乐模型,MusicLink模型和MusicGenre模型。 在MusicController中,我有动作"创建"。
然后,在表单上,我有音乐模型和其他2个字段。 选择2一个小部件,可以让你选择多个类型,另一个字段用于链接(音乐文件的网址),可以通过jQuery插件动态克隆#34; RelCopy" (最多6个字段)
音乐可以有多种类型,以及多个链接
我的问题是如何正确保存所有这些字段?我希望我足够清楚。
这是我到目前为止的代码:
MusicController.php
/**
* Creates a new model.
* If creation is successful, the browser will be redirected to the 'view' page.
*/
public function actionCreate()
{
$music = new Music;
$genre = new MusicGenre;
$link = new MusicLink;
// Uncomment the following line if AJAX validation is needed
// $this->performAjaxValidation($music);
if(isset($_POST['Music']) && isset($_POST['MusicGenre']))
{
CActiveForm::validate($genre);
CActiveForm::validate($link);
$music->attributes=$_POST['Music'];
if($music->save()){
foreach(explode(',',$_POST['MusicGenre']['genre_id']) as $gen)
{
$genre=new MusicGenre;
$genre->genre_id = $gen;
$genre->music_id = $music->id;
if($genre->validate())
$valid[]=true;
else
$valid[]=false;
}
foreach($_POST['Music']['links'] as $lnk)
{
$link=new MusicLink;
$link->link = $lnk;
$link->music_id = $music->id;
$link->host = MusicLink::model()->getHoster($lnk);
if($link->validate())
$valid[]=true;
else
$valid[]=false;
}
if(!in_array(false,$valid)){
$genre->save();
$link->save();
$this->redirect(array('view','id'=>$music->id));
}
}
}
$this->render('create',array(
'music'=>$music,
'genre'=>$genre,
'link'=>$link,
));
}
/**
* Updates a particular model.
* If update is successful, the browser will be redirected to the 'view' page.
* @param integer $id the ID of the model to be updated
*/
public function actionUpdate($id)
{
$music = $this->loadModel($id);
$genre = MusicGenre::model()->findByAttributes(array('music_id'=>$id));//new MusicGenre;
$link = MusicLink::model()->findAll('music_id=:mID',array(':mID'=>$id));;
// Uncomment the following line if AJAX validation is needed
// $this->performAjaxValidation($music);
if(isset($_POST['Music']) && isset($_POST['MusicGenre']))
{
$music->attributes=$_POST['Music'];
if($music->save()){
foreach(explode(',',$_POST['MusicGenre']['genre_id']) as $gen)
{
//$genre = MusicGenre::model()->findByAttributes(array('music_id'=>$music->id));
$genre->genre_id = Genre::model()->nameToId($gen);
$genre->music_id = $music->id;
$valid[]=$genre->save();
}
foreach($_POST['Music']['links'] as $lid => $lnk)
{
$link = MusicLink::model()->find('music_id=:mID AND id=:lID',array(':mID'=>$music->id,':lID'=>$lid));
if($link == null){
$link=new MusicLink;
$link->link = $lnk;
$link->music_id = $music->id;
$link->host = MusicLink::model()->getHoster($lnk);
$valid[]=$link->save();
}else if($link->link != $lnk){
$link->link = $lnk;
$link->music_id = $music->id;
$link->host = MusicLink::model()->getHoster($lnk);
$valid[]=$link->save();
}
}
if(!in_array(false,$valid))
$this->redirect(array('view','id'=>$music->id));
}
}
$this->render('update',array(
'music'=>$music,
'genre'=>$genre,
'link'=>$link,
));
}
\ music_form.php
<?php $form=$this->beginWidget('bootstrap.widgets.TbActiveForm',array(
'id'=>'music-form',
'type' => 'horizontal',
'customCssErrors' => 'inline',
'enableAjaxValidation'=>false,
)); ?>
<fieldset>
<legend>
<?php echo $music->isNewRecord ? Yii::t('b2r','Create Music') : Yii::t('b2r','Update Music') ;?>
</legend>
<p class="help-block well well-small"><?php echo Yii::t('b2r','Fields with <span class="required">*</span> are required.'); ?>
</p>
<?php
$models = array($music,$genre);
if (is_array($link))
foreach ($link as $lnk)
$models[] = $lnk;
else
$models[] = $link;
//die(var_dump($models));
?>
<?php echo $form->errorSummary($models); ?>
<div class="span6 first">
<?php echo $form->textFieldRow($music,'artist',array('class'=>'span12','maxlength'=>255)); ?>
<?php echo $form->textFieldRow($music,'title',array('class'=>'span12','maxlength'=>255)); ?>
<?php echo $form->textAreaRow($music,'desc',array('rows'=>3, 'cols'=>60, 'class'=>'span12')); ?>
<?php echo $form->select2Row($genre, 'genre_id', array(
'asDropDownList' => false,
'val' => MusicGenre::model()->getMusicGenresNames($music->id),
'options' => array(
'data' => Genre::model()->getGenres(),
'placeholder' => 'Escreva um ou mais categorias, separadas por virgulas',
'containerCssClass' => 'span12',
'tokenSeparators' => array(','),
'multiple'=>true,
'width'=>'none',
'initSelection' => 'js:function (element, callback) {
var val = [];
$(element.val().split(",")).each(function () {
val.push({id: this, text: this});
});
callback(val);
}'
)
)); ?>
<?php echo $form->maskedTextFieldRow($music,'length',array('mask'=>'99:99?:99','htmlOptions'=>array('class'=>'span12','maxlength'=>8)),array('hint'=>Yii::t('b2r','No formato {f1} ou {f2}',array('{f1}'=>'<i class="label label-info">MM:SS</i>','{f2}'=>'<i class="label label-info">HH:MM:SS</i>')))); ?>
<?php echo $form->maskedTextFieldRow($music,'size',array('mask'=>'?~~~.~~','charMap'=>array('~'=>'^[0-9]+(\.)?[0-9]{0,2}$'),'placeholder'=>'0','htmlOptions'=>array('class'=>'span12','maxlength'=>8)),array('hint'=>Yii::t('b2r','No formato {f1} ou {f2}',array('{f1}'=>'<i class="label label-info">xx.xx</i>','{f2}'=>'<i class="label label-info">xxx.xx</i>')))); ?>
</div>
<div class="span6">
<div class="controls">
<ul class="thumbnails">
<li class="span5">
<a class="thumbnail">
<?php echo CHtml::image('/images/capa.gif',Yii::t('b2r','Previsualização da Imagem'),
array('id'=>'previewHolder','width'=>'170px','height'=>'170px')); ?>
</a>
</li>
</ul>
</div>
<?php echo $form->textFieldRow($music,'image',array('class'=>'span8','maxlength'=>255),array('controlCss'=>'skipcopy','append'=>'<a href="#" id="findcover" data-toggle="tooltip" title="'.Yii::t('b2r','Procurar capa no Google').'"><i class="icon-circle-arrow-right"></i></a>')); ?>
<?php
if ($music->isNewRecord){
echo $form->textFieldRow($link,'link',
array('name'=>'MusicLink[links][0]','value'=>'','maxlength'=>255, 'class'=>'span8'),
array('controlCss'=>'copy clonable','append'=>'<a id="copylink" href="#" rel=".copy"><i class="icon-plus"></i></a> ')
);
}else{
$last = count($link)-1;
foreach ($link as $k => $v)
die(var_dump($link));
$id = (is_null($v)) ? $k : $v->id;
if($k == $last)
echo $form->textFieldRow($v,'link',
array('name'=>'MusicLink[links]['.$id.']','maxlength'=>255, 'class'=>'span8'),
array('controlCss'=>'copy clonable','label'=>'<span class="required">*</span>','append'=>'<a id="copylink" href="#" rel=".copy"><i class="icon-plus"></i></a> ')
);
else
echo $form->textFieldRow($v,'link',
array('name'=>'MusicLink[links]['.$id.']','maxlength'=>255, 'class'=>'span8'),
array('controlCss'=>'clonable')
);
}
?>
<?php
$this->widget('ext.jqrelcopy.JQRelcopy',array(
//the id of the 'Copy' link in the view, see below.
'id' => 'copylink',
//add a icon image tag instead of the text
//leave empty to disable removing
'removeText' => '<i class="icon-remove"></i>',
//htmlOptions of the remove link
'removeHtmlOptions' => array('style'=>'margin-left:2px;padding:3px 10px;','class'=>'btn btn-small btn-danger'),
//options of the plugin, see http://www.andresvidal.com/labs/relcopy.html
'options' => array(
//A class to attach to each copy
'copyClass'=>'newcopy',
// The number of allowed copies. Default: 0 is unlimited
'limit'=>6,
//Option to clear each copies text input fields or textarea
'clearInputs'=>true,
//A jQuery selector used to exclude an element and its children
'excludeSelector'=>'.skipcopy',
//Additional HTML to attach at the end of each copy.
//'append'=>CHtml::tag('span',array('class'=>'hint'),'You can remove this line'),
//'jsAfterNewId' => "if(typeof $(this > input).attr('name') !== 'undefined'){ $(this > input).attr('name', $(this > input).attr('name').replace('new', 'new_'+counter));}",
)
));
?>
</div>
<?php $collapse = $this->beginWidget('bootstrap.widgets.TbCollapse',array('htmlOptions'=>array('class'=>'span12 first'))); ?>
<div class="accordion-group">
<div class="accordion-heading">
<a class="accordion-toggle" data-toggle="collapse"
data-parent="#accordion2" href="#collapseOne">
Avançado
</a>
</div>
<div id="collapseOne" class="accordion-body collapse">
<div class="accordion-inner">
<?php echo $form->textFieldRow($music,'bitrate',array('class'=>'span9')); ?>
</div>
</div>
</div>
<?php $this->endWidget(); ?>
</fieldset>
<div class="form-actions">
<?php $this->widget('bootstrap.widgets.TbButton', array(
'buttonType'=>'submit',
'type'=>'primary',
'label'=>$music->isNewRecord ? Yii::t('b2r','Create') : Yii::t('b2r','Save'),
)); ?>
</div>
<?php $this->endWidget(); ?>
<?php Yii::app()->clientScript->registerScript('script', "
$('#Music_image').change(function() {
$('#previewHolder').attr('src',$(this).val());
});
$('#findcover').click(function() {
var q = $('#Music_artist').val();
q += ' - '+$('#Music_title').val();
q += ' cover';
window.open('https://www.google.pt/search?q='+escape(q)+'&tbm=isch', '_blank');
});
"
, CClientScript::POS_READY);?>
修改
使用此代码,我可以正确保存所有内容,但是,例如,如果我没有选择流派,或者没有输入文件的链接,则只保存音乐。 但是,例如,如果缺少音乐模型的必需字段,以及MusicGenres或MusicLink模型,则验证所有三个模型。 如果错误仅属于MusicGenre或MusicLink模型,则会保存音乐,但不保存这两个模型
我使用Yii版本1.1.14,使用YiiBoostrap和YiiBoilerplate
以下是插件的链接:
http://www.andresvidal.com/labs/relcopy.html
答案 0 :(得分:1)
你可以使用sluderitz开发的esaverelatedbehavior组件保存相关模型,你可以在这里下载
安装上述扩展程序后,您可以这样做
$music->attributes=$_POST['Music'];
if (isset($_POST['MusicGenre']))
{
$music->musicgenre= $_POST['MusicGenre'];
}
if ($music->saveWithRelated('musicgenre'))
$this->redirect(array('view', 'id' => $model->id));
注意:我们可以$music->musicgenre
,因为musicgenre
是关系名称。
我的博客文章中提供了使用上述扩展程序saving multiple related models的详细解决方案。
答案 1 :(得分:0)
好的,现在我知道你想要的。
在create方法中,当您测试generes或链接数组是否有效时,您可以生成错误消息并重定向到更新操作并要求用户插入genres或链接数据。
在actionCreate中:
if($music->save()){
......
if(!in_array(false,$valid)){
$genre->save();
$link->save();
$this->redirect(array('view','id'=>$music->id));
}
else {
Yii::app()->user->setFlash('error',"Some cool warning message");
$this->redirect(array('update','id'=>$music->id)));
}
}
......
在ActionUpdate中执行相同的操作:
........
if(!in_array(false,$valid))
$this->redirect(array('view','id'=>$music->id));
else
Yii::app()->user->setFlash('error',"Some cool warning message");
现在,在更新视图文件(不在_form中)中,您必须显示错误消息:
<?php if(Yii::app()->user->hasFlash('error')):?>
<div class="flash-error">
<?php echo Yii::app()->user->getFlash('error'); ?>
</div>
<?php endif; ?>
&#34; flash-error&#34;定义了默认的CSS。 DIV。请参阅enter link description here。
我希望它可以帮到你。
另一个可能的解决方案可以定义一个阵列,并链接到音乐模型。
然后,在这些变量中分配表格的值,以便调用$ music-&gt; saave。
在音乐模型中,您必须为数组编写validaors规则,并在 beforeSave() afterSave()方法中编写代码以插入genere并链接行。