Inihanda ang mga query sa pdo. MySQL karagdagang mga tampok. Mga Mode ng Pagkuha ng Data

Karamihan sa mga database ay sumusuporta sa konsepto ng mga inihandang query. Ano ito? Maaari itong ilarawan bilang ilang uri ng pinagsama-samang template ng query ng SQL na tatakbo ng application at iko-configure gamit ang mga parameter ng input. Ang mga inihandang query ay may dalawang pangunahing bentahe:

  • Ang query ay dapat na ihanda nang isang beses at pagkatapos ay maaari itong patakbuhin nang maraming beses kung kinakailangan, parehong may pareho at may iba't ibang mga parameter. Kapag inihanda ang isang query, sinusuri ito ng DBMS, kino-compile at ino-optimize ang plano sa pagpapatupad nito. Sa kaso ng mga kumplikadong query, ang prosesong ito ay maaaring tumagal ng isang malaking halaga ng oras at kapansin-pansing pabagalin ang application kung ito ay kinakailangan upang isagawa ang query ng maraming beses na may iba't ibang mga parameter. Kapag gumagamit ng isang inihandang query, ang DBMS ay nagsusuri/nag-compile/nag-o-optimize ng isang query ng anumang kumplikado nang isang beses lamang, at ang application ay naglulunsad ng nakahandang template para sa pagpapatupad. Ang mga inihandang query sa ganitong paraan ay kumonsumo ng mas kaunting mapagkukunan at tumakbo nang mas mabilis.
  • Ang mga inihandang parameter ng query ay hindi kailangang i-escape gamit ang mga panipi; awtomatikong ginagawa ito ng driver. Kung ang application ay gumagamit ng eksklusibong inihandang mga query, ang developer ay makatitiyak na walang SQL injection na maaaring mangyari (gayunpaman, kung ang ibang bahagi ng query text ay nakasulat na may hindi nakatakas na mga character, ang mga SQL injection ay posible pa rin; dito nag-uusap kami tungkol sa mga parameter).

Kapaki-pakinabang din ang mga inihandang query na maaaring tularan ng PDO ang mga ito kung ang driver ng database ay walang ganitong functionality. Nangangahulugan ito na ang isang application ay maaaring gumamit ng parehong diskarte sa pag-access ng data anuman ang mga kakayahan ng DBMS.

Beispiel #1 Umuulit na pagsingit ng database gamit ang mga inihandang query

pangalan At halaga, na pinapalitan para sa kaukulang mga pseudo-variable:

$stmt = $dbh -> maghanda( "INSERT INTO REGISTRY (name, value) VALUES (:name, :value)");
$stmt -> bindParam(":name" , $name );
$stmt -> bindParam(":value" , ​​​​$value );

// magsingit ng isang linya
$name = "isa" ;
$value = 1 ;
$stmt -> execute();

$name = "dalawa" ;
$value = 2 ;
$stmt -> execute();
?>

Beispiel #2 Umuulit na pagsingit ng database gamit ang mga inihandang query

Sa halimbawang ito, ang isang INSERT query ay isinasagawa ng 2 beses na may iba't ibang halaga pangalan At halaga na pinapalitan ng mga pseudo-variable ? .

$stmt = $dbh -> maghanda( "INSERT INTO REGISTRY (name, value) VALUES (?, ?)");
$stmt -> bindParam(1 , $name );
$stmt -> bindParam(2 , $value );

// magsingit ng isang linya
$name = "isa" ;
$value = 1 ;
$stmt -> execute();

// ngayon ay isa pang string na may iba't ibang mga halaga
$name = "dalawa" ;
$value = 2 ;
$stmt -> execute();
?>

Beispiel #3 Pagkuha ng data gamit ang mga inihandang query

Sa halimbawang ito, ang isang seleksyon ay ginawa mula sa database sa pamamagitan ng susi na ipinasok ng user sa pamamagitan ng form. Ang input ng user ay awtomatikong sinipi kaya walang panganib ng SQL injection.

Kung sinusuportahan ng DBMS ang mga parameter ng output, maaaring gamitin ng application ang mga ito pati na rin ang mga parameter ng input. Karaniwang ginagamit ang mga parameter ng output upang kunin ang data mula sa mga nakaimbak na pamamaraan. Ang paggamit ng mga parameter ng output ay medyo mas kumplikado, dahil kailangang malaman ng developer ang maximum na laki ng mga nakuhang halaga sa yugto ng pagtatakda ng mga parameter na ito. Kung ang nakuhang halaga ay mas malaki kaysa sa inaasahan, magkakaroon ng error.

Beispiel #4 Pagtawag sa isang naka-imbak na pamamaraan na walang mga parameter

$stmt = $dbh -> prepare("TUMAWAG sp_returns_string(?)" );
$stmt -> bindParam(1 , $return_value , PDO :: PARAM_STR , 4000 );

// pagtawag sa isang naka-imbak na pamamaraan
$stmt -> execute();

print "ibinalik ang pamamaraan$return_value\n" ;
?>

Maaari mong itakda ang parameter sa parehong oras input at output; ang syntax ay kapareho ng para sa mga parameter ng output. Sa sumusunod na halimbawa, ang string na "hello" ay ipinapasa sa isang stored procedure, at pagkatapos ang string na iyon ay papalitan ng return value.

Halimbawa #5 Pagtawag ng nakaimbak na pamamaraan na may parameter ng input/output

$stmt = $dbh -> maghanda( "TUMAWAG sa sp_takes_string_returns_string(?)");
$value = "hello" ;!}
$stmt -> bindParam(1 , $value , PDO :: PARAM_STR | PDO :: PARAM_INPUT_OUTPUT , 4000 );

// pagtawag sa isang naka-imbak na pamamaraan
$stmt -> execute();

