Script per gestire fotogallery senza DB: da perfezionare

Ho appena finito uno script che mi permette di leggere il contenuto di una directory in cerca di album e rendere disponibile un foglio xml con i dati delle gallery.

Un secondo script può leggere e usare facilmente quei dati.

Ve lo posto così magari potete usarlo e migliorarlo:

File per generare i fogli xml da richiamare direttamente

makerXML.php

<?php

// imposta la dir dove conservare i file xml creati
$xmlDir = "../xmlData/";

// imposta la dir da dove leggere le informazioni
// è quella dove metterete le vostre immagini organizzate in cartelle
// poi spiego come
$imageDir = "../album/";

if ($handleXML = opendir($imageDir)) {

   while (false !== ($album = readdir($handleXML))) {

         if (($album !== '.')
         && ($album !== '..')
         && (is_dir($imageDir.$album))) {


            $fp = fopen($xmlDir.$album.".xml", "w+");

            $fpHead = "<?xml version='1.0'?>\r\n<elenco>\r\n";

            fwrite($fp, $fpHead);

            if ($handleAlbum = opendir($imageDir.$album)) {

               while (false !== ($file = readdir($handleAlbum))) {

                  if (($file !== '.')
                  && ($file !== '..')
                  && ($file !== '..')
                  && (substr($file, -4) == '.jpg')) {

                     // qui potete modificare il modo in cui i dati vengono registrati

                     $fileNome = strlen($file);
                     $fileNome = substr($file, 0, -4);

                     $percorso = $imageDir.$album."/";
                     $percorso = substr($percorso, 3); // per eliminare '../'

                     $fpFile = "\t<foto nome='".$fileNome."' link='".$percorso."' />\r\n";
                  fwrite($fp, $fpFile);

                  }

               }

            }

            $fpFoot = "</elenco>";
         fwrite($fp, $fpFoot);

            fclose($fp);

         } // end If

   } //end while

} else {

   echo "la directory $imageDir non esiste";

}
closedir($handleXML);

?>

ecco la classe che gestisce la lettura del file xml:

galleryClass.php

<?php

class gallery {

   // variabili Globali

   // il file xml che passiamo alla classe
   var $fdata;

   // l'array interno che conterrà i dati
   var $struct;

   // l'output in formato array
   var $data;

   // costruttore
   function gallery ($fdata) {

      $this->struct = array();

      // popolo l'array interno
      $this->data = $this->parse_file($fdata);

   }


   // FUNZIONI PER LA CREAZIONE DELL'ARRAY //
   function startElement($parser, $name, $attrs) {

      $tag = array("name"=>$name,"attrs"=>$attrs);

      array_push($this->struct, $tag);

   }

   function data($parser, $data) {

      if(trim($data)) {

         $this->struct[count($this->struct)-1]['data']=$data;

      }

   }

   function endElement($parser, $name) {

      $this->struct[count($this->struct)-2]['child'][] = $this->struct[count($this->struct)-1];

      array_pop($this->struct);

   }


   function parse_file($file) {

      $xml_parser = xml_parser_create();

      xml_set_element_handler($xml_parser, array($this,"startElement"), array($this,"endElement"));

      xml_set_character_data_handler($xml_parser, array($this,"data"));

      $parse = xml_parse($xml_parser, file_get_contents($file));



      if(!$parse) {

         die("XML parsing error");

         xml_parser_free($xml_parser);

      }

      return $this->struct;

   }

   // FUNZIONI PER L'UTILIZZO DELLE INFORMAZIONI //

   // per ricavare il numero di foto
   function getFotoNumber () {

      $fotoNumber = count($this->data[0]['child']);

      return $fotoNumber;

   }

   // per ricavare le info su una pic
   function getThisPic ($id) {

      $thisData['id'] = $id;
      $thisData['link'] = $this->data[0]['child'][$id]['attrs']['LINK'];
      $thisData['nome'] = $this->data[0]['child'][$id]['attrs']['NOME'];

      return $thisData;
   }

   // per ricavare la prima pic dell'album
   function getFirstPic () {

      $thisData['id'] = 0;
      $thisData['link'] = $this->data[0]['child'][0]['attrs']['LINK'];
      $thisData['nome'] = $this->data[0]['child'][0]['attrs']['NOME'];

      return $thisData;
   }

