Afficher les menus et sous menus depuis ma BDD

Mammouth du PHP | 725 Messages

26 juin 2011, 13:12

bonjour,

J'ai effectue une requete MySQLi afin d'afficher les menus de ma table hmenu et les sous menu de ma table bmenu, afin d'avoir le resultat suivant:

+Menu1
++ Sous menu1
++ Sous menu1
++ Sous menu1
++ Sous menu1
+Menu2
++ Sous menu2
++ Sous menu2
++ Sous menu2
+Menu3
++ Sous menu3

ainsi de suite
<?php
        	while($row = $r->result->fetch_object())
        	{
        	
			// on affiche les menus principales
        	echo '<div class="headMenu">'.$row->hmenu_ar.'</div>';
        	
        	// on affiche les sous menus du menu principale
        	$r->toDo('SELECT', '*', 'bmenu', 'id_hm1=\''.$row->id_hm.'\' AND onoff=\'1\'');
			$r->num_rows('Number of rows returned: ');
			
			echo '<ul class="ulMenus">';
        	while($row = $r->result->fetch_object())
        	{
        		echo '<li class="liMenus">'.$row->bmenu_ar.'</li>';
        	}
        	
        	echo '</ul>';
        	}
?>

l'affichage se fait comme ca:

+Menu1
++ Sous menu1
++ Sous menu1
++ Sous menu1
++ Sous menu1

mais le reste des menus n'apparaissait pas, merci pour votre aide

Modérateur PHPfrance
Modérateur PHPfrance | 2575 Messages

27 juin 2011, 10:05

Bonjour,

L'erreur est claire : Tu utiliser 2 requêtes imbriquées l'une (celle des sous-menus) dans l'autre (celle des menus principaux) mais malheureusement tu utilises le même nom $r pour les 2 différentes requêtes du coups la seconde requête imbriquée écrase donc la première et la boucle primaire s'arrête net juste après son premier tours c'est à dire après avoir traité le premier menu principal. Il suffit de donner deux noms différents $r1 et $r2 pour séparer les requêtes et par la même il est recommandé aussi de différencier les $row en $row1 et $row2.

Ce sont des règles d'or de programmation : une variable a un nom propre et une durée de vie par rapport une étendue de visibilité.

Début d'une procédure ou fonction ou programme principal:
----- variables locale niveau 1
----- Bloc : IF, WHILE, FOR, ... => variables locales niveau 2 (visibilité variable locales niveau 1)
--------------Sous-Bloc : IF, WHILE, FOR, ... => variables locales niveau 3 (visibilité variable locales niveau 1 et 2)
---------------
... visibilité totale : variables locales niveau 1, 2 et 3
Fin.
... Aucune visibilité des variables locales quelque soit le niveau
--------//////----//---//----//////
-------//---//----//---//----//---//
------//////----//////-----//////
-----||--------||--||---||
Prendre le recul n'est pas une perte de temps.


ps: Affrontez moi dans l'arène

Mammouth du PHP | 725 Messages

28 juin 2011, 03:55

voila la class que j'utilisais pour la connexion:
<?php

######################## Class de connexion Start #################################
class Connexion {
	
