2013-04-01 21 views
0

У меня возникла проблема с созданием чего-то для моего приложения. У меня уже есть система CJuiTabs с формой на каждой вкладке. Количество и значения/имена вкладок определяются рядом столбцов tinyInt в другой таблице в моей базе данных. Значение вкладки представляется в виде скрытого поля.Динамическая форма в Yii

Итак, если вы перейдете к представлению с идентификатором, с которым вы уже отправили запись, вы сможете обновить эту запись, но вы не сможете создавать новые записи с другими значениями табуляции. Это моя проблема. Как заставить приложение решить, создать новую запись или обновить существующую, на основе выбранной вами вкладки? Если вы обновляете запись, я бы хотел, чтобы значения отображаемой записи были показаны, но если вы создаете новую, вы должны видеть только пустые поля (ну, это рейтинговая система, поэтому я думаю, что это звезды не поля).

Я думаю, что это можно сделать с помощью AJAX, но я очень не уверен, как это сделать.

Game/вид:

<?php 
$tab_list=Platform::getPlatforms(); 
$tabarray=array(); 

// Create Dynamic Tabs 
foreach($tab_list as $key=>$value){ 
    $tabarray["$value"]=array(
     'id'=>$key, 
     'content'=>$this->renderPartial('../ranking/_form', 
      array('model'=>$ranking, 'key'=>$key),TRUE) 
    ); 
}?> 

<?php 
$this->widget('zii.widgets.jui.CJuiTabs',array(
    'tabs'=>$tabarray, 
    'options'=>array(
     'collapsible'=>true, 
    ), 
    'id'=>'categorytabs', 
)); ?> 

Модели/Платформа:

const PC = 1; 
    const Mac = 2; 
    const XBOX = 3; 
    const XBOX360 = 4; 
    const PS2 = 5; 
    const PS3 = 6; 
    const PSP = 7; 
    const PSVITA = 8; 
    const Wii = 9; 
    const WiiU = 10; 
    const NintendoDS = 11; 
    const NintendoDS3 = 12; 
... 
    public function getPlatforms() 
    { 
     $id = Yii::app()->request->getQuery('id'); 
     $platform = Platform::model()->findByPk($id); 
     $platforms = array(); 
     if ($platform -> pc == 1) 
     { 
      $platforms[self::PC] = "PC"; 
     } 
     if ($platform -> xbox == 1) 
     { 
      $platforms[self::XBOX] = 'XBOX'; 
     } 
     if ($platform -> xbox360 == 1) 
     { 
      $platforms[self::XBOX360] = "XBOX 360"; 
     } 
     if ($platform -> ps2 == 1) 
     { 
      $platforms[self::PS2] = "PS2"; 
     } 
     if ($platform -> ps3 == 1) 
     { 
      $platforms[self::PS3] = 'PS3'; 
     } 
     if ($platform -> psp == 1) 
     { 
      $platforms[self::PSP] = "PSP"; 
     } 
     if ($platform -> psVita == 1) 
     { 
      $platforms[self::PSVITA] = 'PS VITA'; 
     } 
     if ($platform -> wii == 1) 
     { 
      $platforms[self::Wii] = "Wii"; 
     } 
     if ($platform -> wiiU == 1) 
     { 
      $platforms[self::WiiU] = "Wii U"; 
     } 
     if ($platform -> nintendoDS == 1) 
     { 
      $platforms[self::NintendoDS] = 'Nintendo DS'; 
     } 
     if ($platform -> nintendoDS3 == 1) 
     { 
      $platforms[self::NintendoDS3] = 'Nintendo DS3'; 
     }  
     return $platforms; 
    } 

Контроллеры/GameController:

public function actionView($id) 
    { 
     ... 
     $ranking=$this->createRanking($model); 
     ... 
     } 

    protected function createRanking($model) 
    { 
     $user_id=Yii::app()->user->getId(); 
     $game_id=$model->id; 
     $rank=ranking::model()->find("create_user_id=$user_id and game_id=$game_id"); 

     if($rank===null){ 
     $ranking=new Ranking; 
     } 
     else{ 
     $ranking=$rank; 
     } 

     if(isset($_POST['Ranking'])) 
     { 
      $ranking->game_id=$model->id; 
      $ranking->attributes=$_POST['Ranking']; 

      $valid = $ranking->validate(); 
      if ($valid) 
      { 
       $ranking->save(false); 
       $this->redirect(array('index')); 
      } 
     } 
     return $ranking; 
    } 

Рейтинг/_form:

<?php $form=$this->beginWidget('CActiveForm', array(
    'id'=>'ranking-form', 
    'enableAjaxValidation'=>false, 
)); ?> 

    <p class="note">Fields with <span class="required">*</span> are required.</p> 

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

    <?php echo $form->hiddenField($model, 'platform_id', array('value' => $key)); ?> 

    <div class="row"> 
     <?php echo $form->labelEx($model,'overall'); ?> 
     <?php $this->widget('CStarRating',array(
      'model'=>$model, 
      'attribute' => 'overall', 
     )); ?> 
     <?php echo $form->error($model,'overall'); ?> 
    </div> 
    <br/> 

    <div class="row"> 
     <?php echo $form->labelEx($model,'graphics'); ?> 
     <?php $this->widget('CStarRating',array(
      'model'=>$model, 
      'attribute' => 'graphics', 
     )); ?> 
     <?php echo $form->error($model,'graphics'); ?> 
    </div> 
    <br/> 

    <div class="row"> 
     <?php echo $form->labelEx($model,'sound'); ?> 
     <?php $this->widget('CStarRating',array(
      'model'=>$model, 
      'attribute' => 'sound', 
     )); ?> 
     <?php echo $form->error($model,'sound'); ?> 
    </div> 
    <br/> 

    <div class="row"> 
     <?php echo $form->labelEx($model,'gameplay'); ?> 
     <?php $this->widget('CStarRating',array(
      'model'=>$model, 
      'attribute' => 'gameplay', 
     )); ?> 
     <?php echo $form->error($model,'gameplay'); ?> 
    </div> 
    <br/> 

    <div class="row"> 
     <?php echo $form->labelEx($model,'lastingApp'); ?> 
     <?php $this->widget('CStarRating',array(
      'model'=>$model, 
      'attribute' => 'lastingApp', 
     )); ?> 
     <?php echo $form->error($model,'gameplay'); ?> 
    </div> 
    <br/> 

    <div class="row buttons"> 
     <?php echo CHtml::submitButton($model->isNewRecord ? 'Create' : 'Save'); ?> 
    </div> 

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

