PDA

View Full Version : ایجاد منو (حل شد)



Emir New
یک شنبه 13 بهمن 1392, 09:47 صبح
سلام

من میخوام یه منو مثل منوهای جوملا بسازم باید چکار کنم؟
البته استاد شهرکی یه سری توضیح دادند :


شما کافیه یک جدول برای منوها داشته باشین که یک فیلد parent_id هم داره (از نوع int(11) DEFAULT NULL) و یک relation از جدول به خودش بزنید (فیلد parent_id به فیلد id وصل بشه). حالا میتونید به راحتی منوها و زیرمنوها رو بصورت ساختار درختی تولید کنید و با یک تابع بازگشتی، منوها رو نمایش بدین و هرموقع یک منو، دارای زیرمنو بود، دوباره تابع رو توی خودش صدا بزنید تا زیرمنوها رو هم نشون بده.

با توجه به این که توضیحات ایشان واضح هست ولی هنوز نمی دونم چرا موضوع برای من گنگ هست
اگه میشه یکم بیشتر توضیح بدید ممنون میشم

MMSHFE
یک شنبه 13 بهمن 1392, 17:58 عصر
این migration رو اجرا کنید:


<?php
class m140202_171842_create_menu_table extends CDbMigration {
public function safeUp() {
// Create the tbl_menu table
$this->createTable('tbl_menu',
array (
'id'=>'pk',
'href'=>'varchar(255) NOT NULL',
'urltext'=>'varchar(255) NOT NULL',
'blank'=>'tinyint(1) NOT NULL',
'parent_id'=>'int(11) DEFAULT NULL',
), 'ENGINE=InnoDB'
);
// The tbl_menu.parent_id is a reference to tbl_menu.id
$this->addForeignKey('fk_menu_parent', 'tbl_menu', 'parent_id', 'tbl_menu', 'id', 'CASCADE', 'CASCADE');
}
public function safeDown() {
$this->dropForeignKey('fk_menu_parent', 'tbl_menu');
$this->dropTable('tbl_menu');
}
}

تا جدول tbl_menu برای شما ساخته بشه. توی این جدول فیلد href مشخص کننده action منو، فیلد urltext متن منو، فیلد blank یک مقدار boolean (صفر = بازشدن در همان صفحه و 1 = بازشدن در صفحه جدید) و parent_id هم مشخص کننده منوی والد و کلید خارجی به فیلد id همین جدول هست و منوهای ریشه، فیلد parent_id اونها null خواهد بود. خوب حالا با Gii برای این جدول مدل بسازین و چک کنید که relation اینطوری تنظیم شده باشه:


public function relations()
{
return array(
'parent' => array(self::BELONGS_TO, 'Menu', 'pid'),
'submenus' => array(self::HAS_MANY, 'Menu', 'pid'),
);
}

با این relationها میتونید ازطریق model->parent$ به منوی والد یک منو و ازطریق model->submenus$ به منوهای فرزندش دسترسی پیدا کنید. تنها کار باقیمانده، ساخت منوها توی View هست که یک تابع بازگشتی ساده لازم داره. اگه باز هم جایی ابهام داشت، بفرمایید تا بیشتر توضیح بدم.

Emir New
یک شنبه 20 بهمن 1392, 23:30 عصر
سلام استاد شهرکی
من همون طوری که شما گفتید عمل کردم و کلید خارجی رو ساختم
ولی وقتی می خوام یه رکورد به جدولم اضافه کنم با پیغام خطای زیر مواجه میشم


CDbCommand failed to execute the SQL statement: SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or update a child row: a foreign key constraint fails (`shop`.`tbl_categories`, CONSTRAINT `fk_categories_parent` FOREIGN KEY (`parent_id`) REFERENCES `tbl_categories` (`id`) ON DELETE CASCADE ON UPDATE CASCADE). The SQL statement executed was: INSERT INTO `tbl_categories` (`parent_id`, `level`, `publish`, `create_user_id`, `update_user_id`, `title`, `access`, `meta`, `meta_desc`) VALUES (:yp0, :yp1, :yp2, :yp3, :yp4, :yp5, :yp6, :yp7, :yp8)

Emir New
دوشنبه 21 بهمن 1392, 10:25 صبح
کسی نیست مرا یاری کند؟

Tarragon
دوشنبه 21 بهمن 1392, 15:02 عصر
شما الان باید یه مقدار رو برای parent_id وارد کنید که ایدی یه رکورد تو همون جدول باشه در ضمن شما بجای id اومدید از parent_id استفاده کردید. ساختار کلید خارجی اینجوریه که مثلا : می گن مدرسه شاهد جزو آموزش و پرورش ناحیه 2کرمان هستش. این یعنی برای مدرسه شاهد یه parent_id وجود داره که به کد "3802" که ایدی ناحیه 2 کرمان هستش وصل می شه این که دلیل نمیشه واسه خود مدرسه هم از کد 3802 استفاده کنیم!

