mysqli o DOP - quali sono i pro e i contro? [chiuso]


342

Al nostro posto siamo divisi tra l'uso di mysqli e PDO per cose come dichiarazioni preparate e supporto per le transazioni. Alcuni progetti ne usano uno, altri l'altro. Esistono poche probabilità realistiche di trasferirci in un altro RDBMS.

Preferisco il DOP per il solo motivo che consente parametri nominati per istruzioni preparate, e per quanto ne so mysqli non lo fa.

Ci sono altri pro e contro nella scelta l'uno rispetto all'altro come standard mentre consolidiamo i nostri progetti per usare solo un approccio?


5
Questo articolo ti aiuterà a scegliere quale usare. Se consideri le prestazioni, questo potrebbe aiutarti a scegliere.
ravi404,

3
È divertente quante persone abbiano votato e recitato una domanda "non costruttiva". Il fatto è che l'intero thread è molto costruttivo - forse i moderatori dovrebbero tenerne conto nel giudicare se una domanda è costruttiva o no?
marlar

@marlar Sono così d'accordo con te! Questo è davvero il problema più grande su StackOverflow. Le domande / discussioni eccellenti vengono sempre chiuse.
Sliq,

Risposte:


243

Bene, potresti discutere con l'aspetto orientato agli oggetti, le dichiarazioni preparate, il fatto che diventi uno standard, ecc. Ma so che la maggior parte delle volte, convincere qualcuno a lavorare meglio con una caratteristica killer. Quindi eccolo:

Una cosa davvero bella con PDO è che puoi recuperare i dati, iniettandoli automaticamente in un oggetto. Se non vuoi usare un ORM (perché è solo uno script veloce) ma ti piace la mappatura degli oggetti, è DAVVERO bello:

class Student {

    public $id;
    public $first_name;
    public $last_name

    public function getFullName() {
        return $this->first_name.' '.$this->last_name
    }
}

try 
{
    $dbh = new PDO("mysql:host=$hostname;dbname=school", $username, $password)

    $stmt = $dbh->query("SELECT * FROM students");

    /* MAGIC HAPPENS HERE */

    $stmt->setFetchMode(PDO::FETCH_INTO, new Student);


    foreach($stmt as $student)
    {
        echo $student->getFullName().'<br />';
    } 

    $dbh = null;
}
catch(PDOException $e)
{
    echo $e->getMessage();
}

12
c'è una differenza tra quanto sopra e $mysqliResult->fetch_object("student");?
Andy Fleming,

2
@ e-satis no, io uso PHP. I campi pubblici violano l'incapsulamento, quindi AS A BEST PRACTICEè solo ... lol :) Google non utilizza i campi pubblici, ma solo gli accessori: google-styleguide.googlecode.com/svn/trunk/… .
OZ_

