Skip to content
This repository has been archived by the owner on Nov 9, 2022. It is now read-only.
giulia0709 edited this page Jun 23, 2016 · 13 revisions

logo

Prefazione

Il Target di questo progetto è quello di realizzare un applicativo web in grado di offrire un servizio di evacuazione efficiente, efficace e facilmente fruibile attraverso il world wide web. Per fare ciò ci siamo avvalsi di alcune tecnologie quali:

  • HTML 5
  • PHP 5
  • Zend framework
  • Javascript
  • JQuery
  • Materialize
  • MySql

Progettazione del Database

Il primo step della realizzazione dell’applicativo web è stata l’analisi degli elementi appartenenti al dominio applicativo in sviluppo quali:

  • Gli utenti - opportunamente categorizzati
  • Gli edifici - suddivisi in piani e zone
  • Gli eventi - suddivisi in base alla tipologia

I Piani di Fuga - inerenti ad un determinato piano Per esigenze tecniche sono stati aggiunte successivamente le Faq consultabili da un utente e le Posizioni rappresentanti la collocazione di un utente all’interno di un edificio. Quello che abbiamo ottenuto è il seguente schema Entity Relationship

ER

In seguito è stato tradotto in uno schema logico che rappresenta un buon compromesso tra ottimizzazione e fruibilità delle informazioni, dosando la normalizzazione e l’eliminazione delle ridondanze in funzione di un agevole manipolazione in Zend Framework

schema logico


Design Pattern MVC

Il motivo per cui si adotta un design pattern è quello di rendere i progetti di tipo object-oriented ​ più flessibili e riutilizzabili. Nello specifico l’MVC si articola in tre spazi di lavoro principali:

  1. Il ​ Model con il compito di interfacciarsi con il DMBS che fornisce i servizi MySQL e custodisce le informazioni in una base di dati.
  2. La ​ View ​ che ha il compito di servire l’utenza delle informazioni ad essa referenziate rendendo tale meccanismo il più ​ user-friendly ​ possibile
  3. Il ​ Controller​ , cuore dell’applicativo, che orchestra model e view filtrando le interazioni tra i due.

Zend Framework

Zend Framework logo

Zend è un framework opensource php che negli anni ha riscosso un discreto successo e vanta una grande community che la supporta. Avvalendosi del design patern mvc è uno strumento di sviluppo molto versatile che permette di realizzare applicativi web scalabili ed affidabili. Nel progetto qui realizzato ci si avvale della versione 1.12.13​ . Passiamo ora ad una più attenta analisi dei componenti del progetto

Struttura del progetto

Bootstrap

File di configurazione del bootstrap contenente

  • il settaggio del ​base url
  • l’inizializzazione dei ​placeholders delle view
  • il settaggio del ​loader ​con la definizione del namespace App_ e l’aggiunta delle risorse 'modelResource','models/resources' e 'Resource’ indispesabili per il ​naming ​delle nostre classi.
  • la definizione dell’ ​adapter ​che include il file ​include/connect.php con le credenziali di login.

Model

il Model è strutturato su tre directory

  • le classi ​Model ​sono quell’insieme di classi che permettono ad un alto livello di astrazione di comunicare con la base di dati e di ottenere degli oggetti facilmente consultabili
  • le classi ​Resources ​ rappresentano ciascuna una specifica tabella dalle quali possono prelevare un set di elementi da trasmettere ad una determinata classe Model
  • le classi ​ Items ​ che rappresentano una singola occorrenza di una tabella e permettono di accedervi e manipolarla per poi comunicarla alla corrispettiva classe Model

[Class diagram del model](Class diagram model)

Alcune implementazioni degne di nota sono sicuramente quelle che implementano dei ​Join​ su delle tabelle con ​chiavi esterne

//metodo che restituisce i piani di fuga di una zona 
public function getAssegnazioniByZona($zona){
             $select=$this->select()
            ->where('zona= ? ',$zona)
            ->where('abilitato=1');
        
        return $this->fetchAll($select);

    }