print "ibinalik ang pamamaraan$value\n" ;
?>

(array("% $_GET [pangalan ] %" ));
?>










Ang PDO ay may sariling contrived connection method na tinatawag na . Dagdag pa, sa panahon ng koneksyon, maaari kang magtakda ng isang masamang ulap ng mga pagpipilian, ang ilan sa mga ito ay lubhang kapaki-pakinabang. Ang isang kumpletong listahan ay matatagpuan, ngunit iilan lamang ang mahalaga.

Halimbawa ng tamang koneksyon:

$host = "127.0.0.1" ;
$db = "pagsubok" ;
$user = "ugat" ;
$pass = "" ;
$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 = bagong PDO ($dsn , $user , $pass , $opt );

Anong nangyayari dito?

Tinutukoy ng $dsn ang uri ng database na gagana sa (mysql), host, pangalan ng database, at charset.
- sinusundan ng username at password
- pagkatapos kung saan ang isang hanay ng mga pagpipilian ay tinukoy, na hindi binanggit sa alinman sa mga manual.

Sa kabila ng katotohanan na ang array na ito ay isang lubhang kapaki-pakinabang na bagay, tulad ng nabanggit sa itaas. Ang pinakamahalagang bagay ay ang paraan ng pag-isyu ng mga error ay dapat itakda lamang sa anyo ng mga pagbubukod.
- Una, dahil sa lahat ng iba pang mga mode ang PDO ay hindi nag-uulat ng anumang bagay na mauunawaan tungkol sa error,
- pangalawa, dahil ang isang pagbubukod ay palaging naglalaman ng hindi maaaring palitan na stack trace,
- pangatlo - ang mga pagbubukod ay lubos na maginhawang pangasiwaan.

Dagdag pa, ito ay napaka-maginhawa upang itakda ang FETCH_MODE bilang default upang hindi ito isulat sa BAWAT kahilingan, tulad ng masisipag na hamster na gustong gawin.
Dito rin maaari mong itakda ang pconnect mode, emulation ng mga inihandang expression at marami pang ibang nakakatakot na salita.

Bilang resulta, nakukuha namin ang variable na $pdo, kung saan kami ay nagtatrabaho nang higit pa sa buong script.

Maaari kang gumamit ng dalawang paraan upang magsagawa ng mga query.
Kung walang mga variable na ipinapasa sa query, maaari mong gamitin ang query() function. Ipapatupad nito ang kahilingan at ibabalik ang isang espesyal na bagay - pahayag ng PDO. Maaari itong maihambing sa mapagkukunan ng mysql na ibinalik ng mysql_query(). Maaari kang makakuha ng data mula sa bagay na ito pareho sa tradisyonal na paraan, sa pamamagitan ng habang, at sa pamamagitan ng foreach (). Maaari mo ring hilingin na ibalik ang natanggap na data sa isang espesyal na format, tulad ng inilarawan sa ibaba.
$stmt = $pdo -> query("PUMILI NG pangalan MULA SA mga user" );
habang ($row = $stmt -> fetch())
{
}

Kung hindi bababa sa isang variable ang ipinasa sa kahilingan, ang kahilingang ito ay dapat na maisakatuparan nang walang pagkabigo sa pamamagitan lamang mga inihandang ekspresyon. Ano ito? Ito ay isang regular na query sa SQL, kung saan inilalagay ang isang espesyal na marker sa halip na isang variable - isang placeholder. Sinusuportahan ng PDO ang mga positional na placeholder (?), kung saan ang pagkakasunud-sunod ng mga variable na ipinasa ay mahalaga, at pinangalanan ang mga placeholder (:pangalan), kung saan ang pagkakasunud-sunod ay hindi mahalaga. Mga halimbawa:
$sql = ;
$sql = ;

Upang maisagawa ang naturang query, kailangan muna itong ihanda gamit ang function na prepare(). Nagbabalik din ito ng pahayag ng PDO, ngunit wala pang data. Upang makuha ang mga ito, kailangan mong isagawa ang kahilingang ito, pagkatapos ipasa ang mga variable dito. Maaari mo itong ipadala sa dalawang paraan:
Kadalasan, maaari mo lamang isagawa ang execute() na pamamaraan, na ipapasa ito sa isang array na may mga variable:
$stmt = $pdo -> maghanda( "PUMILI NG pangalan MULA SA mga user WHERE email = ?");
$stmt -> execute(array($email ));

$stmt = $pdo -> maghanda( "PUMILI NG pangalan MULA SA mga user WHERE email = :email");
$stmt -> execute (array("email" => $email ));
Tulad ng nakikita mo, sa kaso ng mga pinangalanang placeholder, isang array ang dapat ipasa upang maipatupad(), kung saan ang mga susi ay dapat tumugma sa mga pangalan ng mga placeholder.

Minsan, napakabihirang, maaaring kailanganin ang pangalawang paraan, kapag ang mga variable ay unang nakatali sa kahilingan nang paisa-isa, gamit ang bindValue() / bindParam(), at pagkatapos ay ipapatupad lamang. Sa kasong ito, walang ipinasa upang maisagawa (). Ang isang halimbawa ay matatagpuan sa manwal.
Gamit ang pamamaraang ito, dapat bang palaging mas gusto ang bindValue()? dahil ang pag-uugali ng bindParam() ay hindi halata sa mga nagsisimula at hahantong sa mga problema.

Pagkatapos nito, maaari mong gamitin ang pahayag ng PDO sa parehong mga paraan tulad ng nasa itaas. Halimbawa, sa pamamagitan ng foreach:
$stmt = $pdo -> maghanda( "PUMILI NG pangalan MULA SA mga user WHERE email = ?");
$stmt ->
foreach ($stmt bilang $row )
{
echo $row [ "pangalan" ] . "\n" ;
}