   // per ricavare il resto delle thumbnails 
   // (vedi oltre per la gerarchia delle cartelle)
   function getThumb () {

      $fotoNumber = $this->getFotoNumber();

      for ($i = $fotoNumber - 1; $i >= 0; $i--) {

         $thisData[$i]['link'] = $this->data[0]['child'][$i]['attrs']['LINK'];
         $thisData[$i]['nome'] = $this->data[0]['child'][$i]['attrs']['NOME'];

      }

      return $thisData;

   }

} // end class

?>

ecco infine un esempio di utilizzo:

fotografie.php

<?php

// file per il template
include ('header.php');

// la classe
include ("galleryClass.php");


$album = 'fotografie';

$gallery = new gallery ("xmlData/".$album.".xml");

if (isset($_GET['id'])) {

   /* vai direttamente a questa foto */

   $id = $_GET['id'];

   /* restituisce un array con la link e nome della foto richiesta */

   $firstPic = $gallery->getThisPic ($id);


} else {

   /* comincia da capo */

   /* restituisce array con link e nome della prima foto */

   $firstPic = $gallery->getFirstPic ();

}


/* visualizza le thumb */

   $thumb = $gallery->getThumb();

?>

      <div id='pix'>

         <img src="<?php echo $firstPic['link'].$firstPic['nome'].".jpg" ?>" alt="<?php echo $firstPic['nome'] ?>" /><br />

         <div id="pic">

            <b>Foto:</b><br /><br />

            <?php

            $fotoNumber = $gallery->getFotoNumber();

            for ($i = $fotoNumber - 1; $i >= 0; $i--) {


               echo "<a href='".$album.".php?id=".$i."' title='".$thumb[$i]['nome']."'>
                 <img src='".$thumb[$i]['link']."50/".$thumb[$i]['nome'].".jpg' alt='".$thumb[$i]['nome']."' width='50' height='50' />
              </a>";

            }

            ?>

          </div><!-- end pic -->

      </div><!-- end pix -->

<?php
include ('foot.php');
?>

Ed in fine ecco come sistemare le foto:

questa è la struttura delle cartelle:

album

|

|- natura

|

|- ritratti

|

|- sport

in ogni cartella secondaria metto le foto che mi interessano, ricordando che i nomi assegnati alle foto saranno i nomi stessi delle foto (per esempio nella descrizione).

ogni album ha una sottocartella che si chiama 50 e che contiene le miniature che hanno lo stesso nome di quelle grandi

esempio:

root/album/fiori/50/margherita.jpg

spero di essere stato chiaro.

accetto qualsiasi suggerimento

inviato 10 anni fa
arjuna
X 0 X

Cavolo, in remoto mi da un problema.

Non visualizza nulla!.

Dovrei fare un debbug ma non so da dove partire.

non mi da errori, ma l'array che deve contenere i dati risulta vuoto!

ma cosa può esserci di diverso tra il remoto e il locale?

risposto 10 anni fa
arjuna
X 0 X

Cavolo.

sono fermo da giorni. Non riesco ad uscire da questo impasse.

Help Please!!!

risposto 10 anni fa
arjuna
X 0 X

Ciao, ieri sera ho provato il tuo script... (anche se uso la versione 4.2 del PHP) e ho notato che nell'esempio che hai riportato viene caricato tutto il file XML e non come lo richiedi tu su un array...

Il problema è sulla funzione parse_file($file) poiché restituisci $this->struct senza avergli assegnato nulla...

return $this->struct;

per questo risulta vuoto...

Io sono riuscito a risolvere il problema... solo che mi manca il passo di inserire il tutto in un array ;) e poi va bene per la versione del PHP citata sopra

Cmq se ti va posso postare la versione finale modificata... appena la concludo!

A presto

risposto 10 anni fa
zeta80
X 0 X

In locale funziona. Questo significa che l'array viene popolato.

Ho utilizzato diverse echo per verificare il progresso dello script e ho visto che il problema è proprio nella funzione che hai evidenziato tu.