6
@ e-satis: scusatemi per il salto ma getter e setter sono necessari se volete controllare cosa succede quando le variabili vengono cambiate. Altrimenti, semplicemente non puoi garantire lo stato interno del tuo oggetto (questo è particolarmente un problema se hai un altro oggetto all'interno). Questo è completamente indipendente dalla lingua. @OZ_: calmati. Le critiche personali metteranno solo qualcun altro sulla difensiva.
James P.

2
@monadic: concordato. L'incapsulamento è ovviamente un argomento valido quando si tratta di componenti core, o oggetti complessi, ecc., Tuttavia come rappresentazioni di record che altrimenti sarebbero associati a lettura e scrittura. array, questo è accettabile. Inoltre, consente una più semplice verifica del tipo quando i record fluttuano nel sistema.
Dan Lugg,

15
@outis Spero di non essere in minoranza qui, ma non credo che le risposte debbano essere giudicate in base alla loro sicurezza nei confronti dei nuovi sviluppatori. Sembra duro, ma è vero. Lo scopo di una risposta su SO non è solo quello di fornire il codice copia e incolla, ma anche di fornire comprensione. Non è compito del risponditore garantire che ogni falla di sicurezza o difetto del modello sia coperto in un esempio, perché ammettiamolo, l'applicazione in cui viene copiato il codice è intrinsecamente diversa rispetto a qualsiasi altra applicazione che utilizza lo stesso codice.
Mattygabe,

57

Spostare un'applicazione da un database a un altro non è molto comune, ma prima o poi potresti trovarti a lavorare su un altro progetto usando un RDBMS diverso. Se sei a casa con la DOP, allora ci sarà almeno una cosa in meno da imparare a quel punto.

A parte questo, trovo l'API PDO un po 'più intuitiva e mi sento più veramente orientata agli oggetti. mysqli si sente come se fosse solo un'API procedurale che è stata oggettificata, se sai cosa intendo. In breve, trovo la DOP più facile da lavorare, ma ovviamente è soggettiva.


25

Ho iniziato a usare DOP perché il supporto delle dichiarazioni è migliore, secondo me. Sto usando un livello di accesso ai dati di tipo ActiveRecord ed è molto più semplice implementare istruzioni generate dinamicamente. L'associazione dei parametri di MySQLi deve essere eseguita in una singola chiamata di funzione / metodo, quindi se non si conosce fino al runtime quanti parametri si desidera associare, si è costretti a utilizzare call_user_func_array()(credo che sia il nome della funzione corretta) per le selezioni . E dimentica la semplice associazione dinamica dei risultati.

Soprattutto, mi piace la DOP perché è un livello di astrazione molto ragionevole. È facile da usare in sistemi completamente astratti in cui non si desidera scrivere SQL, ma semplifica anche l'uso di un sistema di query più ottimizzato e puro, oppure per combinare i due elementi.


2
Il binding dei risultati con query generate dinamiche è possibile, lo facciamo nelle nostre applicazioni. Tuttavia è un dolore enorme.
Pim Jager,

17

DOP è lo standard, è ciò che la maggior parte degli sviluppatori si aspetta di utilizzare. mysqli era essenzialmente una soluzione su misura per un problema particolare, ma ha tutti i problemi delle altre librerie specifiche del DBMS. DOP è dove tutto il duro lavoro e il pensiero intelligente andranno.


15

Ecco qualcos'altro da tenere a mente: per ora (PHP 5.2) la libreria PDO è difettosa . È pieno di strani bug. Ad esempio: prima di archiviare a PDOStatementin una variabile, la variabile dovrebbe essere unset()per evitare una tonnellata di bug. La maggior parte di questi sono stati corretti in PHP 5.3 e saranno rilasciati all'inizio del 2009 in PHP 5.3 che probabilmente avrà molti altri bug. Dovresti concentrarti sull'uso di PDO per PHP 6.1 se vuoi una versione stabile e sull'uso di PDO per PHP 5.3 se vuoi aiutare la comunità.


2
Penso che i guadagni offerti dalla DOP valgano la pena di comprendere e aggirare i bug. PHP stesso è pieno di bug molto aggravanti, alcuni dei quali non possiamo nemmeno aggirare in modo efficiente, e tuttavia offre molti vantaggi che ci inducono a usarlo invece di altre opzioni.
Brian Warshaw,

11
Uhm, strano, non ho mai riscontrato alcun bug con il DOP. E lo uso molto.
NikiC,

Mysqli ha anche dei bug. Tutto il software ha dei bug.
Bill Karwin,

10

Un'altra notevole (buona) differenza sul DOP è che il suo PDO::quote()metodo aggiunge automaticamente le virgolette allegate, mentre mysqli::real_escape_string()(e simili) no:

PDO :: quote () posiziona le virgolette attorno alla stringa di input (se necessario) e sfugge ai caratteri speciali all'interno della stringa di input, usando uno stile di quotazione appropriato per il driver sottostante.


8

PDO renderà molto più semplice il ridimensionamento se la tua app Web / del sito diventa realmente reale poiché puoi configurare quotidianamente connessioni Master e slave per distribuire il carico attraverso il database, inoltre PHP si sta dirigendo verso lo spostamento su PDO come standard.

Informazioni DOP

Ridimensionamento di un'applicazione Web


6

In termini di velocità di esecuzione, MySQLi vince, ma a meno che tu non abbia un buon wrapper che utilizza MySQLi, le sue funzioni che si occupano di istruzioni preparate sono terribili.

Ci sono ancora bug nei miei, ma se qualcuno lo vuole, eccolo qui .

Quindi in breve, se stai cercando un guadagno di velocità, allora MySQLi; se si desidera facilità d'uso, quindi DOP.


2
nel senso della velocità, potresti fornire dei benchmark?
Giulio F,

8
Jonathen Robson ha fatto un discreto confronto di velocità tra i due su jonathanrobson.me/2010/06/mysqli-vs-pdo-benchmarks . Riepilogo: inserts - quasi uguale, selects - mysqli è ~ 2,5% più veloce per le dichiarazioni non preparate / ~ 6,7% più veloce per le dichiarazioni preparate. Considerando quanto piccoli siano i limiti di prestazione, le caratteristiche e la flessibilità dell'uso PDOgeneralmente superano il risultato.
Adam

1
@Adam Grazie per il collegamento al mio blog!
jnrbsn,

@ daemonfire300 Questo è vero, non sono necessari parametri di riferimento. DOP avvolge la libreria mysqli. Probabilmente colpirei il fan se qualcuno potesse dimostrare che il DOP è più veloce di mysqli. MrGreen
Dyin il

@jnrbsn sei d'accordo con Adam su ciò che ha detto?
Basit

5

Personalmente uso la DOP, ma penso che sia principalmente una questione di preferenza.

PDO ha alcune funzioni che aiutano ancora una volta l'iniezione di SQL ( istruzioni preparate ), ma se stai attento con il tuo SQL puoi farlo anche con mysqli.

Passare a un altro database non è tanto un motivo per usare il DOP. Finché non si utilizzano "funzioni SQL speciali", è possibile passare da un DB a un altro. Tuttavia, non appena si utilizza ad esempio "SELEZIONA ... LIMIT 1" non è possibile accedere a MS-SQL dove si trova "SELEZIONA TOP 1 ...". Quindi questo è problematico comunque.


22
MySQLi ha preparato delle dichiarazioni.
Torre

5

Risposta modificata.

Dopo aver avuto qualche esperienza con entrambe queste API, direi che ci sono 2 funzionalità di livello di blocco che rendono mysqli inutilizzabile con istruzioni preparate native.
Sono già stati menzionati in 2 risposte eccellenti (eppure sottovalutate):

  1. Valori vincolanti al numero arbitrario di segnaposto
  2. Restituzione dei dati come un semplice array

(entrambi menzionati anche in questa risposta )

Per qualche motivo mysqli non è riuscito con entrambi.
Oggi ha ottenuto alcuni miglioramenti per il secondo ( get_result ), ma funziona solo su installazioni mysqlnd, il che significa che non puoi fare affidamento su questa funzione nei tuoi script.

Eppure non ha vincoli per valore fino ad oggi.

Quindi, c'è solo una scelta: DOP

Tutti gli altri motivi, come ad esempio

  • segnaposto nominati (questo zucchero di sintassi è molto sopravvalutato)
  • supporto di database diversi (nessuno l'ha mai effettivamente utilizzato)
  • recuperare in oggetto (solo zucchero di sintassi inutile)
  • differenza di velocità (nessuna)

non hanno alcuna importanza significativa.

Allo stesso tempo, entrambe queste API mancano di alcune funzionalità davvero importanti , come

  • segnaposto identificativo
  • segnaposto per i tipi di dati complessi per rendere meno impegnativa l'associazione dinamica
  • codice dell'applicazione più breve.

Quindi, per coprire le esigenze della vita reale , è necessario creare la propria libreria di astrazione, basata su una di queste API, implementando segnaposto analizzati manualmente. In questo caso preferirei mysqli, poiché ha un livello di astrazione minore.


Finalmente qualcuno che conosce e non nega i fatti della vita ...
Ihsan,

4

Nel mio script di benchmark , ogni metodo viene testato 10000 volte e viene stampata la differenza del tempo totale per ciascun metodo. Dovresti farlo sulla tua configurazione, sono sicuro che i risultati varieranno!

Questi sono i miei risultati:

  • " SELECT NULL" -> PGO()più veloce di ~ 0,35 secondi
  • " SHOW TABLE STATUS" -> mysqli()più veloce di ~ 2.3 secondi
  • " SELECT * FROM users" -> mysqli()più veloce di ~ 33 secondi

Nota: usando -> fetch_row () per mysqli, i nomi delle colonne non vengono aggiunti all'array, non ho trovato un modo per farlo in PGO. Ma anche se uso -> fetch_array (), mysqli è leggermente più lento ma comunque più veloce di PGO (tranne SELECT NULL).


17
Che cos'è la PGO? E più veloce di 33 secondi ?! Lo trovo molto difficile da credere ...
Alix Axel,

3

Una cosa che PDO afferma che MySQLi non mi piace davvero è la capacità del PDO di restituire un risultato come oggetto di un tipo di classe specificato (ad es $pdo->fetchObject('MyClass').). MySQLi fetch_object()restituirà solo un stdClassoggetto.


19
In realtà, puoi specificare una classe manualmente: "oggetto mysqli_result :: fetch_object ([string $ class_name [, array $ params]])". stdClass viene utilizzato solo se non si specifica nulla.
Andrioid,

-4

C'è una cosa da tenere a mente.

Mysqli non supporta la funzione fetch_assoc () che restituirebbe le colonne con le chiavi che rappresentano i nomi delle colonne. Naturalmente è possibile scrivere la propria funzione per farlo, non è nemmeno molto lungo, ma ho avuto davvero difficoltà a scriverla (per i non credenti: se ti sembra facile, provalo da solo e non t imbrogliare :))



2
È stato implementato più tempo fa, ma sì, ho controllato il manuale. Funziona con dichiarazioni preparate? Dubito ...
Mike,

2
In realtà, ha un supporto curiosamente parziale. È possibile recuperare le matrici nelle query regolari ma non nelle query parametrizzate: -!
Álvaro González,

1
Perché non cancellare una risposta che è ovviamente sbagliata?
Majid Fouladpour,

2
@MajidFouladpour - La risposta non è ovviamente sbagliata . Manca solo un po 'di contesto. Mysqli fa non supporta completamente associativa recupero matrice.
Álvaro González,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.