	public $db_host, $db_user, $db_passwd, $db_name, $result, $mysqli;
	
	
	// connect to the server
	public function __construct($db_host='', $db_user='', $db_passwd='')
		{
			$this->db_host = $db_host;
			$this->db_user = $db_user;
			$this->db_passwd = $db_passwd;
			
			$this->connexion = new mysqli($db_host, $db_user, $db_passwd); //HOST, USER, PASSWORD
			
				if ($this->connexion->connect_error) 
					{
 						die('Connect Error (' . $this->connexion->connect_errno . ') '. $this_connexion->connect_error);
					}
			
			// set charset to utf-8
			$char = $this->connexion->set_charset("utf8");
		     
		} // end __construct
		
	
	// select databse
	public final function db_name($db_name)
		{
			$this->db_name = $db_name;
			
			$s_db = $this->connexion->select_db($this->db_name);
			
			if(!$s_db)
			{
				echo 'The '.$db_name.' DOES NOT exists<br>';
			}
			
		} // end db_name
		
	
	// method: select, create, insert, delete, update, read (CRUD)
	public final function toDo($method='', $fields=array(), $table_name='', $conditions='') 
		{
			$this->method = $method;
			$this->fields = $fields;
			$this->table_name = $table_name;	
			$this->conditions = $conditions;
			
			switch($this->method)
				{
					case 'SELECT':
						if($conditions)
							{
								$this->select = "$this->method $fields FROM $this->table_name WHERE $conditions";	
							}
							else
							{
								$this->select = "$this->method $fields FROM $this->table_name";
							}
						echo $this->select.'<br>';
					
					
					/*
					ici je veux mettre prepare et execute, est ce que c'est bien comme ca???
					//$this->presult = $this->connexion->prepare($this->select);
					//$this->exresult = $this->result->execute();	
					*/
					$this->result = $this->connexion->query($this->select);
					
					if(!$this->result)
					{
						echo 'An error has occured<br>';
					}
					break;					
				
				
				} // EnD switch
			
		} // EnD toDo
	
	
	
			
	
	public final function num_rows($sentence='')
		{			
				$row_cnt = $this->result->num_rows;
				echo $sentence.$row_cnt.'<br>';			
		} // end num_rows


} // EnD class
######################## Class de connexion Start #################################
?>
au niveau procedureal on fait comme ca:
$con = SELECT ...
$sql = mysql_query...
pour chaque requete on doit avoir une variable differencte ($con), je ne sais pas si c'est le meme cas dessus:

et le reste du code est:
<?php
$r = new Connexion($db_host, $db_user, $db_passwd);
$r->db_name($db_general);
$r->toDo('SELECT', '*', 'hmenu', 'location="r" AND onoff=\'1\'');
$r->num_rows('Number of rows returned: ');

                while($row = $r->result->fetch_object())
                {
               
                        // on affiche les menus principales
                echo '<div class="headMenu">'.$row->hmenu_ar.'</div>';
               
                // on affiche les sous menus du menu principale
                $r->toDo('SELECT', '*', 'bmenu', 'id_hm1=\''.$row->id_hm.'\' AND onoff=\'1\'');
                        $r->num_rows('Number of rows returned: ');
                       
                        echo '<ul class="ulMenus">';
                while($row = $r->result->fetch_object())
                {
                        echo '<li class="liMenus">'.$row->bmenu_ar.'</li>';
                }
               
                echo '</ul>';
                }
?>
je vais changer $r par $r1, $r2, ainsi de suite, et de meme pour $row, mais a chaque fois je dois etablir une nouvelle connexion??

merci sadeq

devlop78
Invité n'ayant pas de compte PHPfrance

28 juin 2011, 04:05

Euh ... Sinon, tu fais tout dans une seule requête ce sera encore plus simple, et moins lourd

Mammouth du PHP | 725 Messages

28 juin 2011, 04:08

Euh ... Sinon, tu fais tout dans une seule requête ce sera encore plus simple, et moins lourd
oui, ce n'est qu'un bruillon pour tester la class, parce que je suis heureuse a la creer et la tester, je suis contente de verifier ma machine :D

Eléphant du PHP | 209 Messages

28 juin 2011, 06:50

public final function toDo($method='', $fields=array(), $table_name='', $conditions='')
C'est une des pire choses que j'ai vue ... Tu ne devrais pas allez dans cette direction...
--
Eric

Mammouth du PHP | 725 Messages

28 juin 2011, 07:05

public final function toDo($method='', $fields=array(), $table_name='', $conditions='')
C'est une des pire choses que j'ai vue ... Tu ne devrais pas allez dans cette direction...
guidez moi svp, je suis debutante :D

