PDA

View Full Version : درست کردن parent sort



Emir New
جمعه 18 مهر 1393, 13:19 عصر
سلام
من برای خواندن زیر مجموعه یا همون پرنت های Categories از کد زیر استفاده کردم



public function getChildren()
{
$parents = $this->with('Categories')->findAll();
foreach ($parents as $key)
{
$list[$key->id] = str_repeat(' - ', $key->level) . $key->title ;
}
return $list;
}


مشکل من این هست که می خوام از این پرنت ایدی ها به صورت سورت در بیاد مثل جوملا همه پرنت های زیر پدر خودشون ظاهر بشن

-

Emir New
جمعه 18 مهر 1393, 21:08 عصر
من با این کد به خواسته ام رسیدم


public function getfather()
{
$criteria = new CDbCriteria;
$criteria->condition = 'parent_id = 1';
$category=$this->findAll($criteria);
foreach ($category as $key)
{
$this->list[$key->id] = str_repeat(' - ', $key->level) . $key->title ;
if($key->id > 1)
$this->getChildren($key->id);
}
return $this->list;
}
protected function getChildren($id)
{

$criteria = new CDbCriteria;
$criteria->condition = 'parent_id = '.$id;
$children = $this->findAll($criteria);
foreach ($children as $key)
{
$this->list[$key->id] = str_repeat(' - ', $key->level) . $key->title ;
if($key->parent_id > 1)
$this->getChildren($key->id);
}
return;
}

اگه راه بهتری هست من رو راهنمایی کنید که کدهام بهینه باشه

googoli
شنبه 19 مهر 1393, 08:17 صبح
بنظر من این خط اضافه هست


if($key->parent_id > 1)

MMSHFE
شنبه 19 مهر 1393, 21:13 عصر
شما اگه یک ارتباط 1 به n بین دسته بندی با خودش ایجاد کنید، به راحتی میتونید با چنین کدی به خواسته خودتون برسین:

foreach(Categories::model()->findAll(array('condition'=>'parent_id IS NULL','order'=>'name')) as $category) {
// display parent category
if($subCategories = Categories::model()->findAll(array('condition'=>'parent_id=:parentId','params'=>array(':parentId'=>$category->id),'order'=>'name'))) {
foreach($subCategories as $subCategory) {
// display subcategories
}
}
}
یا حتی اگه ترتیب براتون مهم نباشه، خیلی ساده تر میشه کار کنید:

foreach(Categories::model()->findAll('parent_id IS NULL') as $category) {
// display parent category
foreach($category->children as $subCategory) {
// display subcategories
}
}
}
بخش ارتباط در مدل:

class Categories extends CActiveRecord
{
// ...
public function relations()
{
return array(
// ...
'parent' => array(self::BELONGS_TO, 'Categories', 'parent_id'),
'children' => array(self::HAS_MANY, 'Categories', 'parent_id'),
// ...
);
}
// ...
}
حتی اگه ترتیب مهم باشه باز هم میشه با یکسری تغییرات جزئی کار رو با همون مدل انجام بدین:

class Categories extends CActiveRecord
{
// ...
public function relations()
{
return array(
// ...
'parent' => array(self::BELONGS_TO, 'Categories', 'parent_id'),
'children' => array(self::HAS_MANY, 'Categories', 'parent_id', 'order'=>'categories.name'),
// ...
);
}
// ...

public function scopes()
{
return array(
'sort'=>array(
'order'=>'name',
),
);
}
}

foreach(Categories::model()->sortByName()->findAll('parent_id IS NULL') as $category) {
// display parent category
foreach($category->children as $subCategory) {
// display subcategories
}
}
}

حالا اگه خواستین همیشه اطلاعات برای شما مرتب شده باشه میتونید از defaultScope استفاده کنید. اگه مستندات رو به خوبی مطالعه نکنید، مجبور میشین برای کارهایی که خود فریمورک چندین روش در اختیارتون گذاشته، راههای دستی و اکثراً غیر بهینه اختراع کنید.

Emir New
یک شنبه 20 مهر 1393, 01:29 صبح
با تشکر از وقتی که گذاشتید
من کارهایی رو که انجام دادم کامل می گم بلکه به جواب برسم
راه های شما رو امتحان کردم ولی جواب نگرفتم می خوام بدونم کجای کار من اشتباه هست تا اصلاحش کنم

1- این میگریشن من هست


