Acasă - Windows
Cum se lucrează cu PDO? Ghid complet. Instalarea extensiilor OCI8 și PDO_OCI pentru PHP5 Instalarea pdo

În prezent lucrez pentru o companie căreia îi place foarte mult să folosească Oracle DBMS în proiecte PHP, uneori versiunea 11g.

Majoritatea dezvoltatorilor acestei companii lucrează sub sistemul de operare Windows. În ultima lună, câțiva dintre ei au decis să se alăture Linux și au instalat Ubuntu. La câteva zile după instalarea sistemului de operare în sine, băieții s-au confruntat cu sarcina de a instala drivere PHP pentru lucrul cu Oracle DBMS - OCI8 și PDO_OCI bazat pe Oracle instant client 11.2, pe care nu le-au putut rezolva singuri.

Nu am găsit un manual detaliat, complet funcțional în limba rusă, conform căruia un nou venit la Linux ar putea efectua el însuși toate manipulările. Ca urmare, a trebuit să execut o serie de aceleași acțiuni de mai multe ori pe mașinile lor și să scriu un manual, pe care vi-l prezint.

Manualul este scris pentru utilizatorii Ubuntu Linux, dar cu unele modificări va fi potrivit pentru utilizatorii majorității sistemelor Linux.

Pregătirea pentru instalare

  1. Trebuie să puteți rula comenzi ca administrator;
  2. Trebuie să aveți instalat php5 cu următoarele pachete (comandă de instalare cu listă):
    sudo apt-get install php5 php5-dev php-pear php5-cli
    sudo pecl install pdo
  3. Trebuie să aveți instalată biblioteca libaio1:
    sudo apt-get install libaio1

Instalarea Oracle instant client

Descărcați instant client Oracle de pe site-ul oficial http://oracle.com pentru arhitectura procesorului și sistemul de operare.
Pentru Linux, clientul instant vine în două versiuni:
  • Pachetul RPM - Linux, CentOS, Fedora, Red Hat Enterprise Linux, Mandriva Linux, SUSE Linux etc. care are suport RPM;
  • Arhivă ZIP - pentru toți ceilalți.
Trebuie să descărcați 2 fișiere:
  • instantclient-basic - Oracle instant client în sine
  • instantclient-sdk - un set de biblioteci pentru dezvoltarea aplicațiilor pentru clientul instant Oracle
De asemenea, puteți descărca:
  • instantclient-sqlplus - SQL*Plus
Creați un director în care vor fi localizate fișierele client instant Oracle (directorul /opt, rezervat pentru pachete software suplimentare, este bun pentru asta):
sudo mkdir -p /opt/oracle/

Mutați fișierele descărcate în /opt/oracle și mergeți la folderul de destinație (să presupunem că ați descărcat „arhive zip” în folderul „descărcări” al utilizatorului):
sudo mv ~/downloads/instantclient-*.zip /opt/oracle/
cd /opt/oracle/

Dezarhivați toate arhivele descărcate:
sudo unzip instantclient-basic-*-*.zip
sudo unzip instantclient-sdk-*-*.zip
Dacă ați descărcat SQL*Plus:
sudo unzip instantclient-sqlplus-*-*.zip

Ca rezultat, în directorul /opt/oracle, directorul instantclient_11_2 a fost creat pentru Oracle instant client 11.2.0.2.0. Să redenumim acest director în instantclient (dacă aveți o altă versiune/director, schimbați comanda) și mergeți la el:
sudo mv instantclient_11_2 instantclient
cd instantclient

În continuare, trebuie să creați mai multe directoare și link-uri simbolice suplimentare pentru ca clientul să funcționeze normal (atenție la versiune și dacă aveți o altă versiune, schimbați comenzile):
sudo ln -s /opt/oracle/instantclient/libclntsh.so.* /opt/oracle/instantclient/libclntsh.so
sudo ln -s /opt/oracle/instantclient/libocci.so.* /opt/oracle/instantclient/libocci.so
sudo ln -s /opt/oracle/instantclient/ /opt/oracle/instantclient/lib

Sudo mkdir -p include/oracle/11.2/
cd include/oracle/11.2/
sudo ln -s ../../../sdk/include client
CD-

Sudo mkdir -p lib/oracle/11.2/client
cd lib/oracle/11.2/client
sudo ln -s ../../../ lib
CD-

Creăm un fișier de configurare care va indica directorul pentru căutarea bibliotecilor Oracle instant client și îl conectăm:
echo /opt/oracle/instantclient/ | sudo tee -a /etc/ld.so.conf.d/oracle.conf
sudo ldconfig

Deoarece nu există un director /usr/include/php în Ubuntu și clientul încă îl caută, să creăm o legătură simbolică către echivalentul său php5:
sudo ln -s /usr/include/php5 /usr/include/php

Instalați OCI8

După toate manipulările noastre, extensia oci8 se instalează minunat folosind comanda pecl:
sudo pecl install oci8
ni se cere să intrăm în calea către clientul instant Oracle, la care trebuie să răspundem:
instantclient,/opt/oracle/instantclient

Creați un fișier de conexiune cu extensie:
echo "; configurație pentru modulul php oci8" | sudo tee /etc/php5/conf.d/oci8.ini
echo extensie=oci8.so | sudo tee -a /etc/php5/conf.d/oci8.ini

Instalați PDO_OCI

Pentru a instala PDO_OCI, trebuie mai întâi să-l descarcăm din depozitul pear.
Să actualizăm lista de pachete de pere:
sudo pecl channel-update pear.php.net

Descărcați și plasați arhiva într-un director temporar:
sudo mkdir -p /tmp/pear/download/
cd /tmp/pear/download/
sudo pecl download pdo_oci

Să extragem conținutul arhivei și să mergem la ea:
sudo tar xvf PDO_OCI*.tgz
cd PDO_OCI*

Aici trebuie să ajustăm fișierul config.m4, deoarece nu conține date despre versiunea noastră de client instant Oracle, cele mai recente modificări datează din 2005. Lansați editorul preferat și faceți modificările marcate cu „+” (atenție la versiune și dacă aveți una diferită, schimbați rândurile):
sudo vim config.m4

Următoarea este o diferență a două fișiere:
***************
*** 7,12 ****
--- 7,14 ----
if test -s "$PDO_OCI_DIR/orainst/unix.rgs"; apoi
PDO_OCI_VERSION=`grep ""ocommon"" $PDO_OCI_DIR/orainst/unix.rgs | sed "s/*/:/g" | tăiat -d: -f 6 | tăiați -c 2-4`
test -z „$PDO_OCI_VERSION” && PDO_OCI_VERSION=7.3
+ elif test -f $PDO_OCI_DIR/lib/libclntsh.$SHLIB_SUFFIX_NAME.11.2; apoi
+ PDO_OCI_VERSION=11.2
elif test -f $PDO_OCI_DIR/lib/libclntsh.$SHLIB_SUFFIX_NAME.10.1; apoi
PDO_OCI_VERSION=10.1
elif test -f $PDO_OCI_DIR/lib/libclntsh.$SHLIB_SUFFIX_NAME.9.0; apoi
***************
*** 119,124 ****
--- 121,129 ----
10.2)
PHP_ADD_LIBRARY(clntsh, 1, PDO_OCI_SHARED_LIBADD)
;;
+ 11.2)
+ PHP_ADD_LIBRARY(clntsh, 1, PDO_OCI_SHARED_LIBADD)
+ ;;
*)
AC_MSG_ERROR(Versiune Oracle neacceptată! $PDO_OCI_VERSION)
;;
***************