//metodo che restituisce tutte le persone all’interno di un determinato edifici
public function  getNumCollocazioniByEdificio($edificio) {

        $select = $this->select()
                       ->setIntegrityCheck(false)
                       ->from(array('c' => 'collocazione'), array())
                       ->join (array('pos' => 'posizione'), 'c.idPosizione=pos.id', array())
                       ->join (array('p' => 'piano'), 'pos.numPiano=p.numeroPiano AND p.edificio=pos.edificio',
                                array('numPersone' => 'COUNT(*)'))
                       ->where ('p.edificio = ?', $edificio);
        return $select;

    }

View

La view dell’applicativo contiene un file ​.phtml ​per ogni azione del controller da cui è referenziata.

##Controller Il controller è la struttura che orchestra view e model ed è composto da quattro classi rappresentati ognuna una tipologia diversa di utente che accede all’applicativo ed un ​errorController ​ che reindirizza agli errori.

Class diagramm Controller

Il Controller fa largo uso dei metodi php file_exist() unlink() e rename()
per manipolare le immagini e le piante degli edifici che sono collocati e strutturati secondo una gerarchia ad albero nella cartella /image della sezione public di Zend.

Qui di seguito riproponiamo (in uno dei metodi più importanti del controller livello3 che ha il compito di rinominare tutti i file collegati ad un edificio e di aggiornare il database)

/**
     * Rinomino tutti i file e le occorrenze del db collegate ad un deerminato edificio
     * @param $nome_vecchio_edificio
     * @param $nome_nuovo_edificio
     */