$this->createTable('A0365_categories',
array(
'id'=>'pk',
'parent_id'=>'int(11) DEFAULT NULL',
'level'=>'int(11) unsigned NOT NULL DEFAULT 0',
'path'=>'varchar(255) DEFAULT NULL',
'extension'=>'varchar(50) DEFAULT NULL',
'title'=>'varchar(255) NOT NULL',
'alias'=>'varchar(255) DEFAULT NULL',
'note'=>'varchar(255) DEFAULT NULL',
'description'=>'longtext DEFAULT NULL',
'published'=>'tinyint(1) NOT NULL DEFAULT 0',
'checked_out'=>'int(11) unsigned NOT NULL DEFAULT 0',
'checked_out_time'=>'datetime',
'access'=>'int(11) unsigned NOT NULL DEFAULT 0',
'params'=>'text',
'metadesc'=>'varchar(1024) DEFAULT NULL',
'metakey'=>'varchar(1024) DEFAULT NULL',
'metadata'=>'varchar(2048) DEFAULT NULL',
'created_user_id'=>'int(11) unsigned NOT NULL DEFAULT 0',
'created_time'=>'varchar(25) NOT NULL',
'modified_user_id'=>'int(11) unsigned NOT NULL DEFAULT 0',
'modified_time'=>'varchar(25) NOT NULL',
'hits'=>'int(11) unsigned NOT NULL DEFAULT 0',
'language'=>'char(7) DEFAULT NULL',
),
'ENGINE=InnoDB');
$this->addForeignKey('fk_parent', 'A0365_categories', 'parent_id', 'A0365_categories', 'id', 'CASCADE', 'CASCADE');

$this->insert('A0365_categories',
array(
'parent_id'=>NULL,
'level'=>0,
'title'=>'--بدون مادر--',
'published'=>50,
'access'=>1,
'created_time'=>'2014-10-08',
'modified_time'=>'2014-10-08',
'language'=>'*',
)
);

$this->insert('A0365_categories',
array(
'parent_id'=>1,
'level'=>1,
'title'=>'بدون مجموعه',
'published'=>50,
'access'=>1,
'created_time'=>'2014-10-08',
'modified_time'=>'2014-10-08',
'language'=>'*',
)
);


2-این هم قسمت ارتباط های من


public function relations()
{
// NOTE: you may need to adjust the relation name and the related
// class name for the relations automatically generated below.
return array(
'parent' => array(self::BELONGS_TO, 'Categories', 'parent_id'),
'children' => array(self::HAS_MANY, 'Categories', 'parent_id', 'order'=>'Categories.title'),
);
}


3- این هم تابعی که طبق راهنمایی های شما بکار گرفته شده


public function sub()
{
$test = $this->findAll(array('condition'=>'parent_id IS NULL','order'=>'title'));

foreach($test as $category)
{

//$this->list[$category->id] = str_repeat(' - ', $category->level) . $category->title ;
if($subCategories = $this->findAll(array('condition'=>'parent_id=:parentId', 'params'=>array(':parentId'=>$category->id),'order'=>'title')));

foreach($subCategories as $subCategory) {
$this->list[$subCategory->id] = str_repeat(' - ', $subCategory->level) . $subCategory->title ;

}
}
return $this->list;
}

این هم عکس از دیتابیس و اطلاعات درونش

این همه کاری هست که من کردم ولی باز به جواب دلخواه نمی رسم لطفا راهنماییم کنید

Emir New
یک شنبه 20 مهر 1393, 09:44 صبح
با سلام مجدد
جناب شهرکی من کد رو به صورت زیر ویرایش کردم و به جواب رسیدم
اگر باز هم مشکلی هست به من گوش زد کنید


public function sub($parent = null)
{
if (empty($parent))
$Categories = $this->findAll(array('condition'=>'parent_id IS NULL','order'=>'title'));
else
$Categories = $this->findAll(array('condition'=>'parent_id=:parentId', 'params'=>array(':parentId'=>$parent)));
foreach($Categories as $category)
{
$this->list[$category->id] = str_repeat(' - ', $category->level) . $category->title ;
if($subCategories = $this->findAll(array('condition'=>'parent_id=:parentId', 'params'=>array(':parentId'=>$category->id),'order'=>'title')));
$this->sub($category->id);
}
return $this->list;
}

MMSHFE
یک شنبه 20 مهر 1393, 09:53 صبح
الان باز بهتر شد (بازگشتی دارین کار میکنید برای زیرمجموعه های نامحدود) ولی فکر میکنم چون همه جا به ترتیب title میخواین مرتب باشه خروجیها، میتونید با کمک defaultScope از شر 'order'=>'title' هم راحت بشین.