MAHALAGA: Ang mga inihandang expression ay ang pangunahing dahilan upang gamitin ang PDO kung ano ito ang nag-iisa ligtas na paraan pagpapatupad ng mga query sa SQL na may kasamang mga variable.

Gayundin, ang prepare() / execute() ay maaaring gamitin upang paulit-ulit na magsagawa ng minsang inihanda na query na may iba't ibang set ng data. Sa pagsasagawa, ito ay lubhang bihirang kailangan, at hindi nagdadala ng isang espesyal na pagtaas sa bilis. Ngunit kung sakaling kailangan mong gumawa ng maraming parehong uri ng mga kahilingan, maaari kang sumulat ng ganito:

$data = array(
1 => 1000,
5 => 300,
9 => 200,
);

$stmt = $pdo -> maghanda( "I-UPDATE ang mga user SET bonus = bonus + ? WHERE id = ?");
foreach ($data bilang $id => $bonus )
{
$stmt -> execute([ $bonus , $id ]);
}

Dito namin inihahanda ang query nang isang beses at pagkatapos ay ipapatupad ito ng maraming beses.

Natugunan na namin ang paraan ng fetch() sa itaas, na nagsisilbing sunud-sunod na pagkuha ng mga row mula sa database. Ang pamamaraang ito ay kahalintulad sa mysq_fetch_array() function at mga katulad nito, ngunit ito ay gumagana nang iba: sa halip na maraming mga function, isa ang ginagamit dito, ngunit ang pag-uugali nito ay itinakda ng naipasa na parameter. Magsusulat ako ng higit pa tungkol sa mga pagpipiliang ito sa ibang pagkakataon, ngunit bilang isang mabilis na tip, inirerekumenda ko ang paggamit ng fetch() sa FETCH_LAZY mode:
$stmt = $pdo -> maghanda( "PUMILI NG pangalan MULA SA mga user WHERE email = ?");
$stmt -> execute([ $_GET [ "email" ]]);
habang ($row = $stmt -> fetch (PDO::FETCH_LAZY ))
{
echo $row [ 0 ] . "\n" ;
echo $row [ "pangalan" ] . "\n" ;
echo $row -> pangalan . "\n" ;
}

Sa mode na ito, walang labis na memorya ang nasasayang, at bukod pa, maaaring ma-access ang mga column sa alinman sa tatlong paraan - sa pamamagitan ng index, pangalan, o property.

Gayundin, ang pahayag ng PDO ay may function ng helper upang makuha ang halaga ng isang column. Ito ay napaka-maginhawa kung humiling lamang kami ng isang patlang - sa kasong ito, ang dami ng pagsulat ay makabuluhang nabawasan:
$stmt = $pdo -> maghanda( "PUMILI NG pangalan MULA sa talahanayan WHERE id=?");
$stmt -> execute(array($id ));
$name = $stmt -> fetchColumn();

Ngunit ang pinakakawili-wiling function, na may pinakamaraming functionality, ay fetchAll(). Siya ang gumagawa ng PDO bilang isang mataas na antas ng aklatan para sa pagtatrabaho sa database, at hindi lamang isang mababang antas ng driver.

Ang FetchAll() ay nagbabalik ng array na naglalaman ng lahat ng row na ibinalik ng query. Kung saan maaaring makuha ang dalawang konklusyon:
1. Ang function na ito ay hindi dapat gamitin kapag ang query ay nagbabalik ng maraming data. Sa kasong ito, mas mainam na gumamit ng tradisyonal na loop na may fetch()
2. Dahil sa mga modernong PHP application ang data ay hindi kailanman ipinapakita kaagad sa oras na matanggap, ngunit ipinapasa sa template para dito, ang fetchAll () ay nagiging kailangang-kailangan, na nagbibigay-daan sa iyong hindi manu-manong magsulat ng mga cycle, at sa gayon ay bawasan ang dami ng code.

Pagkuha ng isang simpleng array.
Tinatawag na walang mga parameter, ang function na ito ay nagbabalik ng regular na naka-index na array na naglalaman ng mga row mula sa database sa format na tinukoy sa FETCH_MODE bilang default. Ang mga constant na PDO::FETCH_NUM, PDO::FETCH_ASSOC, PDO::FETCH_OBJ ay maaaring baguhin ang format sa mabilisang.

Kumuha ng column.
Minsan kailangan mong makakuha ng isang simpleng one-dimensional array sa pamamagitan ng paghingi ng isang field mula sa isang grupo ng mga string. Para dito, ginagamit ang PDO::FETCH_COLUMN mode.
$data = $pdo -> query("PUMILI NG pangalan MULA SA mga user" )-> fetchAll(PDO::FETCH_COLUMN );
array(
0 => "Juan",
1 => "Mike",
2 => "Maria",
3 => "Kathy",
)

Kumuha ng mga pares ng key-value.
Gayundin isang tanyag na format kapag ito ay kanais-nais na makakuha ng parehong haligi, ngunit na-index hindi sa pamamagitan ng mga numero, ngunit sa pamamagitan ng isa sa mga patlang. Ang PDO::FETCH_KEY_PAIR constant ang responsable para dito.
$data = $pdo -> query("SELECT id, name FROM users" )-> fetchAll(PDO::FETCH_KEY_PAIR );
array(
104 => "Juan",
110
120 => "Maria",
121
)

