Pagina 1 di 6 1 2 3 ... ultimoultimo
Visualizzazione dei risultati da 1 a 10 su 58
  1. #1

    [PIPPE MENTALI] gestione degli eventi in PHP

    Salve a tutti,
    stavo lavorando ad una gestione degli errori in PHP 4 che assomigli alle eccezioni (presenti in PHP5)e credo che stia venendo fuori qualcosa di carino

    La gestione degli errori in PHP4 è abbastanza insoddisfacente, di solito si fa così

    if(!operazione)
    {
    //fai qualcosa per l'errore
    }
    elseif(!altraoperazione)
    {
    //fai qualcosa per l'errore
    }

    etc.etc.

    Una serie di controlli che vanno ripetuti ogni volta che si incapsulano le operazioni in un'altra funzione o classe

    Oppure si usa il sistema "ufficiale" di php4 con le funzioni trigger_error e set_error_handler, che però rispetto alle eccezioni ha il difetto di non consentire al programmatore di individuare gli errori per tipologia (es. errore di connessione, errore nella query, altra "malattia" dello script)
    http://www.php.net/set_error_handler

    Ispirandomi ad actionscript ho tirato fuori questa robbba, che trovo abbastanza comoda per intercettare gli errori

    Eccola applicata ad un esempio con FTP

    function ftpError($message, $id, &$sender)
    {
    //qui dentro gestisco l'errore come mi pare
    //qui sotto solo un esempio di ciò che accade all'interno

    $args= func_get_args() ;
    print_r($args) ;
    }

    function getError($message, $id, &$sender)
    {
    //qui dentro gestisco l'errore come mi pare
    //qui sotto solo un esempio di ciò che accade all'interno

    $args= func_get_args() ;
    print_r($args) ;
    }

    function getOk($message, $id, &$sender)
    {
    //qui dentro gestisco l'errore come mi pare
    //qui sotto solo un esempio di ciò che accade all'interno

    $args= func_get_args() ;
    print_r($args) ;
    }

    $ftp = new FTPhandler() ;

    /*anzichè una funzione
    al posto di ftpError posso mettere array($oggetto, 'metodo') oppure
    array('nomeclasse', 'metodo')
    */

    $ftp->addEventListener('onError', 'ftpError') ;


    $dns = array
    (
    'host'=>'',
    'user'=>'',
    'pass'=>'',
    'port'=>21
    ) ;
    $conn = $ftp->open($dns, true);

    /*anzichè una funzione
    al posto di getError e getOk posso mettere array($oggetto, 'metodo') oppure
    array('nomeclasse', 'metodo')
    */

    $conn->addEventListener('onError', 'getError') ;
    $conn->addEventListener('onGetComplete', 'getOk') ;

    $conn->getBinary('pippo1.zip', './dir/miofileremoto1.zip') ;
    $conn->getBinary('pippo2.zip', './dir/miofileremoto2.zip') ;
    $conn->getBinary('pippo3.zip', './dir/miofileremoto3.zip') ;
    $conn->getBinary('pippo4.zip', './dir/miofileremoto4.zip') ;
    $conn->getBinary('pippo5.zip', './dir/miofileremoto5.zip') ;
    $conn->getBinary('pippo6.zip', './dir/miofileremoto6.zip') ;
    $conn->close() ;

    Qui sotto le classi

    <?php

    class EventDispatcher
    {
    //array associativo che contiene gli eventi
    var $events ;

    function EventDispatcher()
    {
    $this->events = array();
    }

    /*
    Genera l'evento: $eventName è una stringa che identifica l'evento (es. onError)
    */
    function dispatchEvent($eventName, $eventId, $eventMessage)
    {
    $args = func_get_args() ;
    //Passo un riferimento all'oggetto che invia l'evento
    $args[] = &$this ;
    $eventName = array_shift($args);
    /*
    Impedisce errori nel caso in cui non sia stato previsto alcun listener
    per l'evento
    */
    if(!isset($this->events[$eventName]))
    {
    return ;
    }
    call_user_func_array($this->events[$eventName], $args) ;
    }

    /*
    - $eventName è una stringa che identifica l'evento (es. onError)
    - $handler può essere una stringa (nome funzione) o
    un array ( array(oggetto, 'metodo') e anche
    array('classe', 'metodo_statico') )
    */
    function addEventListener($eventName, $handler)
    {
    $this->events[$eventName] = $handler ;
    }

    function removeEventListener($eventName)
    {
    unset($this->events[$eventName]) ;
    }
    }


    class FTPhandler extends EventDispatcher
    {
    function FTPhandler()
    {
    parent::EventDispatcher() ;
    }

    function open($dns, $passive = false, $timeout=30)
    {

    $link = ftp_connect(
    $dns['host'] ,
    $dns['port'] ,
    $timeout
    ) ;
    if(!$link)
    {
    $this->dispatchEvent('onError', "Connessione a {$server} fallita", 'CONN_FAILED') ;
    }

    elseif(!ftp_login($link, $dns['user'], $dns['pass']))
    {
    $this->dispatchEvent('onError', "Login fallito (user:{$dns['user']}, pass:{$dns['pass']}) ", 'LOGIN_FAILED') ;
    }

    elseif($passive && !ftp_pasv($link, $passive))
    {
    $this->dispatchEvent('onError', "Impossibile settare la modalità FTP passiva", 'SET_PASV_FAILED' ) ;
    }

    return(new FTPlink($link, $dns)) ;
    }
    }

    class FTPlink extends EventDispatcher
    {
    var $link ;
    var $dns ;

    function FTPlink($link, $dns)
    {
    parent::EventDispatcher() ;
    $this->link = $link ;
    $this->localSaveDir = './' ;
    $this->overwrite = false ;
    $this->dns = $dns ;
    }

    function localSavePath($dir)
    {
    $this->localSaveDir = $dir ;
    }

    function setOverwrite($what=true)
    {
    $this->overwrite = $what ;
    }

    function _get($localFileName, $remoteFile, $type)
    {
    $localSavePath = str_replace('//', '/', $this->localSaveDir.'/'.basename($remoteFile)) ;
    $remoteList = ftp_nlist($this->link, dirname($remoteFile)) ;
    if(!$remoteList)
    {
    $this->dispatchEvent('onError', "Impossibile ottenere la lista dei file remoti in {$remote}", 'FTP_NLIST_FAILED') ;
    }
    elseif (!in_array($remoteFile, $remoteList) ) {

    $this->dispatchEvent('onError', "Il file remoto {$remoteFile} non esiste", 'FTP_NO_FILE') ;
    }
    elseif(!is_writable($this->localSaveDir))
    {
    $this->dispatchEvent('onError', "La directory {$this->localSaveDir} non è scrivibile", 'FTP_NO_WRITE_PERMS') ;
    }
    elseif(!$this->overwrite && file_exists($localSavePath))
    {
    $this->dispatchEvent('onError', "Il file {$localSavePath} già esiste", 'FTP_FILE_EXISTS') ;
    }
    else if (! ftp_get($this->link, $localSavePath, $remoteFile, $type) ) {

    $this->dispatchEvent('onError', "Impossibile prelevare e salvare il file {$remoteFile}", 'FTP_GET_FAILED') ;
    }
    else
    {
    $this->dispatchEvent('onGetComplete', "{$remoteFile} scaricato correttamente", 'FTP_GET_OK') ;
    }
    }
    //END _get

    function getBinary($local, $remote)
    {
    $this->_get($local, $remote, FTP_BINARY) ;
    }
    //END function

    function getAscii($local, $remote)
    {
    $this->_get($local, $remote, FTP_ASCII) ;
    }
    //END function


    function close()
    {
    if(!ftp_close($this->link))
    {
    $this->dispatchEvent('onError', "Errore nella chiusura della connessione a {$this->dns['host']}", 'FTP_CLOSE_FAILED') ;
    }
    }
    }

    ?>
    per favore NIENTE PVT TECNICI da sconosciuti

  2. #2
    e' un gestore eventi che simula metodi AS , ma lo vedo ben lontano dal try catch Exception $e ... forse il titolo e' stra azzeccato: PIPPE MENTALI

    alla fine se usi if ed elseif ci sono tanti modi di monitorare la situazione dello script e degli errori, questo magari e' fatto bene ma non diverso da tanti altri
    Formaldehyde a new Ajax PHP Zero Config Error Debugger

    WebReflection @WebReflection

  3. #3
    Ciao Andrea,
    è molto diverso dall'if else, con if..else devi fare ilcontrollo, ogni volta che incapsuli le tue funzioni in un altra funzione o classe (si chiama bubbling degli errori), invece in questo modo effettui il controllo in un solo punto una volta per tutte

    Altro esempio

    $db = new MySQLDB() ;
    $db->addEventListener('onError', $listener) ;

    $db->connect() ;
    $db->query() ;

    etc.etc.
    Non faccio più controlli perchè il listener è in attesa di eventi

    Per certi versi è anche migliore del sistema delle eccezioni, purtroppo, come spesso accade con le buone idee, ho visto che qualcun altro ci ha già pensato

    http://pear.php.net/pepr/pepr-proposal-show.php?id=186
    http://blog.php-tools.net/archives/1...t-support.html
    per favore NIENTE PVT TECNICI da sconosciuti

  4. #4
    si ok, io mi riferivo a queste

    if(!ftp_close($this->link))
    {
    $this->dispatchEvent('onError', "Errore nella chiusura della connessione a {$this->dns['host']}", 'FTP_CLOSE_FAILED') ;
    }


    comunque mandi "a mano" degli errori e non puoi includere tante istruzioni su un unico "try" come e' invece per le eccezioni, annidate e non , intendevo questo ... riguardo pear, e' sempre una mattonella avanti

    io non ho mai usato pear


    P.S. mentre con pear gia' usano sqlite 3
    Formaldehyde a new Ajax PHP Zero Config Error Debugger

    WebReflection @WebReflection

  5. #5
    [supersaibal]Originariamente inviato da andr3a
    si ok, io mi riferivo a queste

    if(!ftp_close($this->link))
    {
    $this->dispatchEvent('onError', "Errore nella chiusura della connessione a {$this->dns['host']}", 'FTP_CLOSE_FAILED') ;
    }
    comunque mandi "a mano" degli errori e non puoi includere tante istruzioni su un unico "try" come e' invece per le eccezioni, annidate e non , intendevo questo ...
    Però anche con le eccezioni, per ora, devo fare throw manuale, e comunque cong li eventi posso settare un solo listener per più operazioni, esattamente come in actionscript.

    P.S. mentre con pear gia' usano sqlite 3 [/supersaibal]
    Come fanno a usare sqlite 3? Da quel che sapevo l'estensione PHP è ancora alla versione 2
    per favore NIENTE PVT TECNICI da sconosciuti

  6. #6
    [supersaibal]Originariamente inviato da Fabio Heller
    Però anche con le eccezioni, per ora, devo fare throw manuale
    [/supersaibal]
    non necessariamente:
    codice:
    <?php // 5
    class ErrorCapture {
    	private $__handler;
    	final function __construct() {
    		$this->__handler = set_error_handler(
    			array(
    				&$this,
    				'throwException'
    			)
    		);
    	}
    	final public function throwException(
    		$errno,
    		$errstr,
    		$errfile,
    		$errline
    	) {
    		throw new Exception( $errstr );
    	}
    }
    new ErrorCapture;
    
    try {
    	mysql_connect( 'localhost', 'nouser', 'nopass' );
    }
    catch( Exception $e ) {
    	echo 'Error
    ';
    	echo $e->getMessage();
    }
    ?>


    [supersaibal]Originariamente inviato da Fabio Heller
    Come fanno a usare sqlite 3? Da quel che sapevo l'estensione PHP è ancora alla versione 2 [/supersaibal]
    ero convinto di averlo visto usare in pear, ma non trovo piu' il layer, comunque leggi le specifiche di questo
    http://www.php.net/manual/en/ref.pdo.php


    [editato]
    che poi sul link delle PECL c'e' la dll
    Formaldehyde a new Ajax PHP Zero Config Error Debugger

    WebReflection @WebReflection

  7. #7
    [supersaibal]Originariamente inviato da andr3a
    non necessariamente:
    Ah ok, ma io mi riferivo agli errori di tipo "personale" (quelli che vuoi creare tu), che anche con il trucco che hai utilizzato caso richiedono un trigger_error.
    Inoltre in quel modo puoi solo lanciare ecceioni generiche, se vuoi creare un eccezione specifica per mysql, una per ftp e una per...sei costretto a lanciare un nuovo handler, es. errorCapture2

    che poi sul link delle PECL c'e' la dll [/supersaibal]
    PDO se non sbaglio entrerà nella prossima release di PHP5, però credo che fino a quando PHP5 non includerà sqlite 3.0, il diver sqlite per PDO non potrà funzionare
    per favore NIENTE PVT TECNICI da sconosciuti

  8. #8
    [supersaibal]Originariamente inviato da Fabio Heller
    Ah ok, ma io mi riferivo agli errori di tipo "personale" (quelli che vuoi creare tu), che anche con il trucco che hai utilizzato caso richiedono un trigger_error.
    [/supersaibal]
    ri non necessariamente
    codice:
    <?php // 5
    class ErrorCapture {
    	private $__handler;
    	final function __construct() {
    		$this->__handler = &set_error_handler(
    			array(
    				&$this,
    				'throwException'
    			)
    		);
    	}
    	final function __destruct() {
    		restore_error_handler();
    	}
    	final static public function throwException(
    		$errno,
    		$errstr,
    		$errfile = '',
    		$errline = 0
    	) {
    		throw new Exception( $errstr );
    	}
    }
    $EC = &new ErrorCapture;
    
    try {
    	ErrorCapture::throwException( null, 'Errore gestito a mano' );
    }
    catch( Exception $e ) {
    	echo 'Error
    ';
    	echo $e->getMessage();
    	unset( $EC );
    }
    ?>

    [supersaibal]Originariamente inviato da Fabio Heller
    Inoltre in quel modo puoi solo lanciare ecceioni generiche, se vuoi creare un eccezione specifica per mysql, una per ftp e una per...sei costretto a lanciare un nuovo handler, es. errorCapture2
    [/supersaibal]
    in questo esempio usi un metodo statico, quindi non duplichi la classe , intendevi questo ? :master:


    [supersaibal]Originariamente inviato da Fabio Heller
    PDO se non sbaglio entrerà nella prossima release di PHP5, però credo che fino a quando PHP5 non includerà sqlite 3.0, il diver sqlite per PDO non potrà funzionare [/supersaibal]
    faccio delle prove e ti faccio sapere






    [EDITATO]


    codice:
    try {
    	$sqlite3 = new PDO( 'sqlite:testSqlite3.db' );
    }
    catch( PDOException $e ) {
    	echo 'Connection failed: ' . $e->getMessage();
    }
    Formaldehyde a new Ajax PHP Zero Config Error Debugger

    WebReflection @WebReflection

  9. #9
    [supersaibal]Originariamente inviato da andr3a
    ri non necessariamente
    Andrea, quello che voglio dire è che, se vuoi generare un errore personale (un errore che non è un errore di PHP ma è un errore per te) devi in ogni caso lanciarlo (con trigger_error o attraverso un throw.
    Ed è esattamente lo stesso fastidio di usare $this->dispatchEvent

    in questo esempio usi un metodo statico, quindi non duplichi la classe , intendevi questo ? :master:
    Volevo dire che con
    $this->dispatchEvent('onTipoErrore', $id, $messaggio) ;

    posso dire di quale tipo è l'errore (attraverso $id o 'onTipoErrore'), cosa non possibile con trigger_error o lanciando un eccezione generica. Ma solo lanciando un eccezione specificadel tipo

    throw new MioOggettoEccezione( $errstr );

    faccio delle prove e ti faccio sapere
    Non ho capito, quindi attraverso PDO, PHP5 supporta già SQLite 3?

    Da quanto ho letto PDO sarà stabile e incluso di default (senza PECL) in PHP 5.1 , quindi stanno facendo grossi passi avanti davvero: una sola interfaccia per più database come in PERL
    per favore NIENTE PVT TECNICI da sconosciuti

  10. #10
    io direi giusto per complicarsi la vita...

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.