Eléphant du PHP | 209 Messages

28 juin 2011, 07:08

Une fonction qui te permet juste d'executer des requetes SQL comme te le conseil develop78 est plus que suffisante.
--
Eric

Mammouth du PHP | 725 Messages

28 juin 2011, 07:19

Une fonction qui te permet juste d'executer des requetes SQL comme te le conseil develop78 est plus que suffisante.
qu'est ce que dois je faire?? pour les combiner, j'ai repondu a develop78 que ce n'est qu'un bruillon de les separer et connaitre les problemes de la class

Modérateur PHPfrance
Modérateur PHPfrance | 2575 Messages

28 juin 2011, 11:11

Bonjour,

L'objectif de ta classe est de prendre en charge toutes les opérations d'interaction avec la base de données pour les rendre transparentes pour le programmeur. Selon ce principe l'utilisateur de la classe doit pouvoir ouvrir une connexion à une base de données dans le but de l'interroger, donc une seule connexion suffira par objet de ta classe et avec cette connexion on pourra en principe exécuter tout type de requêtes.
Si tu souhaites faire abstraction des requêtes SQL et proposer des méthodes qui simplifient leur usage ça sera une pure perte de temps car SQL est tellement bien conceptualisé que ses différentes combinaisons qui techniquement répondent aux requêtes utilisateurs sont inimitables sinon que du pure plagia. Le plus judicieux est créer des méthodes qui prennent en charge le traitement de l'exécution et la récupération des résultats d'exécution des requêtes SQL connues (SELECT, INSERT, UPDATE et DELETE) que l'utilisateur de la classe fournira texto.
Dans le cas du SELECT, l’intérêt d'une méthode d'exécution réside dans le fait que seule la classe ait accès à une connexion déjà ouverte, et que la méthode puisse gérer les erreurs inhérentes aux relations avec cette connexion. De plus, la méthode peut extraire les résultats d'exécution et les renvoyer à l'utilisateur de la classe dans un format séparé de la connexion comme par exemple : retourner les résultats dans un tableau. Ce qui reste exploitable facilement par l'utilisateur.

De ces spécifications ressort le modèle objet suivant qui redonne à ta classe une nouvelle organisation:
Programme de la classe et son test:
<?php
######################## Class de connexion #################################
class Connexion {
	// propriétés       
	public $connexion, $db, $db_host, $db_user, $db_passwd, $db_name, $result, $mysqli;

	// connect to the server & open default database
	public function __construct($db_host='', $db_user='', $db_passwd='', $db_name='')
	{
		$this->db_host = $db_host;
		$this->db_user = $db_user;
		$this->db_passwd = $db_passwd;
		$this->connexion = new mysqli($db_host, $db_user, $db_passwd); //HOST, USER, PASSWORD
		if ($this->connexion->connect_error)
	   	{
	   		die('Error (' . $this->connexion->connect_errno . ') : '. $this->connexion->connect_error);
		}
       
		// set charset to utf-8
		$this->connexion->set_charset("utf8");
		
		// open default database if givven
		if (trim($this->db_name)!='' && !$this->openDb($db_name))
	   	{
	   		die ('The '.$db_name.' does not exists');
		}
     
	} // end __construct
       
       
	// select a databse
	public function openDb($db_name)
	{
		//si pas de connexion, alors rien
		if (!$this->connexion) return false;
		
		//sinon ouvrir la base
		$this->db_name = $db_name;
       	$this->db = $this->connexion->select_db($this->db_name);
       	if(!$this->db)
		{
			return false;
		}
		return true; // db opened
       
	} // end db_name
       
       
	// method: select, create, insert, delete, update, read (CRUD)
	public function execSQL($sql)
	{
		//si pas de connexion, alors rien
		if (!$this->connexion) return false;
		
		// exécution SQL : 3 cas (1. erreur d'exécution, 2. résultat requêtes non SELECT, 3. résultat SELECT)
		$result = $this->connexion->query($sql);
		if ($result === FALSE) // cas d'erreur d'exécution
		{
			echo ('Error (' . $this->connexion->connect_errno . ') : '. $this->connexion->connect_error);
			return false;
		}
		else if ($result === TRUE)// cas de toute requête non SELECT
		{
			return true;
		}
		else {
			// cas du select
			$tabl_result = array();
			while ($result && $row = $this->connexion->fetch_object())
			{
				$tabl_result[] = $row;
			}
			return $tabl_result;
		}
	} // EnD execSQL
	