Kunin ang lahat ng mga hilera na na-index ng isang field.
Madalas ding kinakailangan upang makuha ang lahat ng mga hilera mula sa database, ngunit na-index din hindi sa pamamagitan ng mga numero, ngunit sa pamamagitan ng isang natatanging field. Ito ang ginagawa ng PDO::FETCH_UNIQUE constant.
$data = $pdo -> query("SELECT * FROM users" )-> fetchAll(PDO::FETCH_UNIQUE );
array(
104 => array (
"pangalan" => "Juan" ,
"kotse" => "Toyota" ,
),
110 => array (
"name" => "Mike" ,
"kotse" => "Ford" ,
),
120 => array (
"pangalan" => "Maria",
"kotse" => "Mazda" ,
),
121 => array (
"pangalan" => "Kathy" ,
"kotse" => "Mazda" ,
),
)

Dapat tandaan na ang unang field sa column ay dapat na kakaibang field.

Sa kabuuan, mayroong higit sa isang dosenang iba't ibang mga mode para sa pagkuha ng data sa PDO. Dagdag pa, maaari mong pagsamahin ang mga ito! Ngunit ito ay isang paksa para sa isang hiwalay na artikulo.

Kapag nagtatrabaho sa mga inihandang expression, dapat mong maunawaan na ang isang placeholder ay maaari lamang palitan ang isang string o isang numero. hindi rin keyword, ni isang identifier, o isang bahagi ng isang string o isang hanay ng mga string ay maaaring palitan sa pamamagitan ng isang placeholder. Samakatuwid, para sa LIKE, kailangan mo munang ihanda ang buong string ng paghahanap, at pagkatapos ay palitan ito sa query:

$name = "% $name %" ;
$stm = $pdo -> maghanda( "PUMILI * MULA sa talahanayan SAAN ang pangalang GUSTO ?");
$stm -> execute(array($name ));
$data = $stm -> fetchAll();

Well, nakuha mo ang ideya. Masama din dito. Ang PDO ay hindi nagbibigay ng anumang mga tool para sa pagtatrabaho sa mga identifier, at dapat na naka-format ang mga ito sa lumang paraan, nang manu-mano (o tumingin, pagkatapos ng lahat, patungo sa SafeMysql , kung saan ito, tulad ng maraming iba pang mga isyu, ay nalutas nang simple at eleganteng).
Dapat tandaan na ang mga patakaran para sa pag-format ng mga identifier ay naiiba para sa iba't ibang mga database.

Sa mysql, upang manu-manong mag-format ng isang id, kailangan mong gawin ang dalawang bagay:
- ilakip ito sa likod ng mga solong panipi (mga backticks, "`").
- sukatin ang mga character na ito sa loob ng identifier sa loob sa pamamagitan ng pagdodoble.

$field = "`" . str_replace ("`" , "``" , $_GET [ "field" ]). "`";
$sql = $patlang" ;

Gayunpaman, mayroong isang caveat dito. Maaaring hindi sapat ang pag-format lamang. Ang code sa itaas ay magpoprotekta sa amin mula sa klasikong iniksyon, ngunit sa ilang mga kaso ang kaaway ay maaari pa ring sumulat ng isang bagay na hindi kanais-nais kung hindi namin pinag-iisipan na palitan ang mga pangalan ng field at talahanayan nang diretso sa query. Halimbawa, mayroong field ng admin sa talahanayan ng mga user. Kung ang mga papasok na pangalan ng field ay hindi na-filter, pagkatapos ay sa field na ito, kapag ang isang kahilingan ay awtomatikong nabuo mula sa isang POST, sinumang tanga ay magsusulat ng anumang muck.

Samakatuwid, ang mga pangalan ng mga talahanayan at mga patlang na nagmumula sa gumagamit ay dapat suriin para sa bisa, tulad ng sa halimbawa sa ibaba

Ang anumang naka-embed na code na makikita sa maraming mga tutorial ay nagbibigay inspirasyon sa mapanglaw at isang pagnanais na pumatay ng isang upsten. Mga multi-kilometrong konstruksyon na may pag-uulit ng parehong mga pangalan - sa mga $_POST na index, sa mga variable na pangalan, sa mga pangalan ng field sa isang kahilingan, sa mga pangalan ng placeholder sa isang kahilingan, sa mga pangalan ng placeholder at mga variable na pangalan kapag nagbubuklod.
Ang pagtingin sa code na ito ay nagdudulot sa akin ng pagnanais na pumatay ng isang tao, o hindi bababa sa gawin itong mas maikli.

Magagawa ito sa pamamagitan ng pagpapatibay sa kumbensyon na ang mga pangalan ng field sa form ay tutugma sa mga pangalan ng field sa talahanayan. Pagkatapos ang mga pangalan na ito ay maaaring ilista nang isang beses lamang (upang maprotektahan laban sa pagpapalit na binanggit sa itaas), at gumamit ng isang maliit na function ng helper upang bumuo ng isang query, na, dahil sa mga kakaiba ng mysql, ay angkop para sa parehong INSERT at UPDATE na mga query:

function pdoSet ($allowed , & $values ​​​​, $source = array()) (
$set = "" ;
$values ​​= array();
kung (! $source ) $source = & $_POST ;
foreach ($allowed as $field ) (
if (isset($source [ $field ])) (
$set .= "`" . str_replace ("`" , "``" , $field ). "`" . "=: $field ," ;
$values ​​​​[ $field ] = $source [ $field ];
}
}
return substr ($set , 0 , - 2 );
}

Alinsunod dito, upang ipasok ang code ay magiging

$allowed = array("pangalan" , "apelyido" , "email" ); // pinapayagan na mga field
$sql = "INSERT INTO users SET " . pdoSet($allowed , $values ​​​​);
$stm = $dbh -> maghanda($sql );
$stm -> execute($values);

At para sa pag-update - ito:

$allowed = array("name" , "apelyido" , "email" , "password" ); // pinapayagan na mga field
$_POST [ "password" ] = MD5 ($_POST [ "login" ]. $_POST [ "password" ]);
$sql = "I-UPDATE ang mga user SET " . pdoSet($allowed , $values ​​​​). " WHERE id = :id" ;
$stm = $dbh -> maghanda($sql );
$values["id"] = $_POST["id"];
$stm -> execute($values);

