Reputation: 5
I'm having a problem creating something for my application. What i already have is a CJuiTabs system with a form in each tab. The number and values/names of the tabs is defined by a number of tinyInt columns in an another table in my database. The value of the tab is submitted with the form as a hidden field.
So now if you go to a view with an id you have already submitted a record with, you will be able to update that record, but you are not able to create new records with the other tab-values. This is my problem. How do i make the application decide wether to create a new record or update an existing one based on which tab you have selected? If you are updating a record i would like to have the values of the record shown, but if you are creating a new one you should only see blank fields (well, its a rating system, so i guess it is stars not fields).
I guess it chould be done by using AJAX but i'm very much unsure of how to do that.
Game/view:
<?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',
)); ?>
Models/Platform:
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;
}
Controllers/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;
}
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(); ?>
Upvotes: 0
Views: 2901
Reputation: 1782
I'm not sure I get this completely, let me try to see if I get the problem,
You have multiple forms one user can edit, they're all forms to rank one game on different gaming platforms (XBOX, PS2/3, etc..).
If this is the case, in your Game controller:
$rank=ranking::model()->find("create_user_id=$user_id and game_id=$game_id");
will always return the same db entry regardless of gaming platform (provided there is an entry) You would need to use something along the lines of
$rank=ranking::model()->find("create_user_id=$user_id and game_id=$game_id and platform_id=$platform_id");
That covers the saving part but there's also an issue in the displaying. You have:
foreach($tab_list as $key=>$value){
$tabarray["$value"]=array(
'id'=>$key,
'content'=>$this->renderPartial('../ranking/_form',
array('model'=>$ranking, 'key'=>$key),TRUE)
);
In essence, you use the same $ranking model for each tab, so therefore the same (already existing) field inputs, or star ratings.
This is where it gets a little tricky. Ideally you would use Yii's relations To set up your models as Plateforms having multiple Games(MANY_MANY) that have multiple Ratings depending on Plateform/Game combination. Then you could do something along the lines of :
$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)
);
(I'm sparing you the use of 'params'=>array(), but do make it a habit.)
However you don't seem like you've gone that route, so check it out if you want, if not how about changing createRanking() to return an array of rankings corresponding to a platform for a given game using a key=> value where the key is the platform id. Then you could do:
foreach($tab_list as $key=>$value){
$tabarray["$value"]=array(
'id'=>$key,
'content'=>$this->renderPartial('../ranking/_form',
array('model'=>$rankings[$key], 'key'=>$key),TRUE)
);
If you went with that, as far as saving goes, if isset($_GET['Ranking']) then you would use the platform_id to isolate the correct model from the array in order to save it to db (or create a new one if it doesn't exist)
Hope that helps, or at least gets you on the right track.
edit: Added some code, not the best/cleanest solution but it should work and be easy to understand :
Controllers/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/view:
<?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',
)); ?>
Upvotes: 1