Domanda

Ho costruito questa classe per lavorare con DOP, per rendere la query SQL "facile" e meno di cui preoccuparsi.

Qui sono i miei pensieri

  • Dovrebbe essere più come classe DB si estende DOP?
  • È il metodo query troppo grande?Dovrebbe essere suddivisi in metodi privati che sono chiamati..questo è ciò che è noto come accoppiamento?
  • È il mio modo per la rilevazione di una query di selezione troppo brutta per il proprio bene?
  • Quali altri problemi sono evidenti?Come io sono il tipo di apprendimento-come-mi-go, sono sicuro che avrei potuto avere di fronte un sacco di potenziali problemi.

Grazie

`

 class Db
 {
    private static $_instance = NULL;


    private function __construct() {

        // can not call me
    }

    private function __clone() {

        // no!
    }

    public static function getInstance() {

        if (!self::$_instance)
        {

            try {

                self::$_instance = new PDO('mysql:host=' . CONFIG_MYSQL_SERVER . ';dbname=' . CONFIG_MYSQL_DATABASE, CONFIG_MYSQL_USERNAME, CONFIG_MYSQL_PASSWORD);;
                self::$_instance-> setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

            } catch(PDOException $e) {

                trigger_error($e->getMessage());

            }

        }

        return self::$_instance;


    }



    public static function query($query /*string*/, $bindings = NULL)
    {

        $queryPortion = substr($query,0, 6);

        try {

            if ($bindings) {

                    $prepared = self::getInstance()->prepare($query);

                    foreach($bindings as $binding=>$data) { // defaults to string

                        if (!is_array($data)) {
                            $prepared->bindParam($binding, $data); 

                        } else {

                            switch(count($data)) {

                                case 1:
                                    $prepared->bindParam($binding, $data['value']);
                                    break;                          

                                case 2:
                                    $prepared->bindParam($binding, $data['value'], $data['dataType']);
                                    break;

                                case 3:
                                    $prepared->bindParam($binding, $data['value'], $data['dataType'], (int)$data['length']);
                                    break;                          

                                default:
                                    trigger_error('An error has occured with the prepared statement bindings.');
                                    return false;
                                    break;
                            }
                        }

                    }

                    $prepared->execute();

                    return $prepared->fetchAll(PDO::FETCH_ASSOC);


            } else if (String::match($queryPortion, 'select')) { // if this is a select query

                $rows = self::getInstance()->query($query);

                return $rows->fetchAll(PDO::FETCH_ASSOC);

            } else {

                return self::getInstance()->exec($query);

            }


        } 
        catch(PDOException $e)
        {
            trigger_error($e->getMessage());
        }


    }

    public static function getLastInsertId()
    {
        try {
            self::getInstance()->lastInsertId();
          }
        catch(PDOException $e)
        {
            trigger_error($e->getMessage());
        }

    }

    public static function disconnect()
    {
        // kill PDO object
        self::$_instance = NULL;

    }
 }
È stato utile?

Soluzione

Non è male e come è stato detto, potrebbe essere di aiuto per le piccole applicazioni anche se è per lo più molto sottile astrazione su un altro astrazione.Non portare un sacco di altre funzionalità.

Qualcosa che si potrebbe desiderare di prendere in considerazione, tra le altre cose:

  • Questo è PHP5 codice, utilizzare eccezioni invece di trigger_error e set_exception_handler se necessario, fino a che le eccezioni sono più diffuse, ma è sicuramente più pulito e più a prova di futuro.
  • Si utilizza un singleton, non è una brutta cosa, necessariamente, ma in questo caso, per esempio, un inconveniente sarà che sarete solo in grado di gestire una connessione a un database.
  • Non so se si fanno uso di stored procedure, ma anche di una stored procedure potrebbe restituire un set di risultati attraverso il query() metodo di troppo.
  • Si dispone di due punti e virgola (;;) alla fine del new PDO linea.

Detto questo, non credo che il tuo metodo di query è troppo grande e non c'è molto che potrebbe essere richiamato da altre parti c'è al momento.Anche se appena vedi due o tre righe che potrebbe essere chiamato da un'altra funzione, dividere.Questo è un buon modo per LAVAGGIO.

Altri suggerimenti

Sì e No.

È un buon codice per un semplice sporca e veloce applicazione.

Il problema nasce quando si utilizza questo in un più complesso strutturato di applicazione.Dove l'errore di gestione variano a seconda che sql in esecuzione.

Anche eventuali gravi errori verranno visualizzati come "problema in linea di 999" tipo di errori dove 999 è nel super duper routine e si avrà difficoltà a ritornare alle origini per una particolare richiesta sql.

Dopo aver detto che faccio questo genere di cose a me stesso per tutto il tempo su progetti di piccole dimensioni.

Ecco quello che ho usato (basta sostituire i riferimenti al Zzz_Config con $GLOBALS['db_conf'] o qualcosa del genere):

/**
 * Extended PDO with databse connection (instance) storage by name.
 */
class Zzz_Db extends PDO
{
    /**
     * Named connection instances.
     *
     * @var array
     */
    static private $_instances;

    /**
     * Retrieves (or instantiates) a connection by name.
     *
     * @param  string $name  Connection name (config item key).
     * @return Zzz_Db        Named connection.
     */
    static public function getInstance($name = null)
    {
        $name = $name === null ? 'db' : "db.$name";
        if (!isset(self::$_instances[$name])) {
            if (!$config = Zzz_Config::get($name)) {
                throw new RuntimeException("No such database config item: $name");
            }
            if (!isset($config['dsn'])) {
                if (!isset($config['database'])) {
                    throw new RuntimeException('Invalid db config');
                }
                $config['dsn'] = sprintf('%s:host=%s;dbname=%s',
                    isset($config['adapter']) ? $config['adapter'] : 'mysql',
                    isset($config['host']) ? $config['host'] : 'localhost',
                    $config['database']);
            }

            $db = self::$_instances[$name] = new self(
                $config['dsn'],
                isset($config['username']) ? $config['username'] : null,
                isset($config['password']) ? $config['password'] : null);
            $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
            //$db->setAttribute(PDO::ATTR_STATEMENT_CLASS, 'Zzz_Db_Statement');

            if ($db->getAttribute(PDO::ATTR_DRIVER_NAME) == 'mysql') {
                $db->setAttribute(PDO::ATTR_EMULATE_PREPARES, true);
                $db->exec('SET CHARACTER SET utf8');
            }
        }

        return self::$_instances[$name];
    }
}

L'utilizzo sarebbe:

$db = Zzz_Db::getInstance(); // or Zzz_Db::getInstance('some_named_db')
$stmt = $db->prepare('SELECT ...

L'obiettivo è di mantenere il db di configurazione in un *.file ini (modificabile da un non-programmatore).

Sono andato l'altro modo e di fatto una classe che estende DOP con un sacco di funzioni wrapper attorno prepare()/execute(), ed è molto più bello di funzioni (anche se è un po ' soggettivo...).

Un'altra cosa:è necessario impostare PDO::ATTR_EMULATE_PREPARES per false a meno che non si sta utilizzando un davvero vecchia versione di mysql (<=4.0).L'impostazione di default è true, che è un enorme mal di testa e fa le cose per rompere clandestinamente...sto indovinando che è il motivo che hai un grande involucro intorno bindParam() in primo luogo.

Per rispondere alla tua domanda, se è un buon codice o non, chiedete a voi stessi:
Qual è il valore aggiunto del mio codice, rispetto all'utilizzo di prodotti DOP direttamente?

Se si trova una buona risposta, andare per l'utilizzo del codice.Se non, vorrei bastone con DOP.

Anche provare a prendere in considerazione l' Zend Framework's DB classe che lavora in proprio e supporta DOP.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top