首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Yii模型与另外两个模型的ManyToMany关系

Yii模型与另外两个模型的ManyToMany关系
EN

Stack Overflow用户
提问于 2014-03-13 22:41:10
回答 1查看 343关注 0票数 1

首先,我对任何书面错误表示歉意。

好吧,让我解释一下

我有三个模型,音乐模型,MusicLink模型和MusicGenre模型。在MusicController中,我有一个动作"Create“。

然后,在表单上,我有了“音乐模型”的字段,还有另外两个字段。Select2是一个小部件,它允许您选择多个类型,以及jQuery插件"RelCopy“可以动态克隆的链接(音乐文件的urls)的另一个字段(最多可达6个字段)。

音乐可以有多种类型,也可以有几个链接。

我的问题是如何保存所有这些字段,正确吗?希望我说的够清楚了。

下面是我到目前为止掌握的代码:

MusicController.php

代码语言:javascript
复制
/**
* 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

代码语言:javascript
复制
<?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模型,则保存音乐,但不保存这两个模型。

我正在使用YII1.1.14版本,与YiiBoostrap和YiiBoilerplate一起使用

以下是插件的链接:

http://www.andresvidal.com/labs/relcopy.html

http://ivaynberg.github.io/select2/

http://yiibooster.clevertech.biz/

EN

回答 1

Stack Overflow用户

发布于 2014-06-19 10:57:10

您可以使用由sluderitz开发的埃斯维利行为组件来保存相关的模型,您可以在这里下载

安装上述扩展后,您可以这样做

代码语言:javascript
复制
$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是一个关系名称。

保存多个相关模型使用上述扩展的详细解决方案可在我的博客文章中找到。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/22392527

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档