Emir New
یک شنبه 20 مهر 1393, 11:23 صبح
یه سوال دیگه
همین ساختار رو چطوری می تونم برای قسمت ادمین پیاده سازی کنم ؟
و نمایش بدم

MMSHFE
یک شنبه 20 مهر 1393, 11:34 صبح
متوجه منظورتون نشدم.

Emir New
یک شنبه 20 مهر 1393, 12:08 عصر
من می خوام در قسمت categories/admin هم فرزند ها زیر پدر خودشون نشون داده بشن
این کد بالا رو من برای نمایش در فرم create نوشتم
یا خیلی بهتر منظورم رو بگم
قسمت مدیریت مجموعه در جوملا

MMSHFE
یک شنبه 20 مهر 1393, 13:10 عصر
خوب همین کدها رو همونجا هم استفاده کنید. مدل که مشترکه اینطور نیست؟

Emir New
یک شنبه 20 مهر 1393, 18:14 عصر
من یه سرچ زدم و کد زیر رو برای قسمت ادمین نوشتم ولی باز هم به خطا بر می خورم
این کد :


public function getGridViewDataProvider($parent = null)
{
if (empty($parent))
$Categories = $this->findAll(array('condition'=>'parent_id IS NULL','order'=>'title'));
else
$Categories = $this->findAll(array('condition'=>'parent_id=:parentId', 'params'=>array(':parentId'=>$parent)));
foreach($Categories as $category)
{

$this->rawData[] =
array(
'id'=>$category->id,
'title'=>$category->title,
'published'=>$category->published,
'created_user_id'=>$category->created_user_id,
'created_time'=>$category->created_time,
'access'=>$category->access,
'modified_time'=>$category->modified_time,
'hits'=>$category->hits,
'level'=>$category->level,

);
if($subCategories = $this->findAll(array('condition'=>'parent_id=:parentId', 'params'=>array(':parentId'=>$category->id),'order'=>'title')));
$this->getGridViewDataProvider($category->id);

}
return $this->rawData;
}


این هم کد برای نمایش


$rawData= $model->getGridViewDataProvider();

$arrayDataProvider =new CArrayDataProvider($rawData);
//exit;
$dataprovider =array(
'arrayDataProvider'=>$arrayDataProvider,
);
$this->widget('zii.widgets.grid.CGridView', array(
'id'=>'Grid_View',
'summaryText' => '',
'cssFile' => $this->AssetsBase.'/css/gridview.css',
'enableSorting' => false,
'summaryText' => '',
//new CArrayDataProvider($data)
'dataProvider'=> $dataprovider,
'pager'=>array(
'header' => '',
'firstPageLabel' => '<<',
/* 'prevPageLabel' => '<img src="'.$this->getAssetsBase().'/img/Back.png">',
'nextPageLabel' => '<img src="'.$this->getAssetsBase().'/img/Next.png">', */
'lastPageLabel' => '&gt;&gt;',
'cssFile'=>false,
),
//'filter'=>$model,
'columns'=>array(
array(
'name'=>'title',
'value'=>function ($data) {
return str_repeat(' - ', $data['level']) . CHtml::encode($data['title']);
},
'htmlOptions' => array('style' => 'width: 150px;'),
),
array(
'name'=>'published',
//'value'=>'access',
'htmlOptions' => array('style' => 'text-align:center;width: 20px;'),
),
array(
'name'=>'created_user_id',
//'value'=>'access',
'htmlOptions' => array('style' => 'text-align:center;'),
),
array(
'name'=>'created_time',
//'value'=>'access',
'htmlOptions' => array('style' => 'width: 100px;'),
),
array(
'name'=>'access',
//'value'=>'access',
'htmlOptions' => array('style' => 'text-align:center;width: 20px;'),
),
array(
'name'=>'modified_time',
//'value'=>'access',
'htmlOptions' => array('style' => 'width: 100px;'),
),
array(
'name'=>'hits',
//'value'=>'access',
'htmlOptions' => array('style' => 'text-align:center;'),
),
array(
'name'=>'id',
//'value'=>'access',
'htmlOptions' => array('style' => 'text-align:center;width: 30px;'),
),
array(
'class'=>'CButtonColumn',
'template'=>'{update} {delete} ',
'htmlOptions' => array('style' => 'text-align:center;'),
),
),
));

این هم پیغام خطا


Fatal error: Call to a member function getData() on a non-object in D:\yii\framework\zii\widgets\CBaseListView.php on line 111