Solo che non riesco a capire quale sia l'intoppo.

Il file viene letto e parsato, infatti se metti delle echo in start e in end element vedrai che le funzione vengono correttamente richiamate.... solo che non viene popolato l'array.

Tra un pò riprovo a smanettare, dopo un pò che giro a vuoto mi viene un senso di nausea e di impotenza.

risposto 10 anni fa
arjuna
modificato 10 anni fa
X 0 X

A me non funziona nemmeno in locale...  :(incompatibilità di versioni di PHP

cmq ti credo sulla parola e poi tu fai il parse di tutto il file!!! e non salvi i dati sull'array di tuo interesse...

risposto 10 anni fa
zeta80
X 0 X

credo che il problema sia con array_pop () della funzione endElement ()

infatti printando i vari risultati in locale array_pop funziona regolarmente.

in remoto invece array_pop resetta l'array.

Per questo risuta vuoto alla fine...

ma perchè?

risposto 10 anni fa
arjuna
X 0 X

Pare che il problema possa nascere anche prima.

Quando il parser chiama startElement questo crea l'array come dovrebbe.

Quando il parser chiama endElement l'array $this->struct risulta vuoto e quindi si riparte da zero.

in endElement () c'è:

$this->struct[count($this->struct)-2]['child'][] = $this->struct[count($this->struct)-1];

in remoto il risultato del primo count è -2 in quanto l'array risultando vuoto parte da 0 e non da 2 come dovrebbe!

come mai l'array si azzera quando si passa da una funzione ad un altra?

la classe inizia con la variabile dichiarata $struct

var $struct;

e nel costruttore è inizzializzata come array:

$this->struct = Array ();

ma pare che in remoto questo non sia globale.

risposto 10 anni fa
arjuna
modificato 10 anni fa
X 0 X

Ecco una versione semplificata:

<?php
class gallery {
   var $struct;
   var $fdata;
   var $data;
   function gallery ($fdata) {
      $this->struct = array();
      $this->data = $this->parse_file($fdata);
   }
   function startElement($parser, $name, $attrs) {
      echo "start $name"."<br />";
      $tag = array("name"=>$name,"attrs"=>$attrs);
      array_push($this->struct, $tag);

      echo "<pre>";
      print_r ($this->struct);
      echo "</pre>";

      return $this->struct;

   }

   function data($parser, $data) {
      if(trim($data)) {
         $this->struct[count($this->struct)-1]['data']=$data;
      }
   }
   function endElement($parser, $name) {
      echo "end $name"."<br />";

      echo "<pre>";
      print_r ($this->struct);
      echo "</pre>";

      $this->struct[count($this->struct)-2]['child'][] = $this->struct[count($this->struct)-1];

      array_pop($this->struct);

      return $this->struct;
   }
   function parse_file($file) {

      $xml_parser = xml_parser_create();

      xml_set_element_handler($xml_parser, array($this,"startElement"), array($this,"endElement"));
      xml_set_character_data_handler($xml_parser, array($this,"data"));

      $parse = xml_parse($xml_parser, file_get_contents($file));

      if(!$parse) {
         die("XML parsing error");
         xml_parser_free($xml_parser);
      }

      return $this->struct;
   }
}
$album = 'foto';
$file = "xmlData/".$album.".xml";
$gallery = new gallery ($file);
//print_r ($gallery->data);
?>

ecco l'xml:

<?xml version='1.0'?>
<elenco>
   <foto nome='foto01' link='album/foto/' />
   <foto nome='foto02' link='album/foto/' />
   <foto nome='foto03' link='album/foto/' />
   <foto nome='foto04' link='album/foto/' />
</elenco>
risposto 10 anni fa
arjuna
X 0 X

Ho scritto pure al provider per sapere se c'erano sistemi di sicurezza che bloccavano lo script.

Ma per quanto ciò che ho scritto era molto semplice hanno fatto spallucce dicendo che non era un problema loro.

allora è un problema mio?

ma perchè nessuno ne sa nulla?

Ho controllato ovunque...

risposto 10 anni fa
arjuna
X 0 X

Ciao,

è ovvio che ti rispondessero così... poiché è solo un errore di programmazione.

Ho avuto modo di sperimentare il tuo script e ho notato che l'array $this->struct non viene visto all'esterno della classe e quindi la galleria risulta vuota.

Ho modificato lo script per risolvere questo problema solo che intendo sistemarlo meglio per postare il tutto lunedì.

Domanda: perché non hai utilizzato un file xsl per visualizzare la tua galleria? Io mi sto interessando solo ora all'XML e devo dire che la parte più interessante sono gli XSL. Se lo finisco posto anche quello ;)

A lunedì

Ciao

risposto 10 anni fa
zeta80
X 0 X

Perchè questo è il mio primo esperimento in xml.

Mi serviva un luogo dove registrare delle info.

Mi sarebbe bastato un .txt ma poi ho visto l'xml.

Cos'è quest'altra cosa che tu dici?

Mi puoi postare qualche link a qualche guida?

risposto 10 anni fa
arjuna
X 0 X

C'è una guida su il sito www.html.it non mi ricordo il link, cmq basta che cerchi XML.

Per ora mi sto documentando su un libro... e appena trovo qualcosa di più dettagliato nel web ti posterò i link.

Se ti serviva una gallery con file di testo bastava chiedere... l'avevo già realizzata!!! posterò anche quella lunedì. Che sito stai realizzando? Son curioso

A presto  :bye:

risposto 10 anni fa
zeta80
X 0 X

Il sito gia lo avevo fatto.

Mio zio è fotografo è gli ho fatto un semplice sito in xHtml e CSS come vetrina.

Visto che anche io sono fotografo e spesso ho a che fare con gallerie fotografiche avevo pensato di fare uno script in due parti:

la prima parte doveva:

1) leggere da una cartella root tutte le sotto cartelle incluse