ответ

1

Я не уверен, что полностью понял, позвольте мне попытаться выяснить, есть ли у меня проблема:

У вас есть несколько форм, которые один пользователь может редактировать, они все формы, чтобы оценивать одну игру на разных игровых платформах (XBOX, PS2/3 и т. Д.).

Если это так, то в контроллере игры:

$rank=ranking::model()->find("create_user_id=$user_id and game_id=$game_id"); 

всегда будет возвращать один и тот же вход дБ независимо от игровой платформы (при условии, есть запись) Вы должны были бы использовать что-то вдоль линий от

$rank=ranking::model()->find("create_user_id=$user_id and game_id=$game_id and platform_id=$platform_id"); 

Это защищающая часть, но есть проблема при отображении. У вас есть:

foreach($tab_list as $key=>$value){ 
    $tabarray["$value"]=array(
     'id'=>$key, 
     'content'=>$this->renderPartial('../ranking/_form', 
      array('model'=>$ranking, 'key'=>$key),TRUE) 
    ); 

В сущности, вы используете ту же модель ранжирования $ для каждой вкладки, так поэтому одни и те же (уже существующие) входы поля или звезды рейтинги.

Это то, где он становится немного сложнее. В идеале вы бы использовали Yii's relations Чтобы настроить свои модели как Plateforms с несколькими играми (MANY_MANY), которые имеют несколько рейтингов в зависимости от комбинации Plateform/Game. Тогда вы могли бы сделать что-то вдоль линий:

$platforms = Plateform::model()->findAll(array(
      'with'=>array(             
       'rankings'=>array(
         'condition'=>'game_id=$game_id AND platform_id=t.id')) //t refers to platform in Yii < 1.1.13. For Yii >= 1.1.13 check version update logs 

)); 
    foreach($platforms as $platform){ 
     $tabarray[$platform->title]=array(//called it title arbitrarily, could be anything 
      'id'=>$platform->id, 
      'content'=>$this->renderPartial('../ranking/_form', 
       array('model'=>$platform->rankings[0], 'key'=>$platform->id),TRUE) 
     ); 

(я избавляя использование «Params» => Array(), но сделать это привычкой.)

Однако вы дону Похоже, что вы пошли по этому маршруту, поэтому проверьте, хотите ли вы, если не хотите, как изменить createRanking(), чтобы вернуть массив ранжировок, соответствующих платформе для данной игры, с использованием значения key =>, где ключ это идентификатор платформы.Тогда вы могли бы сделать:

foreach($tab_list as $key=>$value){ 
     $tabarray["$value"]=array(
      'id'=>$key, 
      'content'=>$this->renderPartial('../ranking/_form', 
       array('model'=>$rankings[$key], 'key'=>$key),TRUE) 
     ); 

Если вы пошли с тем, насколько экономия идет, если Исеть ($ _ GET [ «Рейтинг»]), то вы будете использовать platform_id изолировать нужную модель из массива в чтобы сохранить его в db (или создать новый, если он не существует)

Надеюсь, что это поможет или, по крайней мере, поможет вам на правильном пути.

редактировать: Добавлен некоторый код, не самое лучшее/чистое решение, но он должен работать и быть легко понять:

Контроллеры/GameController:

public function actionView($id) 
{ 
    ... 
    $this->createRanking($model); 
    $rankings = $this->getRankingList(); 
    ... 
} 

//add this function 
protected function getRankingList($gid,$uid) 
    { 
     $tab_list=Platform::getPlatforms(); 
     $rankings = array(); 
     foreach($tab_list as $key=>$value) 
     { 
      $rank=Ranking::model()->find("create_user_id=$user_id and game_id=$game_id and platform_id=$key"); 
      if(empty($rank)) 
       $rank = new Ranking; 
      $rankings[$key]= $rank; 
     } 
     return $rankings; 
    } 

Game/вид:

<?php 
$tab_list=Platform::getPlatforms(); 
$tabarray=array(); 

// Create Dynamic Tabs 
foreach($tab_list as $key=>$value){ 
    $tabarray["$value"]=array(
     'id'=>$key, 
     'content'=>$this->renderPartial('../ranking/_form', 
      array('model'=>$rankings[$key], 'key'=>$key),TRUE) 
    ); 
}?> 

<?php 
$this->widget('zii.widgets.jui.CJuiTabs',array(
    'tabs'=>$tabarray, 
    'options'=>array(
     'collapsible'=>true, 
    ), 
    'id'=>'categorytabs', 
)); ?> 
+0

Спасибо за ваш ответ, и это очень помогло мне. Я думаю, что пойдет с последним методом, но я не уверен, как вернуть массив ранжирования из createRanking(). – Deram

+0

Так что это было бы большой помощью, если бы кто-нибудь мог дать мне быстрый пример или намек на это :) – Deram

+0

@Deram отредактировал мой ответ с дополнительным кодом :) –

Смежные вопросы