	// fermer la connexion
	public function close()
	{      
		if ($this->connexion && $this->db) $this->connexion->close();
	} // end close
	
	// destructeur
	public function __destruct() {
       $this->close();
   }


} // EnD class
######################## Class de connexion #################################



//////////// TEST de la classe ////////////////


// ouvrir la base de données TEST
$db_test = new Connexion('localhost', 'root', '', 'dbtest');

// exécuter des requêtes SELECT
$tabl_hMenu = $db_test->execSQL("SELECT * FROM hmenu WHERE location='r' AND onoff='1'");
if ($tabl_hMenu && is_array($tabl_hMenu))
{
	echo 'Number of rows returned: ' . count($tabl_hMenu);
	foreach($tabl_hMenu as $row_hMenu)
	{
		// on affiche les menus principales
		echo '<div class="headMenu">'.$row_hMenu->hmenu_ar.'</div>';
	
		// on affiche les sous menus du menu principale
		$tabl_bMenu = $db_test->execSQL("SELECT * FROM bmenu WHERE id_hm1='".$row_hMenu->id_hm."' AND onoff='1'");
		if ($tabl_bMenu && is_array($tabl_bMenu))
		{
			echo 'Number of rows returned: ' . count($tabl_bMenu);
			echo '<ul class="ulMenus">';
			foreach($tabl_bMenu as $row_bMenu)
			{                        
				echo '<li class="liMenus">'.$row_bMenu->bmenu_ar.'</li>';
            } // fin boucle $tabl_bMenu
			echo '</ul>';
		}
	} // fin boucle $tabl_hMenu
}

// fermer la base de données
$db_test->close();
?>
--------//////----//---//----//////
-------//---//----//---//----//---//
------//////----//////-----//////
-----||--------||--||---||
Prendre le recul n'est pas une perte de temps.


ps: Affrontez moi dans l'arène

Eléphant du PHP | 209 Messages

28 juin 2011, 12:45

car SQL est tellement bien conceptualisé que ses différentes combinaisons qui techniquement répondent aux requêtes utilisateurs sont inimitables sinon que du pure plagia.
Alors celle-ci, je vais l'encadrer et l'afficher chez les gens qui me gonflent avec leur ORM :-)
--
Eric

Modérateur PHPfrance
Modérateur PHPfrance | 2575 Messages

28 juin 2011, 14:47

car SQL est tellement bien conceptualisé que ses différentes combinaisons qui techniquement répondent aux requêtes utilisateurs sont inimitables sinon que du pure plagia.
Alors celle-ci, je vais l'encadrer et l'afficher chez les gens qui me gonflent avec leur ORM :-)
Voila c'est fait :mrgreen:
Image
--------//////----//---//----//////
-------//---//----//---//----//---//
------//////----//////-----//////
-----||--------||--||---||
Prendre le recul n'est pas une perte de temps.


ps: Affrontez moi dans l'arène

devlop78
Invité n'ayant pas de compte PHPfrance

29 juin 2011, 02:32

LOL

Mammouth du PHP | 725 Messages

29 juin 2011, 04:59

sadeq: j'ai voulu tester le code avant de le bien comprendre ca donne rien, aucun affichage, avec un echo sur $result:
echo $result;
ca donne rien

Eléphant du PHP | 209 Messages

29 juin 2011, 06:21

Voila c'est fait :mrgreen:
lol, merci !
--
Eric