Diaporama généré par PHP sans MySQL à partir d'un dossier d'images

ViPHP
AB
ViPHP | 5818 Messages

06 sept. 2007, 01:37

Si ce que tu souhaites faire est de lister tous les fichier d'un répertoire commençant par $_GET["lettre"] (en majuscule ou en minuscules) et en enlevant l'extension du fichier, le code précédent adapté à ton pb devrait donc donner:
$lettre = isset($_GET["lettre"])? $_GET["lettre"] : "A";
$rep = "livre-d-or/";

$list = opendir($rep);
  
  $tabfile = array();
  
  //liste tous les fichiers
  while ($fichier = readdir($list)) 
           {//s'ils commencent par $lettre (en majuscules ou en minucules)
           if (strpos(strtolower($fichier), strtolower($lettre)) === 0)
				{ 
				//Insère le nom des fichiers dans le tableau $tabfile après avoir enlevé tout ce qui se trouve après le dernier point.
				$tabfile[] = substr($fichier,0,strrpos($fichier,'.'));
           		}
	   }

  closedir($list);
  
  //tri du tableau par ordre alphabétique naturel
  natcasesort($tabfile);
  
  //lecture du tableau trié
  foreach($tabfile as $file)    
      {
      echo $file.'<br />';
        } 
On peut faire l'économie de deux accolades (mais Zeus va me foudroyer car c'est moins lisible) :)
$lettre = isset($_GET["lettre"])? $_GET["lettre"] : "A";
$rep = "livre-d-or/";

$list = opendir($rep);
  
  $tabfile = array();
  
  //liste tous les fichiers
  while ($fichier = readdir($list)) 
           {//s'ils commencent par $lettre (en majuscules ou en minucules), insère le nom des fichiers dans le tableau $tabfile après avoir enlevé tout ce qui se trouve après le dernier point.
           (strpos(strtolower($fichier), strtolower($lettre)) === 0)? $tabfile[] = substr($fichier,0,strrpos($fichier,'.')) : '';
            }

  closedir($list);
  
  //tri du tableau par ordre alphabétique naturel
  natcasesort($tabfile);
  
  //lecture du tableau trié
  foreach($tabfile as $file)    
      {
      echo $file.'<br />';
        }
J'ai enlevé le preg_match car il n'était pas absolument nécessaire et tu auras bien d'autres occasions d'apprendre son fonctionnement :wink:
Tu vois qu'il n'y avait pas beaucoup de code à adapter 8-)

Eléphant du PHP | 160 Messages

06 sept. 2007, 03:04

oui, oui, mais j'avais essayé d'adapter à ce que j'avais fait,
je vais essayer demain en partant du tien...

Dommage, ça partait bien...

Modérateur PHPfrance
Modérateur PHPfrance | 2575 Messages

06 sept. 2007, 13:27

Je ne suis pas tout à fait d'accord, l'expresion régulière (utilisant preg_match() ou ereg() ou eregi()) ou encore un test sur $f[0] est plus simple car le remplacer par un strpos() ne fait pas l'affaire puisqu'il cherche la lettre n'importe où dans le nom.
L'expression régulière ou $f[0] cherchent seulement les noms qui commencent par la lettre. Ce qui est demandé.
Et même remarque pour le cas de suppression de l'extension du fichier, se baser sur la position d'un point est faux car on peut avoir plusieurs points avant celui de l'extension.

Je ne suis jamais d'accord pour l'usage de strpos() et substr() pour taiter un cas de recherche partielle ou de remplacement d'un critère partiel. Car tout simplement c'est le domaine des expressions régulières. Il faut donc utiliser le mieux qu'on peut les fonctions RegExp.

