Lenteurs script boucles foreach

Petit nouveau ! | 6 Messages

13 sept. 2012, 10:11

Bonjour à tous !
Je débute en POO, j'ai un problème de script plutot simple qui s'execute très lentement (alors que si je le code en procedural, l'execution est instantanée).
Voici un extrait de mon code :

Class Collectif :
class Collectif
	{
	public $_c_id;
	public $_c_aid;
	public $_c_nom;
	public $_c_adr;
	public $_c_tel;
	public $_c_fax;
	public $_c_mail;
	public $_c_cpt_compt;
	public $_c_cotis;
	public $_c_frais_dos;
	public $_c_frais_medic;
	public $_c_test_ski;
	public $_c_convoc;
	
	public function __construct (array $data)
		{
		foreach ($data as $key => $value)
			{
			$method = "set" . ucfirst($key);
			
			if (method_exists($this, $method))
				{$value = $this -> $method($value);}
			
			$my_priv_var = "_" . $key;
			$this -> $my_priv_var = $value;
			}
			
		$c_adresse = new Adresse($data);
		
		$this->_c_nom = trim($this->_cot_nom." ".ucfirst($this->_a_orga));
		$this->_c_adr = $c_adresse->getA_libel("<br />");
		$this->_c_tel = $this->setC_affect($c_adresse->_a_tel1);
		$this->_c_fax = $this->setC_affect($c_adresse->_a_tel2);
		$this->_c_mail = $this->setC_affect($c_adresse->_a_mail);
		$this->_c_cpt_compt = $this->setC_affect($this -> _c_cpt_compt);
		$this->_c_cotis = $this->setC_affect2($this -> _c_cotis);
		$this->_c_frais_doss = $this->setC_affect2($this -> _c_frais_doss);
		$this->_c_frais_medic = $this->setC_affect2($this -> _c_frais_medic);
		$this->_c_test_ski = $this->setC_affect2($this -> _c_test_ski);
		}
		
	public function __destruct()
		{
		foreach ($this as $key => $value) 
			{unset($this->$key);}
		} 
		
	// SETTERS
	public function setC_affect($valeur)
		{
		if (empty($valeur)) {$valeur = "-";}
		return $valeur;
		}
		
	public function setC_affect2($valeur)
		{
		if (empty($valeur)){$valeur = "<font class=\"txter\">non</font>";}
		else {$valeur = "<font class=\"txtev\">oui</font>";}
		return $valeur;
		}
		
	public function setC_convoc($valeur)
		{
		switch ($valeur)
			{
			case "p" : $valeur = "pas de convocation"; break;
			case "c" : $valeur = "au tiers collectif"; break;
			case "u" : $valeur = "à l'usager"; break;
			default : $valeur = "-";
			}
		return $valeur; 
		}			
	
	// GETTERS
				
	}

Class Collectif_manager :
class Collectif_manager
	{
	private $_db;
	
	public function __construct ($db)
		{$this -> setDb ($db);}
	
	// SETTERS	
	public function setDb (PDO $db)
		{$this -> _db = $db;}
	
	// GETTERS	
	public function getCollectif ($id)
		{
		$q = $this -> _db -> query("SELECT * FROM sa_collectif
		LEFT JOIN sa_collectif_types ON sa_collectif.c_cotid=sa_collectif_types.cot_id
		LEFT JOIN cmn_adresses ON sa_collectif.c_aid=cmn_adresses.a_id
		LEFT JOIN cmn_lieux_cp_ville ON cmn_adresses.a_lcpvid=cmn_lieux_cp_ville.lcpv_id
		WHERE c_id='".$id."'");
		$donnees = $q->fetch(PDO::FETCH_ASSOC);
		return new Collectif($donnees);
		}
		
	public function getCollectifList ()
		{
		$collectifs = array ();
		$q = $this-> _db -> query("SELECT * FROM sa_collectif
		LEFT JOIN sa_collectif_types ON sa_collectif.c_cotid=sa_collectif_types.cot_id
		LEFT JOIN cmn_adresses ON sa_collectif.c_aid=cmn_adresses.a_id
		LEFT JOIN cmn_lieux_cp_ville ON cmn_adresses.a_lcpvid=cmn_lieux_cp_ville.lcpv_id
		ORDER BY a_orga");
		while ($donnees = $q->fetch(PDO::FETCH_ASSOC))
			{$collectifs[] = new Collectif($donnees);}
		return $collectifs;	
		}
		
	public function getCollectifCts (Collectif $le_col)
		{
		$contacts = array ();
		$q = $this -> _db -> query("SELECT * FROM sa_co_ct 
		LEFT JOIN cmn_contact ON sa_co_ct.cc_ctid=cmn_contact.ct_id
		WHERE cc_cid='" . $le_col -> _c_id . "' ORDER BY cc_id");
		while ($donnees = $q->fetch(PDO::FETCH_ASSOC))
			{$contacts[] = new Contact($donnees);}
		return $contacts;	
		}
		
	public function getCollectifAdr (Collectif $le_col)
		{
		$q = $this -> _db -> query("SELECT * FROM cmn_adresses
		LEFT JOIN cmn_lieux_cp_ville ON cmn_adresses.a_lcpvid=cmn_lieux_cp_ville.lcpv_id
		WHERE a_id='" . $le_col -> _c_aid . "'");
		$donnees = $q->fetch(PDO::FETCH_ASSOC);
		return new Adresse($donnees);
		}
	}

Script faisant appel à mes classes avec la même construction que Collectif et Collectif_manager :
Le principe étant d'afficher toutes les inscriptions à un séjour pour un collectif sur une periode donnée :
Collectif 1 :
5 inscriptions sur le séjour 1 à la session 1
3 inscriptions sur le séjour 1 à la session 2
7 inscriptions sur le séjour 2 à la session 1
...

Collectif 2 :
2 inscriptions sur le séjour 1 à la session 1
45 inscriptions sur le séjour 1 à la session 2
...
<?
$db1 = new PDO("mysql:host=".$serveur.";dbname=".$db,$utilisateur,$mdp);
	
function chargerClasse ($classe)
{require "../_class/".$classe.".class.php";}
	
spl_autoload_register("chargerClasse");


$c_manager = new Collectif_manager($db1);
$sj_manager = new Sejour_manager($db1);
$ss_manager = new Session_manager($db1);

$p_manager = new Periode_manager($db1);
$la_period = $p_manager->getPeriode(1);


foreach ($c_manager->getCollectifList() as $le_coll)
	{
	$chaine = "";
	
	// TRAITEMENT	
	foreach ($p_manager->getSejours($la_period) as $le_sejour)
		{
		foreach ($sj_manager->getSessions($le_sejour) as $la_session)
			{
			$compt = 0;
			foreach ($ss_manager->getInscr($la_session) as $inscr)
				{
				if ($inscr->_i_cid == $le_coll->_c_id)
					{$compt++;}
				}
			
			if (!empty($compt))
				{$chaine .= $le_sejour->_sj_nom." ".$la_session->getSs_d1fr()." - ".$la_session->getSs_d2fr()." NB=".$compt."<br />";}
			}
		}
		
	// AFFICHAGE
	if (!empty($chaine))
		{
		?>
		<div class="fd_blue2">
			<div class="titreb"><? echo $le_coll->_c_nom; ?></div>
			<div class="ligne_rouge"></div>
			<div>
				<div style="float:left; width:50%;">
					<table cellpadding="3" cellspacing="0" border="0" class="txten">
						<tr><td class="txteb" valign="top">Adresse :</td><td><? echo $le_coll->_c_adr; ?></td></tr>
						<tr><td class="txteb">Téléphone :</td><td><? echo $le_coll->_c_tel; ?></td></tr>
						<tr><td class="txteb">Télécopie :</td><td><? echo $le_coll->_c_fax; ?></td></tr>
						<tr><td class="txteb">Mail :</td><td><? echo $le_coll->_c_mail; ?></td></tr>
					</table>
				</div>
				<div style="float:left; width:50%;">
					<table cellpadding="3" cellspacing="0" border="0" class="txten">
						<?
						foreach ($c_manager->getCollectifCts($le_coll) as $contact)
							{echo "<tr><td class=\"txteb\" valign=\"top\">Contact :</td><td>".$contact->getFullCt("<br />")."</td></tr>";}
						?>
					</table>
				</div>
				<div class="clear"></div>
			</div>
		</div>
		<div class="space10"></div>
		<div>
			<? echo $chaine; ?>
		</div>
		<div class="space20"></div>
		<?
		}
	}
?>
Merci pour vos orientations...

ViPHP
xTG
ViPHP | 7331 Messages

13 sept. 2012, 11:33

Il nous faudrait voir ton code procédural pour pouvoir comparer quoi que ce soit. ;)

Petit nouveau ! | 6 Messages

13 sept. 2012, 12:43

Mes requêtes ne sont pas du tout optimisées !
Je ne mets que des SELECT *, alors que je pourrais ne choisir qu'un champ !
Je gagne déjà énormément de temps sur l'exécution :P
(Si vous avez des idées pour encore mieux optimiser mes requetes... Mais je sais que l'execution dépend aussi du nombre d'enregistrements dans mes tables)

Ca donnerait ça en procédural (optimisé) :
<?
$la_period = 1;

$sql1 = "SELECT c_id FROM sa_inscription
LEFT JOIN sa_collectif ON sa_inscription.i_cid=sa_collectif.c_id
LEFT JOIN cmn_adresses ON sa_collectif.c_aid=cmn_adresses.a_id
GROUP BY a_orga";
$res1 = mysql_query($sql1,$link);
while ($coll = @mysql_fetch_array($res1))
	{
	$chaine = "";
	
	$sql2 = "SELECT sj_id,sj_nom FROM sa_sejour WHERE sj_pid='".$la_period."'";
	$res2 = mysql_query($sql2,$link);
	while ($sejour = @mysql_fetch_array($res2))
		{
		$sql3 = "SELECT ss_date1,ss_date2 FROM sa_session WHERE ss_sjid='".$sejour["sj_id"]."'";
		$res3 = mysql_query($sql3,$link);
		while ($session = @mysql_fetch_array($res3))
			{
			$compt = 0;
			
			$sql4 = "SELECT i_cid FROM sa_inscription 
			WHERE (i_sjid='".$sejour['sj_id']."') AND ((i_date1>='".$session['ss_date1']."' AND i_date1<'".$session['ss_date2']."') || (i_date1<='".$session['ss_date1']."' AND i_date2>='".$session['ss_date2']."') || (i_date2>'".$session['ss_date1']."' AND i_date2<='".$session['ss_date2']."')) ORDER BY i_ordre,i_id";
			$res4 = mysql_query($sql4,$link);
			while ($inscr = @mysql_fetch_array($res4))
				{
				if ($inscr["i_cid"] == $coll["c_id"])
					{$compt++;}
				}
			if (!empty($compt))
				{$chaine .= $sejour["sj_nom"]." ".dfr($session["ss_date1"])." - ".dfr($session["ss_date2"])." NB=".$compt."<br />";}
			}
		}
		
	// AFFICHAGE
	if (!empty($chaine))
		{
               // JE DEVRAIS RECHARGER LE COLLECTIF AVEC UN "SELECT * FROM COLLECTIF" POUR AFFICHER LE RESULTAT CI-DESSOUS :
		?>
		<div class="fd_blue2">
			<div class="titreb"><? echo $coll['a_orga']; ?></div>
			<div class="ligne_rouge"></div>
            <div>
                <div style="float:left; width:50%;">
                    <table cellpadding="3" cellspacing="0" border="0" class="txten">
                        <tr><td class="txteb" valign="top">Adresse :</td><td>
                        <? 
                        echo affich_adresse($link,$coll['a_id'],$coll['a_orga'],$coll['a_ad1'],$coll['a_ad2'],$coll['lcpv_cp'],$coll['lcpv_nom']);
                        
                        if (empty($coll['a_tel1'])){$tel="-";}else{$tel=$coll['a_tel1i'].$coll['a_tel1'];}
                        if (empty($coll['a_tel2'])){$fax="-";}else{$fax=$coll['a_tel2i'].$coll['a_tel2'];}
                        if (empty($coll['a_mail'])){$mail="-";}else{$mail="<a href=\"mailto:".$coll['a_mail']."\" class=\"txten\">".$coll['a_mail']."</a>";}
                        if (empty($coll['c_cpt_compt'])){$cpt_compt="-";}else{$cpt_compt=$coll['c_cpt_compt'];}
                        ?>
                        </td></tr>
                        <tr><td class="txteb">Téléphone :</td><td><? echo $tel; ?></td></tr>
                        <tr><td class="txteb">Télécopie :</td><td><? echo $fax; ?></td></tr>
                        <tr><td class="txteb">Mail :</td><td><? echo $mail; ?></td></tr>
                    </table>
                </div>
                <div style="float:left; width:50%;">
                    <table cellpadding="2" cellspacing="0" border="0" class="txten">
                        <?
                        $sql_ct = "SELECT * FROM sa_co_ct 
						LEFT JOIN cmn_contact ON sa_co_ct.cc_ctid=cmn_contact.ct_id 
						WHERE cc_cid='".$coid."' ORDER BY cc_id";	
                        $res_ct = mysql_query($sql_ct,$link);
                        
                        if (mysql_num_rows($res_ct) !== 0)
                            {
                            $i = 1;
                            while ($ct = @mysql_fetch_array($res_ct))
                                {
                                $ct_id = $ct['ct_id'];
                                $ct_genre = $ct['ct_genre'];
                                $ct_nom = $ct['ct_nom'];
                                $ct_fct = $ct['ct_fct'];
                                $ct_teli = $ct['ct_teli'];
                                $ct_tel = $ct['ct_tel'];
                                $ct_mail = $ct['ct_mail'];
            
                                if ($i !== 1) {echo "<tr height=\"20\"><td></td><td></td></tr>";} 
            
                                echo "<tr><td class=\"txteb\">Contact ".$i." :</td><td>".affich_genre($ct['ct_genre']).$ct['ct_nom'];
                                if (!empty($ct['ct_fct'])) {echo " (".$ct['ct_fct'].")";}
                                echo "</td></tr>";
                                
                                if (!empty($ct['ct_tel'])) {echo "<tr><td></td><td>".$ct['ct_teli'].$ct['ct_tel']."</td></tr>";}
                                
                                if (!empty($ct['ct_mail'])) {echo "<tr><td></td><td><a href=\"mailto:".$ct['ct_mail']."\" class=\"txten\">".$ct['ct_mail']."</a></td></tr>";}
                                
                                if (!empty($ct['ct_brochure']))
                                    {echo "<tr><td></td><td class=\"txtev\">".$ct['ct_brochure']." brochure(s) envoyée(s) à cette personne.</td></tr>";}
                                
                                $i++;
                                }
                            }
                        ?>
                    </table>
                </div>
                <div class="clear"></div>
            </div>
		</div>
		<div class="space10"></div>
		<div>
			<? echo $chaine; ?>
		</div>
		<div class="space20"></div>
		<?
		}
	}
?>
En fait, la 2nde question que je me pose, c'est :
"Comment trouvez-vous l'organisation de mes classes Collectif et Collectif_manager ?
L'organisation de mon code est-elle bonne ?"

Merci

ViPHP
xTG
ViPHP | 7331 Messages

13 sept. 2012, 14:42

Bon donc c'est la même structure après lecture en diagonale.
Par contre foreach travaillant sur des copies la perte de temps vient peut être de là si tes requêtes renvoient énormément de résultats, implémentes un itérateur pour voir, ou bien travailles avec un while. ;)