Запрос Sql, чтобы получить заказанное меню - PullRequest
0 голосов
/ 09 октября 2019

Прямо сейчас я создаю свое меню, выполняя множество запросов и зацикливаясь на symfony. Я хотел бы иметь возможность получить ту же вещь в одном запросе SQL

MenuItem (Id,parent_id,level,weight)

parent_id является ссылкой на другой MenuItem

Если у меня есть эти записи

1, ноль, 1,50

2, ноль, 1,20

3,1,2,100

4,1,2,0

5,2,2,40

6,5,3,900

7,5,3500

Я хочу, чтобы результаты были

2

5

7

6

1

4

3

Атрибут weigtht используется для упорядочения пунктов меню внутри их собственного уровня.

Это означает, что id2 идут перед идентификатором 1, потому что вес 20 <вес 50, но идентификатор 2 все еще стоит перед идентификатором 4, потому что уровень 1 <уровень 2 </p>

Я даже не уверен, что это возможно.

РЕДАКТИРОВАТЬ: Правотеперь я должен сделать что-то очень уродливое

$menu = $this->factory->createItem('root');
$menu->setLabel("Menu");

$item_repository = $this->getDoctrine()->getRepository(MenuItem::class);
//profondeur max defini à 5
//On récupère les items du niveau 1 trié par poids (profondeur)
$items_lv1 = $item_repository->findBy(array('menu' => $id_main_menu,'active' => 1, 'niveau' => 1),array('poids' => 'ASC'));
//On récupère les items du niveau 2 trié par parent et poids (profondeur)
$items_lv2 = $item_repository->findBy(array('menu' => $id_main_menu,'active' => 1,'niveau' => 2),array('parent' => 'ASC','poids' => 'ASC'));
$items_lv3 = $item_repository->findBy(array('menu' => $id_main_menu,'active' => 1,'niveau' => 3),array('parent' => 'ASC','poids' => 'ASC'));
$items_lv4 = $item_repository->findBy(array('menu' => $id_main_menu,'active' => 1,'niveau' => 4),array('parent' => 'ASC','poids' => 'ASC'));
$items_lv5 = $item_repository->findBy(array('menu' => $id_main_menu,'active' => 1,'niveau' => 5),array('parent' => 'ASC','poids' => 'ASC'));

$cptLv1 = 1;
foreach ($items_lv1 as $item_lv1){
    $lv1 = $menu->addChild($cptLv1,
        ['uri' => $item_lv1->getUrl(),'label' => $item_lv1->getLabel(),
            'attributes' => array('title' => $item_lv1->getTitle(),
            'id_css' => $item_lv1->getIdCss(), 'class_css' => $item_lv1->getClassCss(), 'target' => $item_lv1->getTarget())]);
    $cptLv2 = 1;
    foreach ($items_lv2 as $item_lv2){
        if($item_lv2->getParent()->getUrl() == $item_lv1->getUrl()){
            $lv2 = $lv1->addChild($cptLv1.$cptLv2,
                ['uri' => $item_lv2->getUrl(),'label' => $item_lv2->getLabel(),
                    'attributes' => array('title' => $item_lv2->getTitle(),
                    'id_css' => $item_lv2->getIdCss(), 'class_css' => $item_lv2->getClassCss(), 'target' => $item_lv2->getTarget())]);
            $cptLv3 = 1;
            foreach ($items_lv3 as $item_lv3){
                if($item_lv3->getParent()->getUrl() == $item_lv2->getUrl()) {
                    $lv3 = $lv2->addChild($cptLv1.$cptLv2.$cptLv3,
                        ['uri' => $item_lv3->getUrl(), 'label' => $item_lv3->getLabel(),
                            'attributes' => array('title' => $item_lv3->getTitle(),
                            'id_css' => $item_lv3->getIdCss(), 'class_css' => $item_lv3->getClassCss(), 'target' => $item_lv3->getTarget())]);
                    $cptLv4 = 1;
                    foreach ($items_lv4 as $item_lv4){
                        if($item_lv4->getParent()->getUrl() == $item_lv3->getUrl()) {
                            $lv4 = $lv3->addChild($cptLv1.$cptLv2.$cptLv3.$cptLv4,
                                ['uri' => $item_lv4->getUrl(), 'label' => $item_lv4->getLabel(),
                                    'attributes' => array('title' => $item_lv4->getTitle(),
                                    'id_css' => $item_lv4->getIdCss(), 'class_css' => $item_lv4->getClassCss(), 'target' => $item_lv4->getTarget())]);
                            $cptLv5 = 1;
                            foreach ($items_lv5 as $item_lv5){
                                if($item_lv5->getParent()->getUrl() == $item_lv4->getUrl()) {
                                    $lv4->addChild($cptLv1.$cptLv2.$cptLv3.$cptLv4.$cptLv5,
                                        ['uri' => $item_lv5->getUrl(), 'label' => $item_lv5->getLabel(),
                                            'attributes' => array('title' => $item_lv5->getTitle(),
                                            'id_css' => $item_lv5->getIdCss(), 'class_css' => $item_lv5->getClassCss(), 'target' => $item_lv5->getTarget())]);
                                }
                                $cptLv4 += 1;
                            }
                        }
                        $cptLv4 += 1;
                    }
                }
                $cptLv3 += 1;
            }
        }
        $cptLv2 +=1;
    }
    $cptLv1+=1;
}