Par exemple,
//expReg pour les nom commençant par $lettre:
if ( preg_match('#^$lettre.*#', $f) ) {
   ... ici: touvé
}
ou
//nom commençant par $lettre:
$f = trim($f);
if ( $f && strtoupper($f[0]) == strtoupper($lettre) ) {
   ... ici: touvé
}
C'est simple, subtil et pratique.
//Pour écarter l'extension d'un fichier (cibler le dernier point)
$nom_sans_extension = eregi_replace('\.[^.]*$', "", $f);
Voilà, c'est aussi simple. le [^.]*$ s'assure que tous les caractères situés entre un point (\.) et la fin ($) du nom, ne contiennent pas de point. En l'occurence on cible vraimment l'extension.

Autre chose:
l'opérateur ternaire (?) n'est pas approprié car dans notre cas on ne veut pas affecter dans le cas de sinon. Et cet opérateur est souvent utilisé pour simplifier l'affectation conditionnelle dans une variable. Utiliser l'alternative if sans else est donc mieux approprié.

Je dis ça pour avertir notre ami jpsartre qu'en programmation il y a plusieurs façons de faire, mais il faut choisir la meilleure.

Comme ça par exemple: (pour continuer sur notre idée de départ)
<p><a href="?lettre=A">A</a>&nbsp;<a href="?lettre=B">B</a></p>
<hr>
<?php
//Initialiser la lettre de recherche
$lettre = isset($_GET["lettre"])?$_GET["lettre"]:"A"; // La lettre A par défaut 

//Lecture du dossier de recherche
$rep = "livre-d-or/";  
$dir = opendir($rep); 
while ($f = readdir($dir)) 
{ 
   //Filrage : les fichiers commançant par la lettre recherchée
   if($f != "." && $f != ".." && is_file($rep.$f) && eregi("^$lettre.*", $f) ) { 
      //Stocke dans un tableau avant classement par ordre alphabétique
       $tableau[] = $f;  
      
   }//fin if
}//fin while

//Affichage
if (count($tableau) > 0){
    //Tri naturel ignorant la casse
    natcasesort( $tableau );
    foreach ($tableau as $f){
        //nom sans extension
        $nom = eregi_replace('\.[^.]*$', "", $f);
        //Affichage
                echo "<p><a href=\"livre-d-or/".$f."\" target=\"afficheur\">".$nom."</a></p>";
    }
}
else echo "<p>Aucun artistre trouvé!</p>";
?> 
<iframe name="afficheur" width="100%" height="200"></iframe>
--------//////----//---//----//////
-------//---//----//---//----//---//
------//////----//////-----//////
-----||--------||--||---||
Prendre le recul n'est pas une perte de temps.


ps: Affrontez moi dans l'arène

Eléphant du PHP | 160 Messages

06 sept. 2007, 14:55

Super,

Je vais bien vous lire pour comprendre,

Un grand merci et à bientôt,

ViPHP
AB
ViPHP | 5818 Messages

06 sept. 2007, 15:57

Je ne suis pas tout à fait d'accord, l'expresion régulière (utilisant preg_match() ou ereg() ou eregi()) ou encore un test sur $f[0] est plus simple car le remplacer par un strpos() ne fait pas l'affaire puisqu'il cherche la lettre n'importe où dans le nom.
Oui, j'ai un peu trop le réflex (selon les indications du manuel php), d'éviter d'utiliser les regex quand on peut faire autrement pour des pb de performances.
Dans ce cas particulier, puisqu'il s'agit de trouver la première lettre, peut-être que les bench te donneraient raison (quoiqu'un nom de fichier n'est jamais long donc parcourir toute la chaine avec un strpos() ne doit pas être très pénalisant).
Et même remarque pour le cas de suppression de l'extension du fichier, se baser sur la position d'un point est faux car on peut avoir plusieurs points avant celui de l'extension.
Ben strrpos() ne cherche que la position du dernier point, donc c'est pas faux mais vrai. Sinon même remarque que précédemment, ça donne quoi au bench?