2) interpretare ogni sotto cartella come un nuovo album

3) leggere i file di ogni singola cartella

4) distinguere i file validi (.jpg) dagli altri

5) inserire i relativi dati in un file esterno (database, .txt, .xml, etc)

la seconda parte doveva:

1) leggere il file esterno

2) rendere disponibile i dati in un array utilizzabile

A questo punto mi basta richiamare la classe:

<?php

// album che voglio richiamare
$album = 'foto';

// percorso dove cercare i file
// (lo si può implementare anche nella classe
// ma per comodità l'ho lasciato qui per fare debbug)
$file = "xmlData/".$album.".xml";

// richiamo la classe
// potevo tranquillamente fare anche:
// $gallery = new gallery ("xmlData/foto.xml");
// ma prevedevo di rendere dinamico l'accesso
$gallery = new gallery ($file);

?>

dopo il motore della classe c'erano altre utili funzioni per manipolare l'array:

<?php

$fotoNum = $gallery->getFotoNumber();

function getFotoNumber () {

      $fotoNumber = count($this->data[0]['child']);

      return $fotoNumber;

   }

$thisPic = $gallery->getThisPic($id);

function getThisPic ($id) {

      $thisData['id'] = $id;
      $thisData['link'] = $this->data[0]['child'][$id]['attrs']['LINK'];
      $thisData['nome'] = $this->data[0]['child'][$id]['attrs']['NOME'];

      return $thisData;
   }

?>

e così via...

in questo modo potevo manipolare le gallery in qualsiasi modo.

potevo aggiungere altre info ai file xml come la dimensione delle immagini, un commento preso da un file esterno, tante altre cose insomma...

utile per gestire enormi quantità di foto che obligano ad un lavoro ripetitivo e noioso...

ma per colpa di un problema x = ? non posso andare avanti.

In locale però funziona tutto egregiamente ed un sito che prima aveva 80 pagine ora ne ha solo una decina!

risposto 10 anni fa
arjuna
X 0 X

Ho provato la "versione semplificata" in locale e mi funziona  :dunno:

risposto 10 anni fa
Gianni Tomasicchio
X 0 X

per questo vado al manicomio...

risposto 10 anni fa
arjuna
X 0 X

ho aspettato con ansia lunedì... ma mi puoi dire che risultati hai ottenuto?

magari ci lavoriamo assieme...

risposto 10 anni fa
arjuna
X 0 X