protected function rinominaEdificio($nome_vecchio_edificio,$nome_nuovo_edificio){

        //model
        $edificioModel  = new Application_Model_Edifici();
        $posizioniModel = new Application_Model_Posizioni();
        $pianiModel     = new Application_Model_Piani();
        $pdfModel       = new Application_Model_PianoDiFuga();
        $adminModel      = new Application_Model_Admin();
        $stringa_esplosa = null;

        //edificio

        $set = $edificioModel->getEdificio($nome_nuovo_edificio); //attenzione  [0]
        $mappa_vecchio_edificio = $set[0]->mappa;
        $stringa_esplosa = explode(".", $mappa_vecchio_edificio);

        //rinomino il file corrispondente
        $file1 = APPLICATION_PATH . '/../public/image/edifici/' . $mappa_vecchio_edificio;
        $nuovoNomeFile = $nome_nuovo_edificio . "." . end($stringa_esplosa);
        $file2 = APPLICATION_PATH . '/../public/image/edifici/' . $nuovoNomeFile;
        rename($file1, $file2);


        $edificioModel->updateEdificio(array('mappa' => $nuovoNomeFile), $nome_nuovo_edificio);

        //aggiorno le posizioni nel db
        $posizioniModel->updateByEdificio($nome_vecchio_edificio,array(
            'edificio' => $nome_nuovo_edificio
        ));

        //aggiorno la zona nel db
        $adminModel->updateZoneByEdificio($nome_vecchio_edificio,array(
            "edificio"  => $nome_nuovo_edificio
        ));

        //pianta

        $pianiset = $pianiModel->getPianiByEdificio($nome_nuovo_edificio);

        foreach ($pianiset as $item){

            //prelevo la pianta vecchia
            $vecchiaPianta = $item->pianta;
            $pianta_esplosa = explode("Piano",$vecchiaPianta);

            $nuovaPianta = $nome_nuovo_edificio . " Piano".end($pianta_esplosa);

            //aggiorno nel db
            $pianiModel->updatePianiByPianta($vecchiaPianta,array(
                "pianta" => $nuovaPianta
            ));

            //rinomino il file
            $file1 = APPLICATION_PATH . '/../public/image/piante/' . $vecchiaPianta;
            $file2 = APPLICATION_PATH . '/../public/image/piante/' . $nuovaPianta;
            rename($file1, $file2);

            //mappature
            $file_vecchia_mappa = $nome_vecchio_edificio . " Piano " .$item->numeroPiano . ".txt";
            $file_nuova_mappa = $nome_nuovo_edificio . " Piano " . $item->numeroPiano . ".txt";
            $path1 = APPLICATION_PATH . '/../public/image/piante/map/' . $file_vecchia_mappa;
            $path2 = APPLICATION_PATH . '/../public/image/piante/map/' . $file_nuova_mappa;
            if(file_exists($path1)){
                rename($path1,$path2);
            }

            //piani di fuga
            print_r($item->numeroPiano.'<br>');

            $setpdf = $pdfModel->getByEdificioPiano($nome_vecchio_edificio,$item->numeroPiano);

            //per ogni piano di fuga colledato ad un determinato piano
            foreach ($setpdf as $pdf){

                //modifico l'occorenza nel db
                $vecchiaPiantaPdf   = $pdf->pianta;
                $vecchiaPiantaEsplosa = explode("Piano",$vecchiaPiantaPdf);
                $nuovaPiantaPdf     = $nome_nuovo_edificio . " Piano" .end($vecchiaPiantaEsplosa);

                $pdfModel->updateByPianta($vecchiaPiantaPdf,array(
                    'pianta' => $nuovaPiantaPdf
                ));

                //aggiorno il file

                $path1 = APPLICATION_PATH . '/../public/image/piante/piani di fuga/' . $vecchiaPiantaPdf;
                $path2 = APPLICATION_PATH . '/../public/image/piante/piani di fuga/' . $nuovaPiantaPdf;

                if(file_exists($path1)){
                    rename($path1,$path2);
                }
            }


            //zone

            $file_vecchia_zona_jpg = $nome_vecchio_edificio . " Piano " . $item->numeroPiano . ".jpg";
            $file_vecchia_zona_png = $nome_vecchio_edificio . " Piano " . $item->numeroPiano . ".png";
            $file_nuova_zona_jpg = $nome_nuovo_edificio. " Piano " . $item->numeroPiano . ".jpg";
            $file_nuova_zona_png = $nome_nuovo_edificio . " Piano " . $item->numeroPiano . ".png";

            $path_old_jpg = APPLICATION_PATH . '/../public/image/piante/zone/' . $file_vecchia_zona_jpg;
            $path_old_png = APPLICATION_PATH . '/../public/image/piante/zone/' . $file_vecchia_zona_png;
            $path_new_jpg = APPLICATION_PATH . '/../public/image/piante/zone/' . $file_nuova_zona_jpg;
            $path_new_png = APPLICATION_PATH . '/../public/image/piante/zone/' . $file_nuova_zona_png;


            //controllo se ho un file in jpg
            if(file_exists($path_old_jpg)){
                //aggiorno in jpg
                rename($path_old_jpg,$path_new_jpg);
            }

            //controllo se ho un file in png
            if(file_exists($path_old_png)){
                //aggiorno in png
                rename($path_old_png,$path_new_png);
            }

        }
    }

Form e Custom Validator

Zend Framework, fra i vari vantaggi, offre un interfaccia prestabilita per creare delle classi Form da inserire nell’applicativo . Nel nostro caso sono state inserite per una moltitudine di operazioni quali:

  • registrazione e log-in
  • modifica dei dati di un utente
  • posizionamento
  • modifica ed inserimento delle informazioni di un edificio Inoltre è stato realizzato un ​ Custom Validator
/** 
*    Questo metodo prende in input una stringa che rappresenta le zone da  
*    inserire usufruendo di un’espressione regolare verifica se la stringa 
*    è formattata in modo corretto. 
*/  

class App_Validate_ValidatoreZona extends Zend_Validate_Abstract
{
    const errore=null;

    protected $_messageTemplates = array(
        self::errore => "Le zone devono essere del tipo [A-Z], separate da uno spazio, non ripetute e lunghe massimo un carattere"
    );

    public function isValid($value)
    {
        $this->_setValue($value);
        $controllo=str_replace(" ", "", $value);
        $nespressioneregolare=strlen($controllo)-1;
        $n=strlen($controllo)-1;

        for($cont=0;$cont<$n+1;$cont++){
            $arrayappoggio=array();
            $varappoggio=$controllo[$cont];
            for($cont2=$cont;$cont2<$nespressioneregolare;$cont2++)
            {
                $arrayappoggio[$cont2]=$controllo[$cont2+1];
            }


            if(in_array($varappoggio, $arrayappoggio))
            {
                $this->_error(self::errore);
                return false;
            }

            $n--;

        }
        if (!mb_ereg_match('([A-Z][[:space:]]){'.$nespressioneregolare.'}[A-Z]',$value)) {
            $this->_error(self::errore);
            return false;
        }

        return true;
    }
}
class Application_Form_Inseriscizone extends Zend_Form
{