Pregătim mediul pentru extensia php folosind comanda phpize (atenție la versiune, dacă aveți alta, schimbați-o):
sudo phpize

Configuram programul de instalare a pachetului si instalam pachetul (atentie la versiune, daca ai alta, schimba-l):
sudo ./configure --with-pdo-oci=instantclient,/opt/oracle/instantclient/,11.2
sudo make
sudo make install

Creăm un fișier de conexiune pentru acesta:
echo "; configurație pentru modulul php PDO_OCI" | sudo tee /etc/php5/conf.d/pdo_oci.ini
echo extension=pdo_oci.so | sudo tee -a /etc/php5/conf.d/pdo_oci.ini

Să rezumam

Reporniți apache și verificați dacă există extensii instalate:
sudo /etc/init.d/apache2 reporniți
php -m

Concluzie

Manualul se bazează pe această postare, care a fost ușor revizuită - erorile au fost corectate și s-au făcut completări.

Sper că articolul va fi util nu numai colegilor mei de muncă.


3 iunie 2018 Andrei Cernîșov Tutorial de traducere 1736 0

PDO este un acronim pentru PHP Data Objects: este o extensie PHP pentru lucrul cu baze de date folosind obiecte. Unul dintre avantajele sale constă în faptul că nu este direct legat de o anumită bază de date: interfața sa vă permite să accesați mai multe medii diferite, printre care: MySQL, SQLite, PostgreSQL, Microsoft SQL Server.

Acest ghid își propune să ofere o privire de ansamblu completă a PDO și să ghideze cititorul pas cu pas, de la crearea și conectarea la o bază de date, până la alegerea celor mai potrivite metode de recuperare, demonstrând cum să creați interogări pregătite și descriind posibilele moduri de eroare.

Crearea unei baze de date și a unui tabel de testare

În primul rând, vom crea o bază de date:

CREATE DATABASE solar_system; Acordați TOATE PRIVILEGIILE PE solar_system.* CĂTRE „testuser”@“localhost” IDENTIFICAT DE „testpassword”;

Am acordat utilizatorului testuser toate privilegiile din baza de date solar_system folosind testpassword pentru parolă. Acum să creăm un tabel și să-l completăm cu câteva informații:

USE solar_system; CREATE TABLE planete (id TINYINT(1) UNSIGNED NOT NULL AUTO_INCREMENT, PRIMARY KEY(id), nume VARCHAR(10) NOT NULL, culoare VARCHAR(10) NOT NULL); INSERT INTO planete(nume, culoare) VALUES("pământ", "albastru"), ("marte", "roșu"), ("jupiter", "ciudat");

Descrierea conexiunii DSN (Numele sursei de date).

Acum că avem o bază de date, trebuie să setăm DSN-ul. DSN înseamnă Data Source Name și este un set de informații necesare pentru a se conecta la o bază de date, DSN este sub forma unui șir. Sintaxa diferă în funcție de baza de date la care trebuie să vă conectați, dar deoarece folosim MySQL/MariaDB, trebuie să setăm următoarele:

  • Tipul de driver folosit pentru conectare;
  • Numele computerului gazdă pe care rulează baza de date;
  • Port de conectare (optional);
  • Numele bazei de date;
  • Codificare (opțional).

Formatul liniei în cazul nostru va fi astfel (o vom stoca în variabila $dsn):

$dsn = "mysql:host=localhost;port=3306;dbname=sistem_solar;charset=utf8";

În primul rând, setăm prefixul sau prefixul bazei de date. În acest caz, deoarece ne conectăm la o bază de date de tip MySQL/MariaDB, folosim mysql. Apoi am separat prefixul de restul liniei cu două puncte și fiecare secțiune ulterioară a fost separată de restul cu un punct și virgulă.

În următoarele două secțiuni am specificat numele de gazdă pe care rulează baza de date și portul folosit pentru conectare. Dacă nu este specificat niciun port, va fi utilizat portul implicit, în acest caz 3306. Imediat după numele bazei de date este charset .

Crearea unui obiect PDO

Acum că DSN-ul nostru este gata, vom începe să creăm obiectul PDO. Constructorul PDO folosește șirul DSN ca prim parametru, numele de utilizator al bazei de date ca al doilea parametru, parola ca al treilea și o matrice opțională de setări ca al patrulea.

$opțiuni = [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC ]; $pdo = PDO nou($dsn, „testuser”, „testpassword”, $opțiuni);

Setările pot fi setate și după ce obiectul este creat, folosind metoda SetAttribute():

$pdo->SetAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

Configurarea PDO pentru vizualizarea erorilor

Să aruncăm o privire la unele dintre opțiunile disponibile pentru PDO::ATTR_ERRMODE. Aceste opțiuni sunt extrem de importante deoarece determină modul în care se comportă PDO atunci când apar erori. Opțiuni posibile:

PDO::ERRMODE_SILENT

Opțiune implicită. PDO va arunca pur și simplu un cod de eroare și un mesaj de eroare. Acestea pot fi obținute folosind metodele errorCode() și errorInfo().

PDO::ERRMODE_EXCEPTION

După părerea mea, se recomandă utilizarea acestei opțiuni. Cu ajutorul lui, pe lângă emiterea unui cod de eroare și a informațiilor, PDO va arunca o PDOException, care va întrerupe execuția scriptului și este util și pentru tranzacțiile PDO (le vom analiza puțin mai târziu).

PDO::ERRMODE_WARNING

Cu această opțiune, PDO va afișa un cod de eroare și un mesaj la fel ca PDO::ERRMODE_SILENT , dar va afișa și un avertisment WARNING care nu întrerupe scriptul.

Setarea metodei implicite de eșantionare

O altă setare importantă este reglată folosind constanta PDO::DEFAULT_FETCH_MODE. Vă permite să configurați operația implicită a metodei fetch(), care va fi folosită pentru a obține rezultatele cererii. Iată care sunt cele mai frecvent utilizate opțiuni:

PDO::FETCH_BOTH

Când îl utilizați, rezultatele obținute vor fi indexate atât după numere întregi, cât și după numele coloanelor. Folosind-o într-o metodă de a obține un rând dintr-un tabel de planete ne va da următoarele rezultate:

$stmt = $pdo->query("SELECT * FROM planete"); $rezultate = $stmt->fetch(PDO::FETCH_BOTH);

Matrice ( => 1 => 1 => pământ => pământ => albastru => albastru)

Cu această constantă, rezultatele vor fi scrise într-o matrice asociativă în care fiecare cheie va fi un nume de coloană, iar fiecare valoare va reprezenta o anumită valoare în rând:

$stmt = $pdo->query("SELECT * FROM planete"); $rezultate = $stmt->fetch(PDO::FETCH_ASSOC);

Matrice ( => 1 => pământ => albastru)

PDO::FETCH_NUM

Folosind constanta PDO::FETCH_NUM obținem o matrice indexată 0:

Matrice ( => 1 => pământ => albastru)

PDO::FETCH_COLUMN

Această constantă este utilă pentru obținerea numai a valorilor dintr-o coloană, iar metoda va returna toate rezultatele într-o matrice simplă unidimensională. De exemplu, iată o cerere:

$stmt = $pdo->query("SELECT numele de pe planete");

Ca urmare:

Matrice ( => pământ => Marte => jupiter)

PDO::FETCH_KEY_PAIR

Această constantă este utilă atunci când trebuie să obțineți valori din două coloane. Metoda fetchAll() va returna rezultatele ca un tablou asociativ. În această matrice, datele din prima coloană vor fi specificate sub formă de chei, iar din a doua - ca valori:

