Visualizzazione dei risultati da 1 a 9 su 9

Discussione: OOP Strategy Pattern

  1. #1
    Utente di HTML.it L'avatar di Marcolino's
    Registrato dal
    May 2003
    residenza
    Udine
    Messaggi
    3,606

    OOP Strategy Pattern

    Ciao,
    sto cercando di far funzionare un pattern in modo che mi passi una variabile tramite un oggetto, ma a quanto pare questa non viene proprio vista, anche se non mi viene riportato un errore dal PHP.

    In pratica sto implementando un'interfaccia in grado di selezionare un modello di database ( in PDO ) tramite un'implementazione dello Strategy Pattern.
    Codice PHP:
    //    iStrategy
        
    interface iPDO_connect
        
    {
            public function 
    connect($user '');
        }
        
        
    //    Context
        
    class PDO_connect
        
    {
            private 
    $_strategy;
            
            public function 
    __construct(iPDO_connect $strategy)
            {
                
    $this->_strategy $strategy;
            }
            public function 
    connect()
            {
                if (!isset(
    $this->_strategy)) {
                    return 
    '';
                }
                
    $this->_strategy->connect($this);
            }
        }
        
        
    //    Concrete Strategy
        
    class PDO_MySQL implements iPDO_Connect
        
    {
            public function 
    connect($user '')
            {
                try
                {
                    if ( 
    $user '') {
                        throw new 
    Exception('L\'utente deve essere definito!');
                    }
                    
    $dsn 'mysql:host=localhost;dbname=x;charset=utf8';
                    
    $password 'la mia pass';
                    
    $connection = new PDO($dsn$user$password);
                    
    $connection->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODEPDO::FETCH_OBJ);
                    
    $connection->setAttribute(PDO::ATTR_ERRMODEPDO::ERRMODE_EXCEPTION);
                    
    $connection->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERYtrue);
                    
    $connection->setAttribute(PDO::ATTR_AUTOCOMMITtrue);
                    
    $connection->setAttribute(PDO::ATTR_EMULATE_PREPAREStrue);
                    
                    return 
    $connection;
                }
                catch (
    PDOException $e)
                {
                    
    $exception 'Exception! ' $e->getCode(). ': '$e->getMessage(). ' in '$e->getFile(). ' on line '$e->getLine(). "\n\n";;
                    echo 
    $exception;
                    exit;
                }
            }
        } 
    L'uso è banale e se voglio modificare il motore del database, ad esempio passare a sqlite o altro mi basta modificare la classe concrete strategy.
    La chiamata è pure banale
    Codice PHP:
    $context = new PDO_connect(new PDO_MySQL());
    $handle $context->connect('marco'); 
    Ma l'errore che riporta non lo è
    Exception! 1045: SQLSTATE[HY000] [1045] Access denied for user ''@'localhost' (using password: YES) in C:\WWW\Z\bin\PDO_connect.class.php on line 43
    La linea 43 non è altro che
    Codice PHP:
    $connection = new PDO($dsn$user$password); 
    Quindi?
    Quindi sembra che la variabile $user non passa.
    Inutile dire che se metto $user='marco' all'interno del metodo l'errore scompare a garantire il fatto che la procedura è giusta e l'errore non è nel PDO.
    Quindi?

  2. #2
    Utente di HTML.it
    Registrato dal
    Feb 2014
    residenza
    Voltati
    Messaggi
    913
    Tu stai richiamando questa funzione
    Codice PHP:
    public function connect()
        {
            if (!isset(
    $this->_strategy)) {
                return 
    '';
            }
            
    $this->_strategy->connect($this);
        } 
    che non ha parametri

    Inoltre qui passi un oggetto:
    Codice PHP:
    $this->_strategy->connect($this); 
    Ci vuole una stringa
    Ultima modifica di tampertools; 13-11-2014 a 18:34
    No

  3. #3
    Utente di HTML.it L'avatar di Marcolino's
    Registrato dal
    May 2003
    residenza
    Udine
    Messaggi
    3,606
    Sì è giusto ho commesso l'errore di passare l'intero oggetto mentre dovevo passare solo la stringa, be sai una cosa modificato non funziona.
    In realtà ho sbagliato l'approccio dato che era giusto così in quanto connect() in realtà non deve richiamare l'algoritmo di chiamata PDO ma registrare la funzione nel pattern.
    Ho dato un'ochiata a molti esempi in rete e nessuno è così complesso in realtà.
    Ad ogni buon conto ancora non sono riuscito a passare la stringa nonostante le modifiche

  4. #4
    Utente di HTML.it
    Registrato dal
    Feb 2014
    residenza
    Voltati
    Messaggi
    913
    Se fai
    $this->_strategy->connect("nome");
    che errore dà?
    No

  5. #5
    Utente di HTML.it L'avatar di boots
    Registrato dal
    Oct 2012
    Messaggi
    1,626
    Se questo è anche il tuo codice allora

    try
    {
    if (
    $user = '') {
    throw new
    Exception('L\'utente deve essere definito!');

    Stai sbagliando nella condizione dell'if! ci va ==, così stai assegnado ad $user null

  6. #6
    usare il _ per identificare le proprietà private non è proprio una buona cosa..
    Questa volta, più che un voto.. è favoreggiamento.

  7. #7
    Utente di HTML.it L'avatar di Marcolino's
    Registrato dal
    May 2003
    residenza
    Udine
    Messaggi
    3,606
    Bene, ci sono riuscito e per farlo mi sono riandato a rileggere questo libro Design Patterns - Elementi per il riuso di software ad oggetti può far sorridere ma non è così, in effetti ho notato da subito che il primo esempio postato da me non era esatto ma nicompleto; è il problema di chi studia solo su internet pensando di trovare tutte le risposte.
    All'esempio mancavano parti di base, in particolare mancava la possibilità di passare direttamente alla classe di Contesto Concreto una qualsivoglia variabile con qualche parametro.
    E infatti, pur se in Java ( ma basta tradurlo ) l'esempio originale del libro riportava un metodo della classe di contesto che mancava in quella realizzata da me e in parte copiata da un blog, cioè un metodo addParameter() che permettesse di settare un qualsivoglia parametro da passare all'altra classe.
    Quindi modificata la classe di Contesto ha funzionato alla grande.
    Ecco il risultato!
    Codice PHP:
    //    Context
        
    class PDO_connect
        
    {
            private 
    $_setAlgorithm null;
            private 
    $_elements null;
            
            
            public function 
    addUser$user )
            {
                
    $this->_elements $user;
            }
            
            public function 
    setAlgorithmiPDO_connect $strategy )
            {
                
    $this->_setAlgorithm $strategy;
            }
            
            public function 
    getAlgorithm()
            {
                if (!isset(
    $this->_setAlgorithm)) {
                    throw new 
    Exception('Classe non implementata!');
                    exit;
                }
                return 
    $this->_setAlgorithm->connect$this->_elements );
            }
        } 
    La chiamata invece...
    Codice PHP:
       //    Accesso al DB
        //    Client
        
    class Client
        
    {
            private 
    $_strategy;
            
            public function 
    getHandle$user )
            {
                
    $this->_strategy = new PDO_connect();
                
    $this->_strategy->addUser$user );
                
    $this->_strategy->setAlgorithm( new PDO_MYSQL );
                return 
    $this->_strategy->getAlgorithm();
            }
        }
        
        
    $obj = new Client();
        
    $handle $obj->getHandle'marco' );
        
    var_dump$handle ); 
    Che riporta la seguente risposta
    object(PDO)[4]
    Da notare due cose: la prima che ho aggiunto un metodo addUser che passa il parametro mancante e che bloccava di fatto il PDO. e quindi pure la sua variabile di passaggio!
    L'altra è che ho svincolato il type hinting dal costruttore per passarlo ad un altro metodo della classe.
    In effetti mi sono accorto che quando si "setta" la funzione da usarsi nel pattern strategy di fatto si blocca l'uso ulteriore della classe; almeno in PHP.
    In pratica ho copiato e tradotto pedisequamente in PHP l'esempio del libro aggiustandolo al mio problema.

    Al_katraz perché no? http://php.net/manual/it/language.variables.basics.php

    Ora sto pensando di vedere anche gli altri pattern just for fun.

  8. #8
    http://www.php-fig.org/psr/psr-2/

    standard 2 voce 4.2 properties

    Property names SHOULD NOT be prefixed with a single underscore to indicate protected or private visibility.
    è concesso ma non serve a niente
    Questa volta, più che un voto.. è favoreggiamento.

  9. #9
    Utente di HTML.it
    Registrato dal
    Feb 2014
    residenza
    Voltati
    Messaggi
    913
    Le variabili con l'undescore si usano in linguaggi, come il JavaScript, in cui non c'è altro modo per distinguere le proprietà "private" da quelle pubbliche
    No

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.