سلام استاد
من این آرایه رو دارم و میخوام عناصرش برای فرم مدل بصورت چک باکس نشون داده بشه.
$tags= $model->getTagsOptions();
<div class="row">
<?php echo $form->labelEx($model,'tags',array('class'=>'col-sm-2 control-label')); ?>
<div class="col-sm-4">
<?php echo $form->checkBox($model,'tags',array('class'=>'form-control')); ?>
</div>
<div class="col-sm-4">
<?php echo $form->error($model,'tags',array('class'=>'alert alert-danger')); ?>
</div>
</div>
لطفا راهنمایی کنید.
متشکرم.
شما توی فیلد tags چطوری میخواین مقادیر رو ذخیره کنید؟ tags یه Relation هست یا فیلد معمولیه؟
tags یه فیلد معمولیه.
من این کارو انجام دادم:
<div class="row">
<div class="col-sm-4">
<?php echo $form->checkBoxList($model,'tags',$model->getTagsOptions()); ?>
</div>
</div>
الآن چک باسهایی که ساخته شدن کدشون به این شکله:
کد:
<span id="AssignForm_tags">
<input id="AssignForm_tags_0" type="checkbox" name="AssignForm[tags][]" value="1">
<label for="AssignForm_tags_0">برچسب اول</label>
<br>
<input id="AssignForm_tags_1" type="checkbox" name="AssignForm[tags][]" value="2">
<label for="AssignForm_tags_1">برچسب دوم</label>
</span>
خوب شما چطوری میخواین توی یک فیلد معمولی مقدار چندتا TextBox تعریف کنید؟
فیلدهای tags و posts آرایه هستند و آیدیهای برچسبهای انتخاب شده برای اختصاص دادن به پستهای انتخاب شده را، به اکشن assign ارجاع میدن.
مدل AssignForm:
class AssignForm extends CFormModel
{
public $tags=array();
public $posts=array();
public function rules()
{
return array(
array('tags, posts', 'safe'),
);
}
public function attributeLabels()
{
return array(
'tags'=> 'برچسب ها',
'posts'=> 'پست ها'
);
}
public function getTagsOptions() {
return CHtml::listData(Tags::model()->findAll(
array(
'select'=> 'id, name',
'condition'=> 'confirm=1',
'order'=> 'name',
)
), 'id', 'name');
}
public function getPostsOptions() {
return CHtml::listData(Posts::model()->findAll(
array(
'select'=> 'id, title',
'condition'=> 'confirm=1',
'order'=> 'title',
)
), 'id', 'title');
}
}
کد:
array
(
'AssignForm' => array
(
'tags' => array
(
0 => '1'
1 => '2'
)
'posts' => array
(
0 => '4'
1 => '1'
2 => '2'
3 => '3'
)
)
)
حالا چطوری اینا رو اختصاص بدم؟
خوب شما بعد از اینکه مقادیر رو گرفتین، باید براساس هرکدوم از اونها یک رکورد توی جدول واسط بسازین. مثال:
foreach($model->tags as $tag) {
$postTag = new Posttags;
$postTag->post_id = $_GET['pid'];
$postTag->tag_id = $tag;
$postTag->save();
}
البته کد بالا خیلی کلیه و باید بر اساس سیستم خودتون تغییرش بدین.
این کد رو برا اختصاص برچسبها نوشتم. وقتی جدول posttag خالی و بدون مقدار است اختصاص برچسب بدرستی انجام میشه ولی وقتی جدول از قبل مقدارهایی داره، خطا میده.
public function actionAssign() {
$model= new AssignForm;
if(isset($_POST['AssignForm'])){
//Tools::debug($_POST,true);
$tags= $_POST['AssignForm']['tags'];
$posts= $_POST['AssignForm']['posts'];
$tagsCount=count($tags);
$postsCount=count($posts);
$oldPostTags= Posttag::model()->findAll(array('select'=>'post_id, tag_id'));
if($oldPostTags){
foreach($oldPostTags as $oldPostTag){
//Tools::debug($oldPostTags,true);
for($i=0;$i<$tagsCount;$i++){
for($j=0;$j<$postsCount;$j++){
if($oldPostTag->tag_id!=(int)$tags[$i] && $oldPostTag->post_id!= (int)$posts[$j]){
$newPosttags= new Posttag;
$newPosttags->tag_id= (int)$tags[$i];
$newPosttags->post_id= (int)$posts[$j];
$newPosttags->confirm= 1;
$newPosttags->save();
}
}
}
}
Yii::app()->user->setFlash('message', 'برچسب های پست ها با موفقیت ثبت شدند.');
}
else{
for($i=0;$i<$tagsCount;$i++){
for($j=0;$j<$postsCount;$j++){
$newPosttags= new Posttag;
$newPosttags->tag_id= (int)$tags[$i];
$newPosttags->post_id= (int)$posts[$j];
$newPosttags->confirm= 1;
$newPosttags->save();
}
}
Yii::app()->user->setFlash('message', 'برچسب های پست ها با موفقیت ثبت شدند.');
}
}
$this->render('assign', compact('model'));
}
خطا اینه:
کد:
خطای CDbCommand در اجرای SQL statement: SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicata du champ '1-2' pour la clef 'PRIMARY'. The SQL statement executed was: INSERT INTO `posttag` (`confirm`, `post_id`, `tag_id`) VALUES (:yp0, :yp1, :yp2)
چطوری چک کنم که اگه رکورد جدید با یکی از رکوردهای قبلی برابر بود، در جدول درج نشود؟
البته در کد بالا نوشتم ولی مشکل داره و میخوام بدونم روش بهتری وجود داره برای این کار؟
خوب این کلیدها از قبل وجود دارن. شما یا باید موقع تعریف تگها، همه تگهای قبلی رو حذف کنید و دوباره تگها رو ثبت کنید و یا قبل از ثبت تگ چک کنید اگه وجود نداشت، بعد ثبت کنید.
بصورت زیر قبل از اختصاص دادن، رکوردهای قبلی رو حذف کردم و برچسبهای جدید رو ثبت کردم.
$oldPostTags= Posttag::model()->findAll(array('select'=>'post_id, tag_id'));
if($oldPostTags){
foreach ($oldPostTags as $oldPostTag) {
$oldPostTag->delete();
}
for($i=0;$i<$tagsCount;$i++){
for($j=0;$j<$postsCount;$j++){
$newPosttags= new Posttag;
$newPosttags->tag_id= (int)$tags[$i];
$newPosttags->post_id= (int)$posts[$j];
$newPosttags->confirm= 1;
$newPosttags->save();
}
}
Yii::app()->user->setFlash('message', 'برچسب های پست ها با موفقیت ثبت شدند.');
}
else{
for($i=0;$i<$tagsCount;$i++){
for($j=0;$j<$postsCount;$j++){
$newPosttags= new Posttag;
$newPosttags->tag_id= (int)$tags[$i];
$newPosttags->post_id= (int)$posts[$j];
$newPosttags->confirm= 1;
$newPosttags->save();
}
}
Yii::app()->user->setFlash('message', 'برچسب های پست ها با موفقیت ثبت شدند.');
}
ولی میدونم که این راه حل کاملی نیست. بهتر بود قبل از درج چک میکردم.
متشکرم.
foreach($posts as $post_id => $post_value) {
Posttag::model()->deleteAllByAttributes(compact('post_id'));
foreach($tags as $tag_id => $tag_value) {
$postTag = new Posttag;
$postTag->post_id = $post_id;
$postTag->tag_id = $tag_id;
$postTag->confirm = 1;
$postTag->save();
}
}
Yii::app()->user->setFlash('message', 'برچسب های پست ها با موفقیت ثبت شدند.');
لطفا خطوط 1 و 2 رو توضیح بدین.
خط 1 که یه حلقه foreach برای تمام پستهایی که با چک باکس ارسال شدن، میسازه و خط 2 تمام تگهای اون post_id رو حذف میکنه.
توضیح: دو تا کد زیر مثل هم هستن:
compact('post_id')
array('post_id' => $post_id)