Ciao,

scusa l'attesa ma impegni lavorativi mi hanno impedito di rispettare la parola data.

Come promesso pubblico il codice per costruire la galleria generata dal file XML da te creato tramite la funzione "marker.php".

Ci tengo a premettere che manca una cosa di importanza rilevante per una galleria: il paging.

La classe è stata realizzata con PHP 4.2.3

Ho cercarto di semplificare al massimo la stesura del codice per fare in modo che anche i più inesperti possano utilizzarla.

Sicuramente si possono apportare molte migliorie...

Per qualsiasi dubbio o chiarimento rimango a disposizione.

Ho caricato il tutto nel mio server per fare il test finale e dimostrare che funziona anche in remoto...

http://wordsearch.altervista.org/prova/esempio.php

Ecco qui il codice del file galleryClass.php:

<?php

class gallery {

var $struct = array();

function galleria($file) {

   $this->parser_XML($file);

}

function startElement($parser, $name, $attrs) {

   global $str;

   $tag = array("name"=>$name,"attrs"=>$attrs);

   if ($name != 'ELENCO')

      array_push($str, $tag);

}

function endElement($parser, $name) {

}

function characterData($parser, $data) {

}

function parser_XML($file) {

   $xml_parser = xml_parser_create();

   # Si utilizza il case-folding per essere certi di trovare le tag in $map_array

   xml_parser_set_option($xml_parser, XML_OPTION_CASE_FOLDING, true);

   xml_set_element_handler($xml_parser, array($this,"startElement"), array($this,"endElement"));

   xml_set_character_data_handler($xml_parser, array($this,"characterData"));

   if (!($fp = fopen($file, "r"))) {

       die("Non si riesce ad aprire il documento XML");

   }

   while ($data = fread($fp, 4096)) {

       if (!xml_parse($xml_parser, $data, feof($fp))) {

           die(sprintf("Errore XML: %s alla linea %d",

                    xml_error_string(xml_get_error_code($xml_parser)),

                    xml_get_current_line_number($xml_parser)));

        }

   }

   xml_parser_free($xml_parser);

} //end parser_XML

} //end class

# Funzioni Aggiuntive

function getImage($id, $struttura) {

   if (isset($struttura[$id])) {

      $immagine['link'] = $struttura[$id]['attrs']['LINK'];

      # Visto che tutte le immagini che carico sono di tipo JPG

      $immagine['nome'] = $struttura[$id]['attrs']['NOME'].".jpg";

      return $immagine;

   } else {

      return "";

   }

}

?>

Ecco qui invece il codice di esempio:

<?php

# Includo la classe

include ("./galleryClass.php");

# Indico il percorso per l'immagine selezionata che deve essere grande ;)

$path = "gallery1/images/";

# Dichiaro la variabile che conterrà la struttura

# del mio file XML

$str = array();

$gallerythumbs = new gallery();

$gallerythumbs->galleria("thumbs.xml");

$structthumbs = $str;

# Se è stata selezionata un'immagine...

if (isset($HTTP_GET_VARS['id'])) {

   /* vai direttamente a questa foto */

   $id = $HTTP_GET_VARS['id'];

   # Ricavo i dati dell'immagine...

   $firstPic = getImage($HTTP_GET_VARS['id'], $structthumbs);

} else {

   # Seleziono i dati della prima immagine

   $id = 0;

   $firstPic = getImage(0, $structthumbs);

}

# Numero totale di immagini

$fotoNumber = count($structthumbs);

# Parte di integrazione con HTML

# Essenzialmente è strutturato in 2 parti:

# - La parte superiore visualizza l'ingrandimento dell'immagine selezionata o della prima della lista (caricando il percorso selezionato all'inizio);

# - La parte inferiore carica dalla struttura tutte le immagini di anteprima contenute nel file come link "<a>".

?>

<html>

<head>

<title>Galleria XML</title>

<style type="text/css">

   a img {

      border: 0px;

      width: 50px;

      height: 50px;

      margin: 5px;

   }

</style>

</head>