    public function init()
    {
        $this->setMethod('post');
        $this->setName('inseriscizone');
        $this->setAttrib('enctype', 'multipart/form-data');
        $this->setAction(''); // definirò l'azione nel controller quando istanzio la form
        $myValidator = new App_Validate_ValidatoreZona();


        $this->addElement('text','zone', array(
            'required'  => true,
            'label'     => 'Zone (inserisci le zone separate da uno spazio)',
            'validators'=>array($myValidator)
        ));
        

        $this->addElement('file', 'pianta', array(
            'label' => 'Pianta',
            'destination' => APPLICATION_PATH.'/../public/image/piante/zone',
            'validators' => array(
                array('Count', false, 1),
                array('Size', false, 30960000),
                array('Extension', false, array('jpg','png'))
            ),
            'required' => true
        ));

        $this->addElement('submit', 'ok', array(
            'class'         => 'btn waves-yellow green',
        ));

    }


}

JQuery e AJAX

ajax jquery logo

Queste due tecnologie che fanno uso del linguaggio javascript sono l’ultima avanguardia della programmazione lato client. La prima permette di rendere meno verbosa la scrittura degli script, eseguire validazione lato client e di “pilotare” le animazioni delle interfacce utente. La seconda permette di ovviare al regolare workflow del modello Client-Server realizzando una ​**interazione asincrona **​.

Il sito si serve di alcune animazioni jQuery nell’​indexView ​del ​Livello1Controller ​per segnalare all’utente un pericolo imminente. Lo script esegue il ​Polling​ per ricaricare periodicamente la pagina e qualora sia in atto una procedura di evacuazione viene suggerito all’utente di consultare il piano di fuga per la sua posizione

 <script>
   //polling
   $( document ).ready(function() {
		setInterval(poll, 45000);
		function poll() {
			location.reload();
		}

	});
   //animazione che fa lampeggiare lo sfondo della pagina
  if($evacuare){
    $( document ).ready(function() {
			setInterval(alertFunc, 800);
		function alertFunc() {
			$( "body" ).effect("highlight",{color: 'yellow'},600);
		}
	});
  }
   
 </script>

L’interazione asincrona con Ajax è presente sulla DashboardView del Livello2Controller per animare le Form delle evacuazioni

   $("#edificio").on("change", function(){
 var actionUrl= ajaxEdificio();

   $.ajax({
     type : 'POST',
     url : actionUrl,
     data : $("#edificio").serialize(),
     dataType : 'json',
     success : pianiPopulate
   });
});

function pianiPopulate(data){

 $('dd#piano-element').find("ul").find("li").remove();
 $('dd#piano-element').find("select").find("option").remove();
 $.each(data, function(key, val){

$('dd#piano-element').find("ul."+"dropdown-content      select-dropdown").append('<li><span>Piano'+ val +'</span></li>');
$('dd#piano-element').find("select").append('<option value="'+ val +'">Piano '+ val +'</option>');

 });
 $('select').material_select();
}

Materialize

logo materialize

Uno dei requisiti principali di un applicazione web al passo con i tempi è la fruibilità dei contenuti.

Per venire in contro a tale esigenza abiamo adottato un Framework CSS molto versatile che adotta i canoni del Material Design rendendo la pagina conforme allo standard a cui si riferiscono tutti i principali servizi che adoperano nel Worl Wide Web.

Questo framework, utilizzando le librerie JQuery, predispone dei fogli di stile predefiniti che reinterpretano i tag html e, qualora inseriti come attributo, adottano gli stili delle classi definite per assegnare determinate animazioni ad un componente

una form normale realizzata con zend form

form normale

una form realizzata con Materialize

form materialize


#Schema di link link