Hindi masyadong epektibo, ngunit napaka-epektibo. Hayaan mong ipaalala ko sa iyo, sa pamamagitan ng paraan, na kung gagamitin mo ang Klase para sa ligtas at maginhawang trabaho sa MySQL, kung gayon ang lahat ay ginagawa sa dalawang linya.

PDO at mga keyword
Dito, bukod sa pagsala, imposibleng mag-isip ng anuman. samakatuwid, hangal na patakbuhin ang lahat ng mga operator na hindi direktang tinukoy sa kahilingan sa pamamagitan ng puting listahan:

$dirs = array("ASC" , "DESC" );
$key = array_search($_GET [ "dir" ], $dirs ));
$dir = $orders [ $key ];
$sql = "PUMILI * MULA SA `table` ORDER NI$field $dir" ;

Termino PDO ay abbreviation para sa Mga Bagay sa Data ng PHP. Tulad ng iminumungkahi ng pangalan, pinapayagan ka ng teknolohiyang ito na magtrabaho kasama ang mga nilalaman ng database sa pamamagitan ng mga bagay.

Bakit hindi myqli o mysql?

Kadalasan, tungkol sa mga bagong teknolohiya, ang tanong ay lumitaw sa kanilang mga pakinabang sa mahusay na luma at napatunayang mga tool, pati na rin ang paglipat ng kasalukuyan at lumang mga proyekto sa kanila.

Object Oriented na PDO

PHP ay aktibong umuunlad at naglalayong maging isa sa mga pinakamahusay na tool para sa mabilis na pag-unlad ng mga web application, parehong mass at antas ng enterprise.

Speaking of PHP, ang ibig nating sabihin ay ang modernong object-oriented PHP, na nagbibigay-daan sa iyong magsulat ng generic na code na madaling subukan at muling gamitin.

Paggamit PDO ay nagbibigay-daan sa iyo upang dalhin ang trabaho sa database sa object-oriented na antas at pagbutihin ang portability ng code. Sa totoo lang, ang paggamit PDO hindi kasing hirap ng iniisip ng isa.

Abstraction

Kunwari tayo na matagal na panahon pagbuo ng isang application gamit ang MySQL. At pagkatapos, sa isang magandang sandali, ito ay nagiging kinakailangan upang palitan MySQL sa PostgreSQL.

Sa pinakamababa, kailangan nating palitan ang lahat ng tawag mysqli_connect() (mysql_connect()) sa pg_connect() at, sa pamamagitan ng pagkakatulad, iba pang mga function na ginagamit upang mag-query at magproseso ng data.

Gamit PDO, lilimitahan namin ang aming sarili sa pagbabago ng ilang mga parameter sa mga file ng pagsasaayos.

Pagbubuklod ng parameter

Ang paggamit ng mga nakatali na parameter ay nagbibigay ng higit na kakayahang umangkop sa pag-query at nagpapabuti ng proteksyon laban sa SQL mga iniksyon.

Pagkuha ng Data bilang Mga Bagay

Yung mga gumagamit na ORM(object-relational mapping - object-relational mapping ng data), halimbawa, Doktrina alamin ang kaginhawahan ng paglalahad ng data mula sa mga talahanayan ng database bilang mga bagay. PDO nagbibigay-daan sa iyo na makatanggap ng data sa anyo ng mga bagay at nang hindi ginagamit ORM.

Ang mysql extension ay hindi na suportado

Suporta sa extension mysql permanenteng inalis sa bago PHP 7. Kung nagpaplano kang ilipat ang iyong proyekto sa bagong bersyon PHP, dapat gumamit ka na ng kahit mysqli dito. Siyempre, mas mahusay na simulan ang paggamit PDO kung hindi mo pa nagagawa.

Tila sa akin na ang mga kadahilanang ito ay sapat na upang ikiling ang mga kaliskis patungo sa paggamit ng PDO. Higit pa rito, hindi mo kailangang mag-install ng anumang dagdag.

Sinusuri ang PDO sa system

Mga bersyon PHP 5.5 at sa itaas, kadalasan, ay naglalaman na ng extension para sa pagtatrabaho PDO. Upang suriin, magpatakbo lamang ng isang simpleng command sa console:

php -i | grep "pdo"

Ngayon buksan natin ito sa anumang browser at hanapin ang kinakailangang data sa pamamagitan ng paghahanap para sa string PDO.

Pagkilala sa PDO

Ang proseso ng pagtatrabaho sa PDO hindi masyadong naiiba sa tradisyonal. Sa pangkalahatan, ang proseso ng paggamit PDO parang ganyan:

  1. Koneksyon sa database;
  2. Kung kinakailangan, naghahanda ng isang kahilingan at nagbubuklod na mga parameter;
  3. Pagpapatupad ng isang kahilingan.

Koneksyon sa database

Upang kumonekta sa database, kailangan mong lumikha ng isang bagong bagay PDO at ipasa ang pangalan ng data source, na kilala rin bilang DSN.

Sa pangkalahatan, DSN ay binubuo ng pangalan ng driver na pinaghihiwalay ng isang colon mula sa string ng koneksyon na partikular sa bawat driver PDO.

Para sa MySQL, ang koneksyon ay ginawa tulad nito:

$koneksyon = bagong PDO("mysql:host=localhost;dbname=mydb;charset=utf8", "root", "root");

$koneksyon = bagong PDO( "mysql:host=localhost;dbname=mydb;charset=utf8", "ugat" , "ugat" );

SA kasong ito, DSN naglalaman ng pangalan ng driver mysql, na tumutukoy sa host (posibleng format host=HOSTNAME:PORT), pangalan ng database, pag-encode, username MySQL at ang kanyang password.