D'un point de vue "réponse à la demande de jpsartre" je ne sais pas si ta réponse concernant les regex est appropriée . Il apprend tout juste à faire et ordonner un tableau et tu lui parle régex...
Je me disais qu'on apprend les regex un peu après avoir commencé la notion des tableaux.

Modérateur PHPfrance
Modérateur PHPfrance | 2575 Messages

06 sept. 2007, 16:59

ok, pour le cas de l'extension j'ai confondu strpos de php avec d'autres langages. Mais pour la recherche de la lettre pourquoi chercher la position puisqu'on sait que c'est le début du mot. Le plus simple est d'utiliser $f[0] (sans les regExp)

C'est vrai que les RegExp sont un peu difficiles à appréhender mais c'est une occasion d'inciter à les utiliser.

Aussi, j'ai dit que ce sont deux façons de faire, le choix reste au lecteur. Merci donc AB pour ton apport enrichissant.
--------//////----//---//----//////
-------//---//----//---//----//---//
------//////----//////-----//////
-----||--------||--||---||
Prendre le recul n'est pas une perte de temps.


ps: Affrontez moi dans l'arène

ViPHP
AB
ViPHP | 5818 Messages

06 sept. 2007, 17:46

   //Filrage : les fichiers commançant par la lettre recherchée
   if($f != "." && $f != ".." && is_file($rep.$f) && eregi("^$lettre.*", $f) ) { 
      //Stocke dans un tableau avant classement par ordre alphabétique
       $tableau[] = $f;  
      
   }//fin if
}//fin while
Là je ne comprend pas pourquoi tu testes $f != "." && $f != ".." puisqu'on teste si la première lettre commence par $lettre, ça devrait répondre faux si $f=='.' ou $f == ".." Y-a-t-il une autre explication ?

Je dis ça pour avertir notre ami jpsartre qu'en programmation il y a plusieurs façons de faire, mais il faut choisir la meilleure.
...
Merci donc AB pour ton apport enrichissant.
Très gros progrès diplomatiques :D

Je me préparais à répondre : pour faire des recherches un peu sophistiquées on emploie de préférence preg_match à ereg... Je dis ça pour avertir notre ami jpsartre qu'en programmation il y a plusieurs façons de faire, mais il faut choisir la meilleure...

Et concernant, la rapidité d'exécution, je vais pas me lancer dans des bench pour savoir si
$nom = eregi_replace('\.[^.]*$', "", $f);
est plus rapide d'exécution que
$nom = substr($fichier,0,strrpos($fichier,'.')) 
mais j'ai des gros doutes. Si quelqu'un pouvait m'éclairer sur ce point...

Et puis à force de défendre tes regex, tu as oublié de dire que mon script n'était pas approprié pour faire exactement ce que veux jpsartre puisque je ne cherchais qu'à afficher une liste de fichiers triée sans les extensions. Et comme il a besoin d'utiliser le fichier par la suite, il ne faut retirer l'extension qu'à la lecture du fichier, dans la boucle du tableau.
Ben oui, t'as oublié de parler de l'essentiel même si tu l'as fait dans ton code. Promis je toucherai plus à tes regex :wink: :lol:

Modérateur PHPfrance
Modérateur PHPfrance | 2575 Messages

07 sept. 2007, 09:24

Ecoutes AB, moi je n'ai rien contre ta solution ni les subtr() ni les strpos(). J'ai proposé les regExp en disant qu'elle sont simples et rapides à écrire. Et j'ai utilisé eregi() et preg_match() dans mes propositions pour des raisons d'exemple.
--------//////----//---//----//////
-------//---//----//---//----//---//
------//////----//////-----//////
-----||--------||--||---||
Prendre le recul n'est pas une perte de temps.


ps: Affrontez moi dans l'arène

ViPHP
AB
ViPHP | 5818 Messages

12 sept. 2007, 01:50

[Edit de Zeus] J'ai remis ton message original dans le message où tu était connecté ;)

J'avais bien compris. Si tu avais été légèrement plus diplomate, ou un peu moins catégorique, je n'aurais pas fait cette réponse :wink:

Enfin toujours est-il que pour en avoir le coeur net, j'ai fait quelques bench sur un tableau de 11120 éléments ("sdfrpgmdnr.png","gfhlgvtdyiy.gif","frtyuiopdeqf.jpg","treuuiopf.txt","qszertyf.doc" répétés).

Voici ma procédure de test (en local sur EasyPHP2):
$lettre = 'f';
$tab = array();
$moyenne = array();

for ($i=0; $i < 100; $i++)
{
$time_start = microtime(true);

    foreach ($tableau as $f)
		{
        //$nom = eregi_replace('\.[^.]*$', "", $f);
		//$nom = preg_replace('#\.[^.]*$#', "", $f);
		//$nom = substr($f,0,strrpos($f,'.'));
		//if(eregi("^$lettre.*", $f)) $tab[] = $f;
		//if(preg_match("#^$lettre.*#i", $f)) $tab[] = $f;
		//if(strpos(strtolower($f), strtolower($lettre)) === 0) $tab[] = $f;
		//(strpos(strtolower($f), strtolower($lettre)) === 0)? $tab[] = $f :'';
		} 
		
$time_end = microtime(true);
$time = $time_end - $time_start;
$moyenne[] = $time;
usleep(50000);
}

echo array_sum($moyenne)/count($moyenne);
et voici le résultat sur les trois premières lignes:

Image



Pour le reste, les résultats sont moins significatifs au niveau du temps d'exécution:
if(eregi("^$lettre.*", $f)) $tab[] = $f;// temps : 0.042
if(preg_match("#^$lettre.*#i", $f)) $tab[] = $f;// temps : 0.040
if(strpos(strtolower($f), strtolower($lettre)) === 0) $tab[] = $f;// temps : 0.034
preg est très légèrement plus rapide qu'eregi et consomme 2 à 3 % de ressources UC en moins.
La solution strpos, arrive légèrement en tête et elle offre l'avantage de consommer environ 6 à 10% de ressources UC en moins qu'eregi.


Concernant la dernière ligne pour la comparaison avec l'opérateur ternaire
(strpos(strtolower($f), strtolower($lettre)) === 0)? $tab[] = $f :''; //temps : 0.037 
pour une utilisation UC équivalente à la solution avec if

Le plus étonnant c'est que même
if(strpos(strtolower($f), strtolower($lettre)) === 0) $tab[] = $f; else $tab[] = $lettre;
conserve le même avantage par rapport à
$tab[] = (strpos(strtolower($f), strtolower($lettre)) === 0)? $f : $lettre;
tout en semblant consommer un chouilla moins de ressources UC
Dans ce test l'opérateur ternaire est donc toujours très légèrement en retard.

Conclusion:
- Le premier graphique donne amplement raison au manuel php (heureusement!). Quand on peut éviter les expressions régulières en les remplaçant par deux fonctions simples, y'a pas photo.
- Preg_match est non seulement plus rapide qu'ereg mais il consomme aussi moins de ressources.
- Quand il faut plus de deux fonctions, l'écart diminue et s'inverserait probablement dans des cas plus complexes.
- Moi qui avait lu que les opérateurs ternaires étaient plus rapides à l'exécution. Ben non, pas dans ce test du moins.


note: j'ai pris les regex tels qu'ils ont été écrits. En optimisant le regex pour rechercher la première lettre
if(preg_match("#^$lettre#i", $f)) $tab[] = $f;// temps = 0.038
pour une consommation ressource UC équivalente à la solution strpos

Modérateur PHPfrance
Modérateur PHPfrance | 2575 Messages

12 sept. 2007, 13:32

Trés interessant, en effet =D>
--------//////----//---//----//////
-------//---//----//---//----//---//
------//////----//////-----//////
-----||--------||--||---||
Prendre le recul n'est pas une perte de temps.


ps: Affrontez moi dans l'arène