Emir New
دوشنبه 21 بهمن 1392, 19:03 عصر
حرف شما کاملا درست
من میگریشن رو اینطوری نوشتم


$this->createTable('tbl_categories', array(
'id' => 'pk',
'parent_id' => 'int(10) DEFAULT NULL',
'title'=> 'string NOT NULL',
'level'=> 'int(10) DEFAULT NULL',


),
'ENGINE=InnoDB'
);
$this->addForeignKey('fk_categories_parent', 'tbl_categories', 'parent_id' , 'tbl_categories', 'id');

MMSHFE
دوشنبه 21 بهمن 1392, 20:13 عصر
اولاً سایز int رو همون مقدار ثابت 11 درنظر بگیرین. ثانیاً Foreign Key رو با ذکر نوع عملیات زمان Update و Delete ایجاد کنید:

$this->addForeignKey('fk_categories_parent', 'tbl_categories', 'parent_id', 'tbl_categories', 'id', 'CASCADE', 'CASCADE');

Emir New
سه شنبه 22 بهمن 1392, 01:46 صبح
سلام
استاد من با استفاده از ارتباط ها نتونستم یک لیست رو تولید کنم
ولی بدون ارتباط پیاده سازی کردم ولی به دلم نمیشه این کار می خوام حتما با ارتباط ها این کار رو انجام بدم
بعد از کلی جستجو تو سایت ها تکه کد زیر رو پیدا کردم

public static function getCategoryTree() {

$subitems = array();
if($this->childs)
foreach($this->childs as $child)
{
$subitems[] = $child->getListed();
}
$returnarray = array($this->id => $this->title);
if($subitems != array())
$returnarray = array_merge($returnarray, array('items' => $subitems));
return $returnarray;
}

ولی من به هدفم نرسیدم
میشه یه راهنمایی بکنید ؟

Emir New
سه شنبه 22 بهمن 1392, 10:58 صبح
این تابعی هست که خودم نوشتم گذاشتم اگه مشکلی دارم بهم بگید


public function getCategoryTree($parent=1, $level=0) {
$list = array();
$criteria = new CDbCriteria;
$criteria->condition='parent_id=:id';
$criteria->params=array(':id'=>$parent);
$data = Categories::model()->findAll($criteria);
foreach ($data as $key)
{
$str_level = str_repeat('>', $level);
$list[$key->id]= $str_level.$key->title;
$list =array_merge($list,$this->getCategoryTree($key->id, $key->level));
}
return $list;
}

Emir New
سه شنبه 22 بهمن 1392, 13:08 عصر
یه مسئله دیگه
اگر بخواهیم مقداری از یک فانکشن بگیری مثل فانکشن status که تو مثال استاد بود و توی gridview نمایش بدیم باید چطور عمل کنیم ؟
و یه اشکال دیگه این که وقتی من ارایه list رو تو dropdown چاپ می کنم value مقدارش برابر با تعداد تکرار ها هست ولی من می خوام value برابر با فیلد id از جدولم باشه باید چکار کنم ؟

shpegah
چهارشنبه 23 بهمن 1392, 09:35 صبح
شما کافیه در actionIndex در فایل کنترلر پرنتتون اینطور عمل کنید


$dataProvider=new CActiveDataProvider('parent',array('criteria'=>array('with'=>array('submenus'));

Emir New
چهارشنبه 23 بهمن 1392, 20:10 عصر
خب تا بعی که من نوشته بودم یه مشکلی داشت که اصلاحش کردم و این هم اصلاح شده تابع


public function getCategoryTree($parent=1, $level=0) {
$list = array();
$criteria = new CDbCriteria;
$criteria->condition='parent_id=:id';
$criteria->params=array(':id'=>$parent);
$data = Categories::model()->findAll($criteria);

foreach ($data as $key)
{
$str_level = str_repeat('>', $level);
$list[] = array('value'=>$key->id, 'label' => $str_level.$key->title);
$list =array_merge($list,$this->getCategoryTree($key->id, $key->level));
}
return $list;
}

ومشکلی که با خودن اون تو dropdownداشتم این طوری بر طرف میشه


$data = CHtml::listData($model->CategoryTree,'value','label');
echo $form->DropDownList($model,'parent_id',$data);

من این پست رو گذاشتم تا اگر کسی مثل من مشکل داشت حداقل مشکلش حل بشه