<body>

      <div>

         <div style="width: 100%; text-align: center;">

            <img src="../<?=$path.$firstPic['nome'] ?>" alt="<?=$firstPic['nome'] ?>" /><br />

            <?=($id+1)?>/<?=$fotoNumber?>

         </div>

         <div id="pic">

            <b>Foto:</b><br /><br />

            <?php

            for ($i = 0; $i < $fotoNumber; $i++) {

               $Pic = getImage($i, $structthumbs);

               echo "<a href=\"esempio.php?id=".$i."\" alt=\"".$Pic['nome']."\"><img src=\"../".$Pic['link'].$Pic['nome']."\" alt=\"".$Pic['nome']."\" /></a>";

            }

            ?>

          </div><!-- end pic -->

      </div><!-- end fisrt div -->

</body>

</html>

Rimango a tua disposizione se ci sono dubbi o commenti e mi scuso nuovamente per il ritardo.

Buona giornata e alla prossima.

Zeta80  8)

risposto 10 anni fa
zeta80
X 0 X

Ora scappo in facoltà ma appena torno verifico la situazione.

Ti ringrazio anticipatamente per il tuo lavoro...

risposto 10 anni fa
arjuna
X 0 X

Ok,

la gallery funziona ma hai dovuto inserire nel parser un controllo sulla voce ELENCO.

il fatto è che come lo avevo impostato il suo funzionamento era indipendente dal contenuto del file xml, inserendo invece tale voce non si possono fare xml maggiormente strutturati (con più nodi in pratica).

Per ora è perfetto ma dato che volevo renderlo abbastanza universale si pone il problema della compatibilità con altre strutture...

Poi devo ancora capire cosa sono tutte quelle funzioni, non mi piace implementare codice che non conosco...

Cmq sei stato più più che prezioso...

Tu avevi in mente altri miglioramenti?

Potremo farne uno script abbastanza performante, che ne pensi?

risposto 10 anni fa
arjuna
X 0 X

Cos'è $structthumbs = $str;

prima dichiari $str come array, ma non risulta vuoto?

risposto 10 anni fa
arjuna
X 0 X

La proposta per creare uno script universale è interessante...  cmq non ho usato molte funzioni sconosciute!

$strcutthums è un semplice array che riprende la struttura $str... se vuoi puoi utilizzare tranquillamente $str.

$str non risulta vuoto... come puoi notare dalla pagina del sito che ho pubblicato  O0

Io avevo già creato qualche script per una galleria senza DB, che veniva completamente gestita con un file di testo... Appena ho un attimo di tempo ricontrollerò i codici e li posterò magari in una sezione di questo sito...

Ora scappo a casa...

buona serata  8)

risposto 10 anni fa
zeta80
X 0 X

Lo vedo che non è vuoto... lo script funziona benissimo (ho fatto qualche lieve modifica), il fatto è che non capisco come si popoli...  :-\

risposto 10 anni fa
arjuna
X 0 X

L'array $str viene popolato grazie a questa funzione e tramite l'istruzione array_push che avevi utilizzato anche tu...

function startElement($parser, $name, $attrs) {

   global $str;

   $tag = array("name"=>$name,"attrs"=>$attrs);

   if ($name != 'ELENCO')

      array_push($str, $tag);

}

Sono d'accordo con te nel fatto che siano state necessarie delle modifiche.. soprattutto dal punto di vista della creazione della pagina ;) Io ho aggiunto solo un semplice css... nulla di più ;)

risposto 10 anni fa
zeta80
X 0 X

Vi propongo un "potente"  :coolsmiley:  parser XML:

<?php

$xml = simplexml_load_string(

"<?xml version='1.0'?>

<elenco>

   <foto nome='foto01' link='album/foto/' />

   <foto nome='foto02' link='album/foto/' />

   <foto nome='foto03' link='album/foto/' />

   <foto nome='foto04' link='album/foto/' />

</elenco>");

foreach ($xml->foto as $foto) {

   echo $foto['nome'] . ' -> ' . $foto['link'] . "\n";

   }

?>

 :bye:

risposto 10 anni fa
Gianni Tomasicchio
X 0 X

 :buck:

risposto 10 anni fa
arjuna
X 0 X
Effettua l'accesso o registrati per rispondere a questa domanda