Ответы [ 2 ]

1 голос
/ 09 октября 2019

вам не нужно использовать уровень и вес ... просто используйте вес (лучше было бы "заказать").
не беспокойтесь, если id 2 до или после id 4, потому что id4 находится в id2 (родительский уровень).

элемент с parent_id = null является идентификатором с уровнем 0.

думайте так:

 select Id,parent_id,level  ,weight from mytable order by level,weight

Вот фрагмент кода, который позволяет вам после вашеговыберите, чтобы иметь рекурсивную таблицу, которую вы можете просматривать для отображения меню. Он принимает во внимание, что элемент может быть связан с «нулем» (корень), и что могут быть непоследовательные «веса» ...

результат $Переменная строится так, как если бы вы сделали выбор с сортировкой по уровню + вес

<style>

 ul {
   list-style-type: none;
   margin: 0;
   padding: 0;
  background-color: #D0D0D0;
 }


 li {
  margin-left:2em;
  border-left:solid 2px green;
  text-align:left;
  padding-left:1em;
 }


</style>

<?php 

 /* 
  * warn ! this array looks like a result after a select, ordered by level+weight 
  */
 $result=array(
   array(   'id'=>2,   'parent_id'=>null,   'level'=>1,   'weight'=>20  ),
   array(   'id'=>1,   'parent_id'=>null,   'level'=>1,   'weight'=>50  ),

   array(   'id'=>4,   'parent_id'=>1,    'level'=>2,   'weight'=>0   ),
   array(   'id'=>3,   'parent_id'=>1,     'level'=>2,   'weight'=>100  ),

   array(   'id'=>5,   'parent_id'=>2,    'level'=>2,   'weight'=>40   ),

   array(   'id'=>7,   'parent_id'=>5,    'level'=>3,   'weight'=>500   ),
   array(   'id'=>6,   'parent_id'=>5,    'level'=>3,   'weight'=>900   )
);


 // store recursive array of menus
 $menus=array();

 // store link of an id in the recursive array of menus 
 $keysIds=array();

 // start with a empty menu
 $menus[0]=array('element'=>'ROOT','subMenus'=>array());
 $keysIds[0]=&$menus[0];

 // build a menus array  
 foreach ($result as $element) {

    $idParent=$element['parent_id'];
    $id=$element['id'];

    // check for idParent=0 !!     
    if ($idParent==null) {
        $idParent=0;
    }

    // check if parent exists
    // don't forget, result is sorted by level+weight,
    // so the idParent is always in array
    if (!isset($keysIds[$idParent])) {
        echo "<H2>PARENT = $idParent , not exists while INSERTING Id {$id} </H2>";
        continue;
    }

    // JSON index sorting prevention    
    $max=sizeof($keysIds[$idParent]['subMenus']);
    // create a entry
    $keysIds[$idParent]['subMenus'][$max]=array('element'=>$element,'subMenus'=>array());
    // for next entries, keep this id accessible quickly..it can be a parent.
    $keysIds[$id]=&$keysIds[$idParent]['subMenus'][$max]; 

 }


 // show the HTML LISTE   
 htmlMenus($menus,0);


 // Recursive iteration on $menus   
 function htmlMenus($root,$listeLevel) {
     echo str_repeat(" ", $listeLevel*2); // beautifull source...
     echo "<ul>\n";    
     foreach ($root as $datas) {
         echo str_repeat(" ", $listeLevel*2+2);
         echo "<li>\n ";
         if ($datas['element']!='ROOT') {
             echo str_repeat(" ", $listeLevel*2+2);
             echo "ID : {$datas['element']['id']} weight:{$datas['element']['weight']}\n";
         }
         htmlMenus($datas['subMenus'],$listeLevel+1);
         echo str_repeat(" ", $listeLevel*2+2);
         echo '</li>';             
     }
     echo str_repeat(" ", $listeLevel*2);
     echo "</ul>\n"; 
 }
1 голос
/ 09 октября 2019

Примите во внимание следующее:

DROP TABLE IF EXISTS my_table;

CREATE TABLE my_table
(id SERIAL PRIMARY KEY
,parent_id INT NULL
,level INT NOT NULL
,weight INT NOT NULL
);

INSERT INTO my_table VALUES
(1,null,1,50),
(2,null,1,20),
(3,1,2,100),
(4,1,2,0);

SELECT *,COALESCE(y.level,x.level) my_level,COALESCE(y.weight,x.weight) my_weight FROM my_table x LEFT JOIN my_table y ON y.id = x.parent_id;
+----+-----------+-------+--------+------+-----------+-------+--------+----------+-----------+
| id | parent_id | level | weight | id   | parent_id | level | weight | my_level | my_weight |
+----+-----------+-------+--------+------+-----------+-------+--------+----------+-----------+
|  1 |      NULL |     1 |     50 | NULL |      NULL |  NULL |   NULL |        1 |        50 |
|  2 |      NULL |     1 |     20 | NULL |      NULL |  NULL |   NULL |        1 |        20 |
|  3 |         1 |     2 |    100 |    1 |      NULL |     1 |     50 |        1 |        50 |
|  4 |         1 |     2 |      0 |    1 |      NULL |     1 |     50 |        1 |        50 |
+----+-----------+-------+--------+------+-----------+-------+--------+----------+-----------+

Извлекайте из этого все, что захотите.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...