Mga kahilingan

Unlike mysqli_query(), V PDO Mayroong dalawang uri ng mga kahilingan:

  • Nagbabalik na resulta ( piliin, ipakita);
  • Walang ibinalik na resulta ( ipasok, detalye at iba pa).

Una sa lahat, isaalang-alang natin ang pangalawang pagpipilian.

Nagsasagawa ng mga query

Isaalang-alang ang isang halimbawa ng pagsasagawa ng isang query gamit ang isang halimbawa ipasok.

$connection->exec("INSERT INTO users VALUES (1, "somevalue"");

$koneksyon -> exec();

Siyempre, ibinabalik ng query na ito ang bilang ng mga apektadong row at makikita mo ito bilang mga sumusunod.

$affectedRows = $connection->exec("INSERT INTO users VALUES (1, "somevalue"");echo $affectedRows;

$affectedRows = $koneksyon -> exec( "INSERT INTO users VALUES (1, "somevalue"") ;

echo $affectedRows ;

Pagkuha ng mga resulta ng query

Sa kaso ng paggamit mysqli_query(), ang code ay maaaring ang mga sumusunod.

$result = mysql_query("SELECT * FROM users"); while($row = mysql_fetch_assoc($result)) ( echo $row["id"] . " " . $row["name"]; )

$result = mysql_query ("PUMILI * MULA SA mga gumagamit" );

