• User

    [RISOLTO] PDO Singleton e type hinting

    Salve ho un curioso problema...in pratica non mi sta funzionando più il type hinting seppur credo di implementarlo in modo corretto.

    Il problema.
    Sto sviluppando un portale che necessita di accedere al database da varie classi che, per ovvie ragioni, non possono tutte essere estensioni di una sola unica classe Factory. A tal proposito ho sviluppato un semplice Singleton di prova per PDO come da scheletro proposto di seguito

    [php]
    <?php

    class PDOFactory
    {

          /** Propietà private per la connessione al database */
    
          static private $_bPDOSingletonInstance;
    
           static private function getInstance()
          {
    
                     /** Codice che verifica se self::$_bPDOSingletonInstance è settata e se non lo è crea la nuova istanza */
    
          }
    

    }
    ?>
    [/php]

    Tale singleton lo invoco in questo modo (non uso qua un blocco try catch perchè l'ho già dentro al metodo getInstance e mi richiama, in caso di errore, un metodo statico che impagina il messaggio)

    [php]
    <?php

    require_once 'class.PDOFactory.php';

    $objPDO = PDOFactory::getInstance();

    [/php]

    Fino qua tutto bene ma se voglio, ad esempio, verificare che l'istanza esiste e creo una classe di prova come la seguente

    [php]
    <?php

    class ProvaIstanza
    {

           private $objPDO;
    
           public function verifica(PDO $objPDO)
           {
    
                   if ( self::$ObjPDO)
                   {
    
                           echo "Istanza corerttamente passata";
    
                    } else {
    
                           echo "Non c'è nessuna istanza";
    
                    }
    
          }
    

    }
    ?>
    [/php]

    e modifico il codice precedente in questo modo

    [php]
    <?php
    require_once 'class.PDOFactory.php';
    require_once 'class.ProvaIstanza.php';
    $objPDO = PDOFactory::getInstance();
    $objProvaIstanza = new ProvaIstanza($objPDO)
    $objProvaIstanza->verifica();
    [/php]

    stampa correttamente il messaggio "Istanza correttamente passata" ma ci agginge anche il seguente errore

    
    **Catchable fatal error**:  Argument 1 passed to ProvaIstanza::verifica() must be an instance of PDO, none given, called in (nome del file e riga).
    
    

    Qualche idea si come risolvere il problema ?

    Grazie


  • User

    Come non detto: risolto. Se il metodo singleton è statico pure i metodi che implementano il type hinting devono esserlo.

    Bastano queste due modifiche e il tutto funziona

    [php]
    <?php

    class ProvaIstanza
    {

           private $objPDO;
    
           static public function verifica(PDO $objPDO)
           {
    
                   if ( self::$ObjPDO)
                   {
    
                           echo "Istanza corerttamente passata";
    
                    } else {
    
                           echo "Non c'è nessuna istanza";
    
                    }
    
          }
    

    }
    ?>
    [/php]

    [php]
    <?php
    require_once 'class.PDOFactory.php';
    require_once 'class.ProvaIstanza.php';
    $objPDO = PDOFactory::getInstance();
    ProvaIstanza::verifica($objPDO)
    [/php]


    Se a qualcuno serve qua c'è il codice completo per la verifica

    index.php
    [php]
    <?php

    require_once 'Configuration.php';
    require_once 'class.PDOFactory.php';
    require_once 'class.StampaArticoli.php';

    $objPDO = PDOFactory::getInstance();
    $objPDO->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    StampaArticoli::anteprima($objPDO);

    ?>
    [/php]

    namespace.php
    [php]
    <?php
    namespace PDOFactory
    {

    const PDONAME         = 'mysql';
    const PDOHOST         = 'localhost';
    const PDOPORT        = 3306;
    const PDOCHARSET    = 'utf8';
    const PDOUSERNAME    = 'tuoUtente';
    const PDOPASSWORD    = 'tuaPassword';
    const PDODBNAME        = 'tuoDatabase';
    const PDOOPTIONS    = null;
    

    }

    ?>
    [/php]
    class.PDOFactory.php
    [php]
    <?php

    class PDOFactory
    {

    static private $_sPDOName         = PDOFactory\PDONAME;
    static private $_sPDOHost        = PDOFactory\PDOHOST;
    static private $_iPDOPort        = PDOFactory\PDOPORT;
    static private $_sPDOCharset    = PDOFactory\PDOCHARSET;
    static private $_sPDOUsername    = PDOFactory\PDOUSERNAME;
    static private $_sPDOPassword    = PDOFactory\PDOPASSWORD;
    static private $_sPDODbName        = PDOFactory\PDODBNAME;
    
    static private $_bPDOSingletonInstance;
    
    public function __construct()
    {
    
    }
    
    public function __clone()
    {
    
    }
    
    static public function getInstance()
    {
    
        if ( !self::$_bPDOSingletonInstance )
        {
        
            try
            {
            
                self::$_bPDOSingletonInstance = new PDO (
                                                            self::$_sPDOName 
                                                            . ':host=' . self::$_sPDOHost 
                                                            . ';dbname=' . self::$_sPDODbName
                                                            . ';charset=' . self::$_sPDOCharset
                                                            . ';port=' . self::$_iPDOPort,
                                                            self::$_sPDOUsername,
                                                            self::$_sPDOPassword
                                                        
                                                        );
                                                    
            } catch (PDOException $e) {
                
                die ('PDOError: ' . $e->getMessage());
                
            }
            
        }
        return self::$_bPDOSingletonInstance;
        
    }
    

    }

    ?>
    [/php]

    mentre la classe StampaArticoli è una semplice classe di prova con un solo metodo giusto per verificare il funzionamento del tutto; non è detto che sia la soluzione ottimale per tutti ma serve a verificare il funzionamento

    [php]
    <?php

    class StampaArticoli
    {

    private $objPDO;

    static public function anteprima (PDO $objPDO)
    {
    
        try
        {
        
            foreach($objPDO->query('SELECT * FROM articoli') as $row)
            {
            
                echo $row['testoArticolo'] . '<br />';
        
            }
            
        } catch (PDOException $e) {
        
            die ('Error: ' . $e->getMessage());
            
        }
        
    }
    

    }
    ?>
    [/php]

    a tutta sta pappardella stampa correttamente:

    
    Questo è il primo articolo
    Questo è il secondo articolo
    Questo è il terzo articolo
    
    

    Spero sia utile a qualcuno

    Ciauz