$stmt = $pdo->query("SELECT numele de pe planete");

$stmt = $pdo->query("SELECT numele, culoarea FROM planete"); $rezultat = $stmt->fetchAll(PDO::FETCH_KEY_PAIR);

Matrice ( => albastru => roșu => ciudat)

PDO::FETCH_OBJECT

Când utilizați constanta PDO::FETCH_OBJECT, va fi creat un obiect anonim pentru fiecare rând preluat. Proprietățile sale (publice) vor fi numite la fel ca și coloanele, iar rezultatele interogării vor fi folosite ca valori. Utilizarea acestei metode pentru aceeași interogare ca mai sus va produce următorul rezultat:

$rezultate = $stmt->fetch(PDO::FETCH_OBJ);

obiect stdClass ( => pământ => albastru)

PDO::FETCH_CLASS

La fel ca constanta anterioară, aceasta va atribui valorile coloanei proprietăților obiectului, dar în acest caz trebuie să configuram o clasă existentă care va fi folosită pentru a crea obiectul. Pentru demonstrație, mai întâi vom crea o clasă:

Class Planet ( privat $nume; privat $culoare; funcția public setName($planet_name) ( $this->name = $planet_name; ) public function setColor($planet_culore) ( $this->color = $planet_culo; ) public function getName () ( returnează $this->nume; ) funcția publică getColor() ( returnează $this->culoare; ) )

$stmt = $pdo->query("SELECT numele, culoarea FROM planete"); $stmt->setFetchMode(PDO::FETCH_CLASS, "Planeta");

Specificăm constanta PDO::FETCH_CLASS ca prim argument al metodei setFetchMode() și numele clasei utilizate pentru a crea obiectul (în cazul nostru „Planet”) ca al doilea argument. Acum hai să rulăm codul:

$planeta = $stmt->fetch();

Acest lucru ar trebui să aibă ca rezultat un obiect Planet:

Var_dump($planeta);

Obiect Planet ( => pământ => albastru)

Observați cum valorile returnate din interogare au fost atribuite caracteristicilor corespunzătoare ale obiectului, chiar dacă sunt private.

Atribuirea de caracteristici după crearea unui obiect

Clasa „Planeta” nu a avut niciun constructor specific, deci nu au existat probleme cu atribuirea caracteristicilor; dar ce se întâmplă dacă clasa are un constructor în care caracteristicile sunt stabilite și modificate? Deoarece valorile sunt atribuite înainte de rularea constructorului, acestea vor fi suprascrise.

PDO ajută la furnizarea constantei FETCH_PROPS_LATE: atunci când este utilizat, valorile vor fi alocate după ce obiectul este creat. Exemplu:

Class Planet ( privat $nume; privat $culoare; funcția publică __construct($nume = lună, $culoare = gri) ( $this->nume = $nume; $this->culoare = $culoare; ) public function setName($ planet_name) ( $this->name = $planet_name; ) public function setColor($planet_color) ( $this->color = $planet_culo; ) public function getName() ( return $this->name; ) public function getColor() ( returnează $this->color; ) )

Am modificat clasa noastră Planet pentru a crea un constructor care va lua două argumente: nume nume și culoare. Aceste argumente au valorile de bază lună și gri, ceea ce înseamnă că dacă nu sunt date alte valori, acestea vor fi setate.

În acest caz, dacă nu folosim FETCH_PROPS_LATE, atunci indiferent de valorile obținute din baza de date, toate caracteristicile vor rămâne de bază, deoarece în timpul procesului de creare a obiectului, acestea vor fi suprascrise. Pentru a verifica acest lucru, să rulăm următoarea interogare:

$stmt = $pdo->query("SELECT numele, culoarea FROM solar_system WHERE nume = "pământ""); $stmt->setFetchMode(PDO::FETCH_CLASS, "Planeta"); $planeta = $stmt->fetch();

Acum să aruncăm o privire la obiectul Planet și să verificăm ce valori corespund caracteristicilor sale:

După cum era de așteptat, valorile preluate din baza de date au fost suprascrise cu valorile implicite. Acum, vom demonstra soluția problemelor folosind constanta FETCH_PROPS_LATE (și aceeași interogare ca cea anterioară):

$stmt->setFetchMode(PDO::FETCH_CLASS|PDO::FETCH_PROPS_LATE, „Planeta”); $planeta = $stmt->fetch(); var_dump($planeta);

obiect(Planeta)#4 (2) ( ["nume":"Planeta":privat]=> string(5) "pământ" ["culoare":"Planeta":privat]=> string(4) "albastru" )

În cele din urmă, s-a obținut rezultatul dorit. Dar ce se întâmplă dacă constructorul clasei nu are valori de bază și acestea trebuie specificate? Acest lucru este deja mai simplu: putem seta parametrii constructorului sub forma unui tablou, ca al treilea argument după numele clasei, folosind metoda setFetchMode(). De exemplu, să schimbăm constructorul:

Clasa Planeta ( privat $nume; privat $culoare; function public __construct($nume, $culoare) ( $this->nume = $nume; $this->culoare = $culoare; ) [...] )

Argumentele constructorului sunt acum necesare, așa că rulăm:

$stmt->setFetchMode(PDO::FETCH_CLASS|PDO::FETCH_PROPS_LATE, "Planeta", ["luna", "gri"]);

În acest caz, parametrii pe care îi specificăm servesc doar ca valori de bază necesare pentru ca obiectul să funcționeze fără erori: ei vor fi suprascriși de valorile din baza de date.

Preluarea mai multor obiecte

Desigur, este posibil să obțineți mai multe rezultate simultan sub formă de obiecte, fie folosind metoda fetch(), fie printr-o buclă:

While ($planet = $stmt->fetch()) ( // Ceva de-a face cu rezultatele )

Sau obțineți toate rezultatele deodată. În acest caz, așa cum am menționat mai devreme, atunci când utilizați metoda fetchAll(), va trebui să specificați modul de preluare nu înainte de a rula metoda, ci în momentul în care aceasta rulează:

$stmt->fetchAll(PDO::FETCH_CLASS|PDO_FETCH_PROPS_LATE, „Planeta”, [„lună”, „gri”]);

PDO::FETCH_INTO

Când folosește această constantă, PDO nu creează un obiect nou, actualizează în schimb caracteristicile unuia existent, ci numai dacă este public sau dacă în interiorul obiectului se folosește metoda __set().

Pregătit împotriva solicitărilor directe

PDO are două moduri de a lucra cu interogări: folosind cele directe și cea mai de încredere - cele pregătite.

Cereri directe

A doua metodă, în schimb, returnează numărul rândului care a fost modificat de interogare: îl folosim în cazurile care înlocuiesc rânduri, cum ar fi INSERT, DELETE sau UPDATE. Interogările directe trebuie utilizate numai în cazurile în care nu există variabile în interogări și nu există nicio îndoială cu privire la siguranța metodei.

Interogări pregătite

PDO acceptă, de asemenea, interogări pregătite în doi pași: acestea sunt utile atunci când interogările au variabile și sunt mai sigure în general, deoarece metoda prepare() va face toată munca necesară pentru noi. Să aruncăm o privire la modul în care sunt utilizate variabilele. Imaginați-vă că vrem să inserăm caracteristicile unei planete în tabelul Planetelor. Mai întâi, să pregătim o cerere:

$stmt = $pdo->prepare("INSERT INTO planete(nume, culoare) VALORI(?, ?)");

După cum am menționat mai devreme, folosim metoda prepare() care ia ca argument interogarea SQL, folosind valori temporare pentru variabile. Valorile temporare pot fi de două tipuri: poziționale și nominale.

Pozițional

Folosind? valori temporare poziționale, codul este mai concis, dar trebuie să specificăm datele care urmează să fie inserate în aceeași ordine ca numele coloanelor din tabloul furnizat ca argument pentru metoda execute():

$stmt->execute([$planeta->nume, $planeta->culoare]);

Personalizat

Folosind substituenți numiți, nu avem nevoie de o anumită comandă, dar obținem mai mult cod ca rezultat. Când rulăm metoda execute(), trebuie să furnizăm datele sub forma unui tablou asociativ, unde fiecare cheie este numele valorii temporare utilizate, iar valoarea asociată este ceea ce este transportat în interogare. De exemplu, cererea anterioară ar deveni:

$stmt = $pdo->prepare("INSERT INTO planete(nume, culoare) VALORI(:nume, :culoare)"); $stmt->execute(["nume" => $planeta->nume, "culoare" => $planeta->culoare]);

Metodele prepare() și execute() pot fi folosite ambele pentru interogări care modifică sau pur și simplu preiau informații din baza de date. În primul caz, folosim metodele fetch enumerate mai sus pentru a obține informații, iar în al doilea, folosim metoda rowCount().

metodele bindValue() și bindParam().

Metodele bindValue() și bindParam() pot fi, de asemenea, folosite pentru a furniza valorile care vor fi inserate în cerere. Prima leagă valoarea unei variabile date de o valoare pozițională sau temporară numită utilizată în pregătirea cererii. Luând ca exemplu cazul anterior, vom face:

$stmt->bindValue("nume", $planeta->nume, PDO::PARAM_STR);

Legăm valoarea lui $planet->name la o valoare temporară:name . Rețineți că folosind ambele metode bindValue() și bindParam() putem specifica și tipul variabilei ca al treilea argument folosind o constantă PDO adecvată, în acest caz PDO::PARAM_STR .

Folosind în schimb bindParam(), putem lega variabila la o valoare temporară adecvată utilizată în pregătirea interogării. Rețineți că, în acest caz, variabila este legată de referință și valoarea ei va fi schimbată în temporară numai când se rulează metoda execute(). Sintaxa este aceeași ca data trecută:

$stmt->bindParam(„nume”, $planeta->nume, PDO::PARAM_STR)

Am legat variabila, nu valoarea ei, $planet->name la:nume ! După cum s-a spus mai sus, înlocuirea se va întâmpla numai atunci când este rulată metoda execute(), astfel încât valoarea temporară va fi înlocuită cu valoarea variabilei în acel moment.

Tranzacții DOP

Tranzacțiile vă permit să mențineți coerența atunci când executați mai multe interogări. Toate interogările sunt executate în loturi și sunt aplicate bazei de date numai dacă toate reușesc. Tranzacțiile nu vor funcționa cu toate bazele de date și nu cu toate constructele SQL, deoarece unele dintre ele provoacă probleme.

Ca exemplu extrem și ciudat, imaginați-vă că utilizatorul trebuie să selecteze o listă de planete și de fiecare dată când face o nouă selecție, ar trebui să o ștergeți pe cea anterioară din baza de date înainte de a introduce una nouă. Ce se întâmplă dacă ștergerea are loc, dar inserarea nu? Vom obține un utilizator fără planete! Practic, tranzacțiile se aplică astfel:

$pdo->beginTransaction(); încercați ( $stmt1 = $pdo->exec("ȘTERGERE DE PE planete"); $stmt2 = $pdo->prepare("INSERT INTO planete(nume, culoare) VALORI (?, ?)"); foreach ($planete ca $planeta) ( $stmt2->execute([$planeta->getName(), $planeta->getColor()]); ) $pdo->commit() ) catch (PDOException $e) ( $pdo-> rollBack ();

În primul rând, metoda beginTransaction() de pe obiectul PDO dezactivează autocommit-ul cererii, apoi cererile sunt pornite în ordinea necesară. În acest moment, cu excepția cazului în care apare o excepție PDO, cererile sunt transmise automat prin metoda commit() în caz contrar, tranzacțiile sunt anulate prin metoda rollBack() și autocommit-ul este restaurat.

Astfel, cu cereri multiple, va exista întotdeauna consecvență. Acest lucru este destul de evident, dar tranzacțiile PDO pot fi utilizate numai de PDO::ATTR_ERRMODE setat la PDO::ERRMODE_EXCEPTION .

Mai întâi, să creăm baza de date pentru acest tutorial:

CREATE DATABASE solar_system; Acordați TOATE PRIVILEGIILE PE solar_system.* CĂTRE „testuser”@“localhost” IDENTIFICAT DE „testpassword”;

Un utilizator cu utilizatorul de conectare și parola testpassword i s-au acordat drepturi de acces complete la baza de date solar_system.

Acum să creăm un tabel și să-l umplem cu date, a căror acuratețe astronomică nu este implicită:

USE solar_system; CREATE TABLE planete (id TINYINT(1) UNSIGNED NOT NULL AUTO_INCREMENT, PRIMARY KEY(id), nume VARCHAR(10) NOT NULL, culoare VARCHAR(10) NOT NULL); INSERT INTO planete(nume, culoare) VALUES("pământ", "albastru"), ("marte", "roșu"), ("jupiter", "ciudat");

Descrierea conexiunii

Acum că baza de date a fost creată, să definim DSN () - informații pentru conectarea la baza de date, prezentate ca șir. Sintaxa descrierii diferă în funcție de SGBD utilizat. În exemplu lucrăm cu MySQL/MariaDB, așa că indicăm:

  • numele gazdă unde se află SGBD;
  • port (opțional dacă este utilizat portul standard 3306);
  • numele bazei de date;
  • codificare (opțional).

Linia DSN în acest caz arată astfel:

$dsn = "mysql:host=localhost;port=3306;dbname=sistem_solar;charset=utf8";

Prefixul bazei de date este specificat mai întâi. În exemplu - mysql. Prefixul este separat de restul liniei prin două puncte, iar fiecare parametru ulterior este separat printr-un punct și virgulă.

Crearea unui obiect PDO

Acum că șirul DSN este gata, să creăm un obiect PDO. Constructorul de intrare acceptă următorii parametri:

  1. șir DSN.
  2. Numele utilizatorului care are acces la baza de date.
  3. Parola acestui utilizator.
  4. O matrice cu parametri suplimentari (opțional).
$opțiuni = [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC ]; $pdo = PDO nou($dsn, „testuser”, „testpassword”, $opțiuni);

Parametrii suplimentari pot fi definiți și după ce obiectul este creat folosind metoda SetAttribute:

$pdo->SetAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

Definirea metodei implicite de eșantionare

PDO::DEFAULT_FETCH_MODE este un parametru important care determină metoda implicită de preluare. Metoda specificată este utilizată la obținerea rezultatului unei cereri.

PDO::FETCH_BOTH

Modul implicit. Rezultatul selecției este indexat atât de numere (începând de la 0) cât și de numele coloanelor:

$stmt = $pdo->query("SELECT * FROM planete"); $rezultate = $stmt->fetch(PDO::FETCH_BOTH);

După ce executăm o interogare cu acest mod împotriva tabelului de test al planetelor, obținem următorul rezultat:

Matrice ( => 1 => 1 => pământ => pământ => albastru => albastru)

PDO::FETCH_ASSOC

Rezultatul este stocat într-o matrice asociativă în care cheia este numele coloanei și valoarea este valoarea rândului corespunzătoare:

$stmt = $pdo->query("SELECT * FROM planete"); $rezultate = $stmt->fetch(PDO::FETCH_ASSOC);

Ca rezultat obținem:

Matrice ( => 1 => pământ => albastru)

PDO::FETCH_NUM

Când utilizați acest mod, rezultatul este prezentat ca o matrice indexată după numerele coloanei (începând de la 0):

Matrice ( => 1 => pământ => albastru)

PDO::FETCH_COLUMN

Această opțiune este utilă dacă trebuie să obțineți o listă de valori pentru un câmp sub forma unei matrice unidimensionale, a cărei numerotare începe de la 0. De exemplu:

$stmt = $pdo->query("SELECT numele de pe planete");

Ca rezultat obținem:

Matrice ( => pământ => Marte => jupiter)

PDO::FETCH_KEY_PAIR

Folosim această opțiune dacă trebuie să obținem o listă de valori a două câmpuri sub forma unui tablou asociativ. Cheile matricei sunt datele din prima coloană a selecției, valorile matricei sunt datele din a doua coloană. De exemplu:

$stmt = $pdo->query("SELECT numele, culoarea FROM planete"); $rezultat = $stmt->fetchAll(PDO::FETCH_KEY_PAIR);

Ca rezultat obținem:

Matrice ( => albastru => roșu => ciudat)

PDO::FETCH_OBJECT

Când utilizați PDO::FETCH_OBJECT, este creat un obiect anonim pentru fiecare rând preluat. Proprietățile sale publice sunt numele coloanelor eșantion, iar rezultatele interogării sunt folosite ca valori:

$stmt = $pdo->query("SELECT numele, culoarea FROM planete"); $rezultate = $stmt->fetch(PDO::FETCH_OBJ);

Ca rezultat obținem:

Obiect StdClass ( => pământ => albastru)

PDO::FETCH_CLASS

În acest caz, ca și în cel precedent, valorile coloanei devin proprietăți ale obiectului. Cu toate acestea, trebuie să specificați o clasă existentă care va fi folosită pentru a crea obiectul. Să ne uităm la asta cu un exemplu. Mai întâi, să creăm o clasă:

Class Planet ( privat $nume; privat $culoare; funcția public setName($planet_name) ( $this->name = $planet_name; ) public function setColor($planet_culore) ( $this->color = $planet_culo; ) public function getName () ( returnează $this->nume; ) funcția publică getColor() ( returnează $this->culoare; ) )

Vă rugăm să rețineți că clasa Planet are proprietăți private și nu are un constructor. Acum să executăm cererea.

Dacă utilizați metoda fetch cu PDO::FETCH_CLASS , trebuie să utilizați metoda setFetchMode înainte de a trimite o solicitare de preluare a datelor:

$stmt = $pdo->query("SELECT numele, culoarea FROM planete"); $stmt->setFetchMode(PDO::FETCH_CLASS, "Planeta");

Primul parametru pe care îl transmitem metodei setFetchMode este constanta PDO::FETCH_CLASS. Al doilea parametru este numele clasei care va fi folosită la crearea obiectului. Acum hai sa facem:

$planeta = $stmt->fetch(); var_dump($planeta);

Ca rezultat, obținem un obiect Planet:

Obiect Planet ( => pământ => albastru)

Valorile returnate de interogare sunt atribuite proprietăților corespunzătoare ale obiectului, chiar și celor private.

Definirea proprietăților după execuția constructorului

Clasa Planet nu are un constructor explicit, deci nu vor fi probleme de atribuire a proprietăților. Dacă o clasă are un constructor în care proprietatea a fost atribuită sau schimbată, acestea vor fi suprascrise.

Când utilizați constanta FETCH_PROPS_LATE, valorile proprietăților vor fi alocate după ce constructorul este executat:

Class Planet ( privat $nume; privat $culoare; funcția publică __construct($nume = lună, $culoare = gri) ( $this->nume = $nume; $this->culoare = $culoare; ) public function setName($ planet_name) ( $this->name = $planet_name; ) public function setColor($planet_color) ( $this->color = $planet_culo; ) public function getName() ( return $this->name; ) public function getColor() ( returnează $this->color; ) )

Am modificat clasa Planet adăugând un constructor care ia ca intrare două argumente: nume și culoare. Valorile implicite pentru aceste câmpuri sunt luna și, respectiv, gri.

Dacă nu utilizați FETCH_PROPS_LATE, proprietățile vor fi suprascrise cu valorile implicite atunci când obiectul este creat. Să verificăm. Mai întâi să rulăm interogarea:

$stmt = $pdo->query("SELECT numele, culoarea FROM solar_system WHERE nume = "pământ""); $stmt->setFetchMode(PDO::FETCH_CLASS, "Planeta"); $planeta = $stmt->fetch(); var_dump($planeta);

Ca rezultat obținem:

Object(Planeta)#2 (2) ( ["nume":"Planeta":privat]=> string(4) "luna" ["culoare":"Planeta":privat]=> string(4) "gri" )

După cum era de așteptat, valorile preluate din baza de date sunt suprascrise. Acum să ne uităm la rezolvarea problemei folosind FETCH_PROPS_LATE (o solicitare similară):

$stmt->setFetchMode(PDO::FETCH_CLASS|PDO::FETCH_PROPS_LATE, „Planeta”); $planeta = $stmt->fetch(); var_dump($planeta);

Drept urmare, obținem ceea ce avem nevoie:

Object(Planeta)#4 (2) ( ["nume":"Planeta":privat]=> string(5) "pământ" ["culoare":"Planeta":privat]=> string(4) "albastru" )

Dacă un constructor de clasă nu are valori implicite, dar acestea sunt necesare, parametrii constructorului sunt setați la apelarea metodei setFetchMode cu al treilea argument sub forma unui tablou. De exemplu:

Clasa Planeta ( privat $nume; privat $culoare; function public __construct($nume, $culoare) ( $this->nume = $nume; $this->culoare = $culoare; ) [...] )

Argumentele constructorului sunt necesare, deci să facem:

$stmt->setFetchMode(PDO::FETCH_CLASS|PDO::FETCH_PROPS_LATE, "Planeta", ["luna", "gri"]);

Parametrii primiți acționează și ca valori implicite care sunt necesare pentru inițializare. În viitor, acestea vor fi suprascrise cu valori din baza de date.

În acest caz, parametrii pe care îi specificăm servesc doar ca valori de bază necesare pentru ca obiectul să funcționeze fără erori: ei vor fi suprascriși de valorile din baza de date.

Mai multe rezultate sunt preluate ca obiecte folosind metoda fetch într-o buclă while:

While ($planet = $stmt->fetch()) ( // procesează rezultatele )

Sau prin eșantionarea tuturor rezultatelor simultan. În al doilea caz, se folosește metoda fetchAll, iar modul este specificat în momentul apelului:

$stmt->fetchAll(PDO::FETCH_CLASS|PDO_FETCH_PROPS_LATE, „Planeta”, [„lună”, „gri”]);

PDO::FETCH_INTO

Când această opțiune de selecție este selectată, PDO nu creează un obiect nou, ci mai degrabă actualizează proprietățile celui existent. Cu toate acestea, acest lucru este posibil numai pentru proprietăți publice sau când se utilizează metoda magic __set pe obiect.

Cereri pregătite și directe

Există două moduri de a executa interogări în PDO:

  • drept, care constă dintr-o treaptă;
  • pregătit, care constă din două etape.

Cereri directe

Există două metode pentru a efectua interogări directe:

  • interogarea este utilizată pentru instrucțiunile care nu fac modificări, cum ar fi SELECT. Returnează un obiect PDOStatemnt din care rezultatele interogării sunt preluate folosind metodele fetch sau fetchAll;
  • exec este folosit pentru instrucțiuni precum INSERT, DELETE sau UPDATE. Returnează numărul de rânduri procesate de cerere.

Operatorii direcți sunt utilizați numai dacă nu există variabile în interogare și sunteți sigur că interogarea este sigură și scăpată corect.

Interogări pregătite

PDO acceptă declarații pregătite, care sunt utile pentru protejarea unei aplicații de: metoda de pregătire realizează evadarea necesară.

Să ne uităm la un exemplu. Doriți să inserați proprietățile unui obiect Planet în tabelul Planete. Mai întâi, să pregătim cererea:

$stmt = $pdo->prepare("INSERT INTO planete(nume, culoare) VALORI(?, ?)");

Folosim metoda prepare, care ia ca argument o interogare SQL cu pseudo-variabile (substituenți). Pseudovariabilele pot fi de două tipuri: nenumite și numite.

Pseudovariabile fără nume

Pseudovariabilele nenumite (substituenți poziționali) sunt marcate cu ? . Interogarea rezultată este compactă, dar necesită ca valorile să fie înlocuite în aceeași ordine. Ele sunt transmise ca o matrice prin metoda execute:

$stmt->execute([$planeta->nume, $planeta->culoare]);

Pseudovariabile numite

Când folosiți substituenți numiți, ordinea în care valorile sunt transmise pentru înlocuire nu este importantă, dar codul în acest caz devine mai puțin compact. Datele sunt transmise metodei execute sub forma unui tablou asociativ, în care fiecare cheie corespunde numelui unei pseudo-variabile, iar valoarea matricei corespunde valorii care trebuie înlocuită în cerere. Să refacem exemplul anterior:

$stmt = $pdo->prepare("INSERT INTO planete(nume, culoare) VALORI(:nume, :culoare)"); $stmt->execute(["nume" => $planeta->nume, "culoare" => $planeta->culoare]);

Metodele de pregătire și execuție sunt utilizate atât la executarea cererilor de modificare, cât și la preluare.

Și informații despre numărul de rânduri procesate, dacă este necesar, vor fi furnizate prin metoda rowCount.

Controlul comportamentului erorii PDO

Parametrul de selectare a modului de eroare PDO::ATTR_ERRMODE este utilizat pentru a determina modul în care se comportă PDO în cazul unor erori. Există trei opțiuni disponibile: PDO::ERRMODE_SILENT , PDO::ERRMODE_EXCEPTION și PDO::ERRMODE_WARNING .

PDO::ERRMODE_SILENT

Opțiune implicită. PDO va înregistra pur și simplu informații despre eroare, pe care metodele errorCode și errorInfo vă vor ajuta să le obțineți.

PDO::ERRMODE_EXCEPTION

Aceasta este opțiunea preferată în care PDO aruncă o excepție (PDOException) în plus față de informațiile despre eroare. O excepție întrerupe execuția scriptului, ceea ce este util atunci când se utilizează tranzacții PDO. Un exemplu este dat în descrierea tranzacțiilor.

PDO::ERRMODE_WARNING

În acest caz, PDO înregistrează și informații despre eroare. Fluxul de script nu este întrerupt, dar sunt emise avertismente.

metodele bindValue și bindParam

De asemenea, puteți utiliza metodele bindValue și bindParam pentru a înlocui valorile într-o interogare. Prima asociază valoarea variabilei cu pseudovariabila care este utilizată pentru pregătirea cererii:

$stmt = $pdo->prepare("INSERT INTO planete(nume, culoare) VALORI(:nume, :culoare)"); $stmt->bindValue("nume", $planeta->nume, PDO::PARAM_STR);

A legat valoarea variabilei $planet->name de pseudovariabila:nume . Rețineți că atunci când utilizați metodele bindValue și bindParam, tipul variabilei este specificat ca al treilea argument folosind constantele PDO corespunzătoare. În exemplu - PDO::PARAM_STR .

Metoda bindParam leagă o variabilă la o pseudo variabilă. În acest caz, variabila este asociată cu o referință pseudo-variabilă, iar valoarea va fi inserată în interogare numai după apelarea metodei execute. Să ne uităm la un exemplu:

$stmt->bindParam("nume", $planeta->nume, PDO::PARAM_STR);

Tranzacții în DOP

Să ne imaginăm un exemplu neobișnuit. Utilizatorul trebuie să selecteze o listă de planete, iar de fiecare dată când cererea este executată, datele curente sunt șterse din baza de date, iar apoi sunt inserate altele noi. Dacă apare o eroare după ștergere, următorul utilizator va primi o listă goală. Pentru a evita acest lucru, folosim tranzacții:

$pdo->beginTransaction(); încercați ( $stmt1 = $pdo->exec("ȘTERGERE DE PE planete"); $stmt2 = $pdo->prepare("INSERT INTO planete(nume, culoare) VALORI (?, ?)"); foreach ($planete ca $planeta) ( $stmt2->execute([$planeta->getName(), $planeta->getColor()]); ) $pdo->commit() ) catch (PDOException $e) ( $pdo-> rollBack ();

Metoda beginTransaction dezactivează execuția automată a cererilor, iar în interiorul constructului try-catch, cererile sunt executate în ordinea dorită. Dacă nu se aruncă nicio excepție PDO, cererile vor fi finalizate folosind metoda commit. În caz contrar, acestea vor fi anulate folosind metoda rollback-ului, iar execuția automată a interogărilor va fi restabilită.

Acest lucru a creat consistență în execuția interogărilor. Evident, pentru ca acest lucru să se întâmple, PDO::ATTR_ERRMODE trebuie setat la PDO::ERRMODE_EXCEPTION .

Concluzie

Acum că lucrul cu PDO a fost descris, să notăm principalele sale avantaje:

  • cu PDO este ușor să transferați aplicația în alte SGBD;
  • Toate SGBD-urile populare sunt acceptate;
  • sistem de gestionare a erorilor încorporat;
  • diverse opțiuni pentru prezentarea rezultatelor eșantionului;
  • sunt acceptate interogări pregătite, care scurtează codul și îl fac rezistent la injecțiile SQL;
  • Sunt acceptate tranzacțiile, ceea ce ajută la menținerea integrității datelor și a coerenței interogărilor atunci când utilizatorii lucrează în paralel.

Alexander Nalivaiko, traducător

Cum folosește Yandex datele și învățarea automată pentru a personaliza serviciile -.












PDO are propria sa metodă inteligentă de conectare numită . În plus, în timpul conexiunii puteți seta o mulțime de opțiuni, dintre care unele sunt extrem de utile. O listă completă poate fi găsită, dar doar câteva sunt importante.

Exemplu de conexiune corectă:

$gazdă = "127.0.0.1" ;
$db = "test" ;
$utilizator = „rădăcină” ;
$trece = "" ;
$charset = "utf8" ;

$dsn = "mysql:host= $host ;dbname= $db ;charset= $charset " ;
$opt = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false,
];
$pdo = PDO nou ($dsn, $user, $pass, $opt);

Ce se întâmplă aici?

$dsn specifică tipul de bază de date cu care vom lucra (mysql), gazdă, numele bazei de date și setul de caractere.
- urmat de nume de utilizator și parolă
- după care este specificată o serie de opțiuni, despre care nu este scris în niciunul dintre manuale.

În ciuda faptului că această matrice este un lucru extrem de util, așa cum am menționat mai sus. Cel mai important lucru este că modul de eroare ar trebui setat numai sub formă de excepții.
- În primul rând, deoarece în toate celelalte moduri PDO nu raportează nimic inteligibil despre eroare,
- în al doilea rând, deoarece excepția conține întotdeauna o urmă de stivă de neînlocuit,
- în al treilea rând, excepțiile sunt extrem de convenabil de gestionat.

În plus, este foarte convenabil să setați FETCH_MODE în mod implicit, pentru a nu-l scrie în FIECARE solicitare, așa cum le place foarte mult hamsterilor diligenti.
Tot aici puteți seta modul pconnect, emularea expresiilor pregătite și multe alte cuvinte înfricoșătoare.

Ca rezultat, obținem variabila $pdo, cu care lucrăm pe parcursul întregului script.

Puteți folosi două metode pentru a executa interogări.
Dacă nu sunt transmise variabile la cerere, atunci puteți utiliza funcția query(). Acesta va executa cererea și va returna un obiect special - instrucțiunea PDO. Foarte aproximativ, o puteți compara cu resursa mysql, care a fost returnată de mysql_query(). Puteți obține date de la acest obiect fie în mod tradițional, prin while sau prin foreach(). De asemenea, puteți cere să returnați datele primite într-un format special, care este discutat mai jos.
$stmt = $pdo -> interogare ("SELECT numele de la utilizatori");
while ($row = $stmt -> fetch())
{
}

Dacă cel puțin o variabilă este transmisă cererii, atunci această solicitare trebuie executată numai prin expresii pregătite. Ce este? Aceasta este o interogare SQL obișnuită, în care este plasat un marker special în loc de o variabilă - un substituent. PDO acceptă substituenți poziționali (?), pentru care ordinea variabilelor trecute este importantă și substituenți denumiti (:nume), pentru care ordinea nu este importantă. Exemple:
$sql = ;
$sql = ;

Pentru a executa o astfel de interogare, trebuie mai întâi pregătită folosind funcția prepare(). De asemenea, returnează o declarație PDO, dar fără date încă. Pentru a le obține, trebuie să executați această solicitare, după ce ați trecut anterior variabile în ea. Îl poți transfera în două moduri:
Cel mai adesea, puteți executa pur și simplu metoda execute(), trecându-i o serie de variabile:
$stmt = $pdo -> pregătiți ( „SELECTează numele FROM utilizatorii WHERE email = ?”);
$stmt -> execute (array($email ));

$stmt = $pdo -> pregătiți ( „SELECTează numele FROM utilizatorii WHERE email = :email”);
$stmt -> execute (array("email" => $email ));
După cum puteți vedea, în cazul substituenților numiți, o matrice în care cheile trebuie să se potrivească cu numele substituenților trebuie să fie transmisă pentru a executa ().

Uneori, foarte rar, a doua metodă poate fi necesară, când variabilele sunt mai întâi legate la cerere pe rând, folosind bindValue() / bindParam(), și apoi doar executate. În acest caz, nu se trece nimic la execute(). Un exemplu poate fi găsit în manual.
Când utilizați această metodă, ar trebui să fie întotdeauna preferată bindValue()? deoarece comportamentul lui bindParam() nu este evident pentru începători și va duce la probleme.

Puteți utiliza apoi declarația PDO în aceleași moduri ca mai sus. De exemplu, prin foreach:
$stmt = $pdo -> pregătiți ( „SELECTează numele FROM utilizatorii WHERE email = ?”);
$stmt ->
foreach ($stmt ca $row )
{
echo $row [ „nume” ] . „\n” ;
}

IMPORTANT: Expresiile pregătite sunt motivul principal pentru a utiliza PDO deoarece acesta singura cale sigură executând interogări SQL care implică variabile.

De asemenea, prepare() / execute() poate fi folosit pentru a executa în mod repetat o interogare pregătită odată cu diferite seturi de date. În practică, acest lucru este necesar extrem de rar și nu aduce mult câștig de viteză. Dar în cazul în care trebuie să faceți mai multe interogări de același tip, puteți scrie astfel:

$date = matrice(
1 => 1000,
5 => 300,
9 => 200,
);

$stmt = $pdo -> pregătiți ( "UPDATE utilizatorii SET bonus = bonus + ? WHERE id = ?");
foreach ($date ca $id => $bonus)
{
$stmt -> execute ([ $bonus , $id ]);
}

Aici pregătim cererea o dată și apoi o executăm de mai multe ori.

Ne-am familiarizat deja cu metoda fetch(), care este folosită pentru a obține secvențial rânduri din baza de date. Această metodă este un analog al funcției mysq_fetch_array() și a altora similare, dar acționează diferit: în loc de multe funcții, aici este folosită una, dar comportamentul ei este specificat de parametrul transmis. Voi scrie despre acești parametri în detaliu mai târziu, dar ca o scurtă recomandare aș recomanda utilizarea fetch() în modul FETCH_LAZY:
$stmt = $pdo -> pregătiți ( „SELECTează numele FROM utilizatorii WHERE email = ?”);
$stmt -> execute([ $_GET [ "email" ]]);
while ($rând = $stmt -> preluare (PDO :: FETCH_LAZY ))
{
echo $rând [ 0 ] . „\n” ;
echo $row [ „nume” ] . „\n” ;
echo $row -> nume . „\n” ;
}

În acest mod, nu se irosește memorie suplimentară și, în plus, coloanele pot fi accesate în oricare dintre trei moduri - prin index, nume sau proprietate.

Declarația PDO are și o funcție de ajutor pentru obținerea valorii unei singure coloane. Este foarte convenabil dacă solicităm un singur câmp - în acest caz, cantitatea de scris este redusă semnificativ:
$stmt = $pdo -> pregătiți ( „SELECTează numele din tabelul WHERE id=?”);
$stmt -> execute (array($id ));
$nume = $stmt -> fetchColumn();

Dar cea mai interesantă funcție, cu cea mai mare funcționalitate, este fetchAll(). Acesta este ceea ce face din PDO o bibliotecă de nivel înalt pentru lucrul cu o bază de date, și nu doar un driver de nivel scăzut.

FetchAll() returnează o matrice care constă din toate rândurile pe care le-a returnat interogarea. Din care se pot trage două concluzii:
1. Această funcție nu trebuie utilizată atunci când interogarea returnează o mulțime de date. În acest caz, este mai bine să utilizați o buclă tradițională cu fetch()
2. Deoarece în aplicațiile PHP moderne datele nu sunt niciodată scoase imediat după primire, ci sunt transferate într-un șablon în acest scop, fetchAll() devine pur și simplu de neînlocuit, permițându-vă să evitați scrierea manuală a buclelor și, prin urmare, reducând cantitatea de cod.

Obținerea unui tablou simplu.
Apelată fără parametri, această funcție returnează o matrice obișnuită indexată care conține rânduri din baza de date, în formatul specificat în FETCH_MODE în mod implicit. Constantele PDO::FETCH_NUM, PDO::FETCH_ASSOC, PDO::FETCH_OBJ pot schimba formatul din mers.

Obținerea unei coloane.
Uneori trebuie să obțineți o matrice simplă unidimensională solicitând un singur câmp dintr-o grămadă de șiruri. Pentru a face acest lucru, utilizați modul PDO::FETCH_COLUMN
$date = $pdo -> interogare ("SELECT name FROM users" ) -> fetchAll (PDO :: FETCH_COLUMN );
matrice (
0 => „Ioan” ,
1 => „Mike” ,
2 => "Maria" ,
3 => „Kathy” ,
)

Se preiau perechi cheie-valoare.
De asemenea, un format popular atunci când este de dorit să obțineți aceeași coloană, dar indexată nu după numere, ci după unul dintre câmpuri. Constanta PDO::FETCH_KEY_PAIR este responsabilă pentru acest lucru.
$date = $pdo -> interogare ("SELECT id, name FROM users" ) -> fetchAll (PDO :: FETCH_KEY_PAIR );
matrice (
104 => "Ioan" ,
110 => "Mike" ,
120 => "Maria" ,
121 => "Kathy" ,
)

Obțineți toate rândurile indexate după un câmp.
De asemenea, este adesea necesar să obțineți toate rândurile din baza de date, dar și indexate nu după numere, ci printr-un câmp unic. Constanta PDO::FETCH_UNIQUE face acest lucru.
$date = $pdo -> interogare ("SELECT * FROM users") -> fetchAll (PDO :: FETCH_UNIQUE );
matrice (
104 => matrice (
"name" => "Ioan" ,
"mașină" => "Toyota" ,
),
110 => matrice (
"name" => "Mike" ,
"mașină" => "Ford" ,
),
120 => matrice (
"name" => "Maria" ,
"mașină" => "Mazda" ,
),
121 => matrice (
"name" => "Kathy" ,
"mașină" => "Mazda" ,
),
)

Trebuie reținut că trebuie să selectați mai întâi un câmp unic în coloană.

Există mai mult de o duzină și jumătate de moduri diferite de achiziție de date în PDO. Plus că le poți combina! Dar acesta este un subiect pentru un articol separat.

Când lucrați cu expresii pregătite, ar trebui să înțelegeți că un substituent poate înlocui doar un șir sau un număr. Nici un cuvânt cheie, nici un identificator, nici o parte dintr-un șir sau un set de șiruri nu pot fi înlocuite printr-un substituent. Prin urmare, pentru LIKE trebuie mai întâi să pregătiți întregul șir de căutare și apoi să îl înlocuiți în interogare:

$nume = "% $nume %" ;
$stm = $pdo -> pregătiți ( "SELECT * FROM tabelul WHERE nume LIKE?");
$stm -> execute (matrice($nume));
$date = $stm -> fetchAll();

Ei bine, ai înțeles ideea. Totul este rău și aici. PDO nu oferă deloc instrumente pentru lucrul cu identificatorii, iar aceștia trebuie formatați în mod demodat, manual (sau, totuși, priviți spre SafeMysql, în care acest lucru, la fel ca multe alte probleme, este rezolvat simplu și elegant).
Trebuie reținut că regulile de formatare a identificatorilor diferă pentru diferite baze de date.

În mysql, pentru a formata manual un identificator, trebuie să faceți două lucruri:
- închideți-l în backticks ("`").
- căutați aceste caractere în interiorul identificatorului prin dublare.

$câmp = "`" . str_replace ("`" , "``" , $_GET [ "câmp" ]). "`" ;
$sql = $câmp " ;

Cu toate acestea, există o avertizare aici. Formatarea singură poate să nu fie suficientă. Codul de mai sus ne protejează de injectarea clasică, dar în unele cazuri inamicul poate scrie ceva nedorit dacă înlocuim fără grija numele câmpurilor și tabelelor direct în interogare. De exemplu, în tabelul utilizatori există un câmp de administrare. Dacă numele câmpurilor primite nu sunt filtrate, atunci orice prost va scrie orice lucru urât în ​​acest câmp atunci când generează automat o solicitare de la un POST.

Prin urmare, este recomandabil să verificați valabilitatea numelor tabelelor și câmpurilor provenite de la utilizator, ca în exemplul de mai jos

Orice cod de încorporare care poate fi văzut în numeroase tutoriale aduce melancolie și dorința de a ucide apstenul. Construcții multikilometrice cu repetarea acelorași nume - în indexurile $_POST, în nume de variabile, în nume de câmpuri într-o cerere, în nume de substituenți într-o cerere, în nume de substituenți și nume de variabile la legare.
Privind acest cod, îmi doresc să ucid pe cineva, sau cel puțin să-l fac puțin mai scurt.

Acest lucru se poate face prin adoptarea unei convenții conform căreia numele câmpurilor din formular se potrivesc cu numele câmpurilor din tabel. Apoi, aceste nume pot fi listate o singură dată (pentru a proteja împotriva înlocuirii, care a fost menționat mai sus), și o mică funcție de ajutor poate fi utilizată pentru a asambla interogarea, care, datorită particularităților mysql, este potrivită atât pentru INSERT, cât și pentru ACTUALIZARE interogări:

funcția pdoSet ($permis și $valori, $sursă = matrice()) (
$set = "" ;
$valori = matrice();
if (! $sursa ) $sursa = & $_POST ;
foreach ($permis ca $câmp) (
if (isset($sursa [ $câmp])) (
$set .= "`" . str_replace ("`" , "``" , $câmp ). „`”. "=: $câmp , " ;
$valori [ $câmp ] = $sursă [ $câmp ];
}
}
return substr ($set, 0, - 2);
}

În consecință, codul de încorporare va fi

$allowed = array("nume" , "nume" , "e-mail" ); // câmpuri permise
$sql = "INSERT INTO users SET " . pdoSet ($permis, $valori);
$stm = $dbh -> pregăti ($sql );
$stm -> execute ($valori);

Și pentru actualizare - aceasta:

$allowed = array("nume", "nume" , "e-mail" , "parolă"); // câmpuri permise
$_POST[„parolă”] = MD5($_POST[„autentificare”]. $_POST[„parolă”]);
$sql = "UPDATE users SET " . pdoSet ($permis, $valori). „WHERE id = :id” ;
$stm = $dbh -> pregăti ($sql );
$values ​​​​["id" ] = $_POST ["id" ];
$stm -> execute ($valori);

Nu foarte impresionant, dar foarte eficient. Permiteți-mi să vă reamintesc, apropo, că dacă utilizați Class pentru a lucra sigur și convenabil cu MySQL, atunci totul se face în două rânduri.

DOP și cuvinte cheie
Este imposibil să veniți cu altceva decât filtrarea aici. Prin urmare, este o prostie să rulezi toți operatorii nespecificați direct în cerere prin lista albă:

$dirs = array("ASC" , "DESC" );
$key = array_search($_GET["dir"], $dirs));
$dir = $comenzi [ $cheie ];
$sql = „SELECT * FROM `table` ORDER BY$câmp $dir " ;



 


Citire:



Ce să faci dacă evoluezi offline

Ce să faci dacă evoluezi offline

În cele din urmă, ea a vizitat piața de jocuri pe computer, luminând-o cu lumina monștrilor extratereștri și a armelor high-tech. Desigur, un astfel de neobișnuit...

Testarea procesorului pentru supraîncălzire

Testarea procesorului pentru supraîncălzire

Trebuie să monitorizați în mod constant temperatura procesorului sau a plăcii video, deoarece dacă se supraîncălzi, computerul pur și simplu nu va porni. Pe aceasta...

Ce sunt serviciile publice Yesia

Ce sunt serviciile publice Yesia

Au dispărut vremurile în care primirea serviciilor de stat sau municipale nu era posibilă fără o vizită personală la executiv...

Poziția capetelor pe antenă

Poziția capetelor pe antenă

Articolul dezvăluie principalele metode de determinare a azimutului folosind o busolă magnetică și locurile de utilizare posibilă a acestuia. Utilizare...

imagine-alimentare RSS