habang ($row = mysql_fetch_assoc ($result) ) (

Para sa PDO, ang code ay magiging mas simple at mas maigsi.

foreach($connection->query("SELECT * FROM users") as $row) ( echo $row["id"] . " " . $row["name"]; )

foreach ($koneksyon -> query("SELECT * FROM users") bilang $row ) (

echo $row [ "id" ] . " " . $row [ "pangalan" ] ;

Mga Mode ng Pagkuha ng Data

Tulad ng sa mysqli, PDO nagbibigay-daan sa iyong makatanggap ng data sa iba't ibang mga mode. Upang matukoy ang mode, ang klase PDO naglalaman ng kaukulang mga pare-pareho.

  • PDO::FETCH_ASSOC- nagbabalik ng array na na-index ng pangalan ng column sa database table;
  • PDO::FETCH_NUM- nagbabalik ng array na na-index ayon sa numero ng column;
  • PDO::FETCH_OBJ- nagbabalik ng hindi kilalang bagay na may mga pangalan ng property na tumutugma sa mga pangalan ng column. Halimbawa, maglalaman ang $row->id ng value mula sa column ng id.
  • PDO::FETCH_CLASS- nagbabalik ng isang bagong halimbawa ng klase, na may mga halaga ng ari-arian na tumutugma sa data mula sa hilera ng talahanayan. Kung tinukoy ang parameter PDO::FETCH_CLASSTYPE(Halimbawa PDO::FETCH_CLASS | PDO::FETCH_CLASSTYPE), ang pangalan ng klase ay matutukoy mula sa halaga ng unang column.

Tandaan: ay hindi buong listahan, lahat ng posibleng constant at variant ng kumbinasyon ng mga ito ay available sa dokumentasyon.

Isang halimbawa ng pagkuha ng isang associative array:

$statement = $connection->query("SELECT * FROM users"); while($row = $statement->fetch(PDO::FETCH_ASSOC)) ( echo $row["id"] . " " . $row["name"]; )

$statement = $koneksyon ->

habang ($row = $statement -> fetch (PDO::FETCH_ASSOC ) ) (

echo $row [ "id" ] . " " . $row [ "pangalan" ] ;

Tandaan: Inirerekomenda na palagi mong tukuyin ang sampling mode, dahil ang sampling mode PDO::FETCH_BOTH mangangailangan ng dalawang beses higit pang memorya- sa katunayan, dalawang array ang gagawin, isang associative at isang regular.

Isaalang-alang ang paggamit ng sample mode PDO::FETCH_CLASS. Gumawa tayo ng klase gumagamit:

Class User ( protected $id; protected $name; public function getId() ( return $this->id; ) public function setId($id) ($this->id = $id; ) public function getName() ( return $this->name; ) public function setName($name) ( $this->name = $name; ) )

User ng klase

protektado $id ;

protektado $name ;

pampublikong function getId()

ibalik $this -> id ;

public function setId ( $id )

$this -> id = $id ;

pampublikong function getName()

ibalik ang $this -> name ;

public function setName ($name )

$this -> name = $name ;

Ngayon piliin natin ang data at ipakita ang data gamit ang mga pamamaraan ng klase:

$statement = $connection->query("SELECT * FROM users"); while($row = $statement->fetch(PDO::FETCH_CLASS, "User")) ( echo $row->getId() . " " . $row->getName(); )

$statement = $connection -> query ("PUMILI * MULA SA mga user" );

habang ($row = $statement -> fetch (PDO::FETCH_CLASS , "User") ) (

echo $row -> getId() . " " . $row -> getName();

Inihanda ang mga query at parameter binding

Upang maunawaan ang kakanyahan at lahat ng mga pakinabang ng pagbubuklod ng mga parameter, kailangan mong tingnan nang mabuti ang mga mekanismo. PDO. Kapag tinawag $statement -> query() sa code sa itaas, PDO ay maghahanda ng query, isasagawa ito, at ibabalik ang resulta.

Kapag tinawag $koneksyon -> maghanda() isang inihandang query ay nilikha. Ang mga inihandang query ay ang kakayahan ng sistema ng pamamahala ng database na makatanggap ng template ng query, i-compile ito, at isagawa ito pagkatapos matanggap ang mga halaga ng mga variable na ginamit sa template. Ang mga template engine ay gumagana sa parehong paraan. Matalino At Twig.

Kapag tinawag $statement -> execute() Ang mga halaga ay ipinapasa para sa pagpapalit sa template ng query at ang DBMS ay nagpapatupad ng query. Ang pagkilos na ito ay katulad ng pagtawag sa function ng template render().

Isang halimbawa ng paggamit ng mga inihandang query sa PHP PDO:

Sa code sa itaas, isang query para sa pagpili ng isang talaan na may isang field ay inihanda id katumbas ng halaga na papalitan :id. Sa yugtong ito, i-parse at i-compile ng DBMS ang query, posibleng gamit ang caching (depende sa mga setting).

Ngayon ay kailangan mong ipasa ang nawawalang parameter at isagawa ang kahilingan:

$id = 5; $statement->execute([ ":id" => $id ]);

Mga Benepisyo ng Paggamit ng Mga Naka-link na Parameter

Marahil, pagkatapos tingnan kung paano gumagana ang mga inihandang query at ang nauugnay na mga parameter, nagiging malinaw ang mga benepisyo ng paggamit sa mga ito.

PDO nagbibigay ng maginhawang paraan upang makatakas sa data ng user, halimbawa, hindi na kailangan ang code na ito:

Sa halip, mas makatuwirang gawin ito:

Maaari mo pa ring paikliin ang code sa pamamagitan ng paggamit ng mga parameter na may bilang sa halip na mga pinangalanan:

Kasabay nito, ang paggamit ng mga inihandang query ay nagbibigay-daan sa iyo na mapabuti ang pagganap kapag ginamit mo ang parehong query ng template nang maraming beses. Sample na seleksyon ng limang random na user mula sa database:

$numberOfUsers = $connection->query("SELECT COUNT(*) FROM users")->fetchColumn(); $users = ; $statement = $connection->prepare("SELECT * FROM users WHERE id = ? LIMIT 1"); para sa ($i = 1; $i<= 5; $i++) { $id = rand(1, $numberOfUsers); $users = $statement->execute([$id])->fetch(PDO::FETCH_OBJ); )

$numberOfUsers = $connection -> query ("SELECT COUNT(*) FROM users" ) -> fetchColumn () ;

$users = ;

para sa ($i = 1 ; $i<= 5 ; $i ++ ) {

$id = rand (1 , $numberOfUsers );

$users = $statement -> execute ([ $id ] ) -> fetch (PDO::FETCH_OBJ );

Kapag tumatawag sa isang pamamaraan maghanda(), susuriin at isasama ng DBMS ang query, gamit ang caching kung kinakailangan. Mamaya sa cycle para sa, tanging ang data na may tinukoy na parameter ang kinukuha. Binibigyang-daan ka ng diskarteng ito na makakuha ng data nang mas mabilis, na binabawasan ang oras ng pagtakbo ng application.

Pagkatanggap kabuuan ang mga gumagamit sa paraan ng database ay ginamit fetchColumn(). Ibinabalik ng pamamaraang ito ang halaga ng isang column at kapaki-pakinabang kapag nagbabalik ng mga scalar na halaga gaya ng bilang, kabuuan, maximum, o pinakamababang halaga.

Bound Values ​​at ang IN Operator

Kadalasan, kapag nagsimula sa PDO, may mga paghihirap sa operator SA. Halimbawa, ipagpalagay na ang gumagamit ay nagpasok ng maraming mga pangalan na pinaghihiwalay ng mga kuwit. Ang input ng user ay iniimbak sa isang variable $pangalan.

Sa huling artikulong ito, titingnan natin, ano ang mga inihandang tanong, kung paano mahuli ang mga error At ano ang mga transaksyon sa PDO.

Inihanda ang mga tanong

Kapag nagsagawa kami ng isang query sa database, ito ay sinusuri at ino-optimize, na natural na tumatagal ng oras. Kung marami tayong kumplikadong query, maaaring tumagal ito ng napakatagal. Gamit ang pareho naghanda ng mga katanungan, ito ay ginagawa nang isang beses, at pagkatapos ay magagamit namin ang aming query nang maraming beses hangga't gusto namin. Gayundin, hindi namin kailangang takasan ang mga parameter, dahil driver ng database gagawin ang lahat sa kanyang sarili. Tingnan natin kung paano gamitin ang mga ito.

$stmt = $db->prepare("INSERT INTO articles (title, text) VALUES (:title, :text)");
$stmt->bindParam(":title", $title);
$stmt->bindParam(":text", $text);



$stmt->execute();



$stmt->execute();

Upang maghanda ng isang kahilingan, isinusulat namin ito sa pamamaraan maghanda, kung saan sa halip na mga halaga ay tinukoy namin ang isang linya tulad nito: ":Pangalan". Sa pamamaraan bindParam tinutukoy namin kung saang linya kung aling data ang isailalim. Sa aming kaso, sa linya : pamagat nagbubuklod na data mula sa isang variable $title, at sa linya :text- data mula sa isang variable $text. Upang maisagawa ang isang kahilingan, kailangan mong tawagan ang pamamaraan isagawa. Ang ganitong mga parameter ay tinatawag pinangalanan, tingnan mo ngayon walang pangalan.

$stmt = $db->prepare("INSERT INTO articles (title, text) VALUES (?, ?)");
$stmt->bindParam(1, $title);
$stmt->bindParam(2, $text);

$title = "pamagat ng artikulo 1";!}
$text = "Ilang teksto para sa unang artikulo";
$stmt->execute();

$title = "pamagat ng artikulo 2";!}
$text = "Ilang teksto para sa pangalawang artikulo";
$stmt->execute();

Narito ang lahat ay magkapareho, maliban na sa halip na linya :Pangalan isang tandang pananong ay ipinahiwatig, at sa pamamaraan bindParam numero 1 ibig sabihin una tandang pananong at numero 2 - pangalawa tandang pananong. Gamitin ang alinmang paraan na gusto mo.

Mga error sa paghuli

Upang mahuli ang mga error, ginagamit namin ang pamilyar na konstruksiyon subukan mong mahuli at klase PDOException.

Subukan(
$db = bagong PDO("myql:host=$host;dbname=$dbname", $user, $pass);
) catch(PDOException $e) (
echo "Mayroon kang error: ".$e->getMessage()."
";
echo "Online: ".$e->getLine();
}

Bilang halimbawa, nagkamali ako at nagsulat mysql, ngunit hindi mysql. Mahuhuli ang error na ito at ipapakita namin ang text nito at kung saang linya naganap ang error.

Mga transaksyon

isaalang-alang natin mga transaksyon mismo sa halimbawa.

Subukan(
$db = bagong PDO("mysql:host=$host;dbname=$dbname", $user, $pass);
$db->beginTransaction();

$stmt = $db->exec("INSERT INTO `articles`(`title`) VALUES("title1")");
$stmt = $db->exec("INSERT INTO `articles`(`title`) VALUES("title2")");
exit("error");

$stmt = $db->exec("INSERT INTO `articles`(`title`) VALUES("title3")");
$db->commit();

) catch(PDOException $e) (
$db->rollBack();
}

simulan angTransaksyon ibig sabihin nagsisimula na tayo ng transaksyon. Mangako Kinukumpirma ang mga pagbabago, at rollBack kinansela ang lahat.

Ang kakanyahan ng mga transaksyon ay ginagawa natin ang lahat o wala. Sa aming halimbawa, ipinasok namin sa talahanayan mga artikulo mga halaga pamagat1, pamagat2, pamagat3. Ngunit pagkatapos ipasok ang pangalawang halaga, na-simulate namin ang isang error sa pamamagitan ng paghinto sa script gamit ang labasan. Kung hindi natin ginamit mga transaksyon, pagkatapos ay mayroon kaming unang dalawa pamagat ilalagay, ngunit ang huli ay hindi. Sa aming halimbawa, hindi ito mahalaga, ngunit may mga pagkakataon na maaari itong humantong sa mga seryosong pag-crash sa application. Upang maiwasang mangyari ito, ginagamit namin mga transaksyon, kung saan ang pamamaraan rollBack ibabalik ang lahat sa orihinal nitong anyo at ang una nating dalawa pamagat ay hindi rin maipasok, at kung ang lahat ay naging maayos, nang walang mga pagkakamali, kung gayon ang pamamaraan mangako ay kumpirmahin ang mga pagbabago at lahat ng tatlo pamagat ay matagumpay na maipasok.

Konklusyon

Kaya, sa aming tatlong artikulo sa pag-aaral ng PDO, sinaklaw namin ang lahat ng kailangan mo para magamit ang interface na ito nang madali. Sa tingin ko naiintindihan mo kung paano PDO ginagawang mas madali ang aming buhay at gagamitin ito sa iyong mga proyekto. Good luck!

Ito ay mga talahanayan, ngunit read-only (maaari kang gumawa ng ilang mga pagbabago, ngunit ang mga ito ay lubhang limitado). Sa katunayan, ito ay isang ordinaryong talahanayan, ngunit ito ay nilikha batay sa ilang query (iba pang mga talahanayan), i.e. ito ay isang 'link' sa ilang query. Isaalang-alang ang isang halimbawa:

GUMAWA NG TALAAN t(pangalan, presyo); //gumawa ng table GUMAWA NG VIEW v BILANG PUMILI pangalan, presyo, pangalan * presyo BILANG halaga MULA t;//lumikha ng isa pang talahanayan, ang ikatlong field bilang produkto ng unang dalawang PUMILI * MULA sa v; //kumuha ng data mula sa talahanayan

Yung. gumawa kami ng table na may ikatlong field na walang nakakaalam. At hindi mo kailangang ipakita ito sa lahat. Yung. maaari tayong gumawa ng table gamit ang View, halimbawa, sa isang kumpanya, para sa HR department, para sa mga empleyado, para sa educational department, para sa accounting. Ang aksyon ay katulad ng paggamit sa unang talahanayan bilang isang template at pagdaragdag ng mga bagong field dito.

Inihanda ang mga tanong

May mga sitwasyon na marami tayong record (halimbawa, 50000) sa database, at pinipili ang mga ito sa isang loop. Kung itulak namin ang mysql_query doon, ang query na ito ay susuriin ng 50,000 beses. Upang hindi mag-aksaya ng oras sa naturang pagsusuri, mayroong isang nakahanda na kahilingan - ito ay isang kahilingan na ibinigay sa database nang maaga, ito ay nasuri nang isang beses, at ang database ay handa na tanggapin ito. Halimbawa:

mysql_connect("localhost", "root", "password"); mysql_select_db("pagsusulit"); mysql_query("HANDA ANG myinsert MULA // isulat ang pangalan ng inihandang query "INSERT INTO test_table (pangalan, presyo) VALUES (?, ?)""); //narito ang inihandang query para sa ($i = 0; $i< 1000; $i++){ mysql_query("SET @name = "Товар # $i""); //установить значение "товар" для переменной @name mysql_query("SET @price = " . ($i * 10)); //установить значение цены для переменной @price mysql_query("EXECUTE myinsert USING @name, @price"); //исполнить подготовленный запрос, используя эти две переменные } mysql_close();

Sa linya ng inihandang tanong, ang mga halagang ilalagay ay hindi alam (sign?). Pagkatapos sa loop ay itinapon namin ang mga halaga sa talahanayan. Yung. sa loob ng mysql language nakikita natin ang ating mga variable, ang ating mga function.