Období CHOP je zkratka pro pojem Datové objekty PHP. Jak název napovídá, tato technologie umožňuje pracovat s obsahem databáze prostřednictvím objektů.

Proč ne myqli nebo mysql?

Nejčastěji s ohledem na nové technologie vyvstává otázka jejich výhod oproti starým dobrým a osvědčeným nástrojům a také přenosu současných a starých projektů na ně.

Objektová orientace PDO

PHP Velmi aktivně se rozvíjí a snaží se stát jedním z nejlepších nástrojů pro rychlý vývoj webových aplikací na masové i firemní úrovni.

Mluvit o PHP, máme na mysli moderní objektově orientované PHP, což vám umožní psát univerzální kód, který je vhodný pro testování a opětovné použití.

Používání CHOP umožňuje posunout práci s databázemi na objektově orientovanou úroveň a zlepšit přenositelnost kódu. Ve skutečnosti použití CHOP není tak těžké, jak by si někdo myslel.

Abstrakce

Představme si, že jsme aplikaci vyvíjeli dlouhou dobu pomocí MySQL. A pak, v jednom krásném okamžiku, bude nutné vyměnit MySQL na PostgreSQL.

Minimálně budeme muset nahradit všechna volání mysqli_connect() (mysql_connect()) na pg_connect() a analogicky další funkce používané k dotazování a zpracování dat.

Použitím CHOP, omezíme se na změnu několika parametrů v konfiguračních souborech.

Vazba parametrů

Použití propojených parametrů poskytuje větší flexibilitu při návrhu dotazů a zlepšuje ochranu proti SQL injekce.

Příjem dat jako objektů

Ti, kteří již používají ORM(objektově-relační mapování - objektově-relační mapování dat), např. Doktrína, znát pohodlí reprezentace dat z databázových tabulek ve formě objektů. CHOP umožňuje přijímat data ve formě objektů a bez použití ORM.

Rozšíření mysql již není podporováno

Podpora rozšíření mysql trvale odstraněno z nového PHP 7. Pokud plánujete migrovat projekt na novou verzi PHP, měli byste v něm nyní používat alespoň mysqli. Samozřejmě je lepší začít používat CHOP pokud jste tak již neučinili.

Zdá se mi, že tyto důvody jsou dostatečné k překlopení vah ve prospěch použití CHOP. Navíc nemusíte instalovat nic dalšího.

Kontrola přítomnosti PDO v systému

Verze PHP 5.5 a vyšší již nejčastěji obsahují rozšíření pro práci s CHOP. Pro kontrolu stačí spustit jednoduchý příkaz v konzole:

php -i | grep "pdo"

Nyní jej otevřeme v libovolném prohlížeči a vyhledáním po řádcích najdeme potřebná data CHOP.

Seznámení s CHOP

Proces práce s CHOP se příliš neliší od tradičního. Obecně platí, že proces použití CHOP vypadá takto:

  1. Připojte se k databázi;
  2. V případě potřeby připravte požadavek a parametry odkazu;
  3. Vyřízení požadavku.

Připojování k databázi

Pro připojení k databázi je potřeba vytvořit nový objekt CHOP a předejte mu název zdroje dat, známý také jako DSN.

Obecně, DSN sestává z názvu ovladače odděleného dvojtečkou od připojovacího řetězce specifického pro každý ovladač CHOP.

Pro MySQL, připojení je provedeno takto:

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

$connection = nové PDO ( "mysql:host=localhost;dbname=mydb;charset=utf8", "kořen" , "kořen" );

V tomto případě, DSN obsahuje jméno ovladače mysql, označení hostitele (možný formát hostitel=HOST_NAME:PORT), název databáze, kódování, uživatelské jméno MySQL a jeho heslo.

Žádosti

Na rozdíl od mysqli_query(), V CHOP existují dva typy žádostí:

  • Vrácení výsledku ( vybrat, ukázat);
  • Nevrácení výsledku ( vložit, detail a další).

Nejprve se podívejme na druhou možnost.

Provádění dotazů

Podívejme se na příklad provedení požadavku pomocí příkladu vložit.

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

$connection -> exec () ;

Tento dotaz samozřejmě vrátí počet ovlivněných řádků a můžete jej vidět následovně.

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

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

echo $affectedRows ;

Získání výsledků dotazu

V případě použití mysqli_query(), kód by mohl být následující.

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

$result = mysql_query ("SELECT * FROM users" ) ;

while ($row = mysql_fetch_assoc ($result) ) (

Pro CHOP, bude kód jednodušší a výstižnější.

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

foreach ($connection -> dotaz ("SELECT * FROM users") jako $row ) (

echo $row [ "id" ] . " ". $row["jméno"];

Režimy sběru dat

Jako v mysqli, CHOP umožňuje přijímat data v různých režimech. Chcete-li určit režim, tř CHOP obsahuje odpovídající konstanty.

  • PDO::FETCH_ASSOC— vrátí pole indexované podle názvu sloupce v databázové tabulce;
  • PDO::FETCH_NUM— vrátí pole indexované číslem sloupce;
  • PDO::FETCH_OBJ- vrátí anonymní objekt s názvy vlastností odpovídajícími názvům sloupců. Například $row->id bude obsahovat hodnotu ze sloupce id.
  • PDO::FETCH_CLASS— vrátí novou instanci třídy s hodnotami vlastností odpovídajícími datům z řádku tabulky. Pokud je parametr zadán PDO::FETCH_CLASSTYPE(Například PDO::FETCH_CLASS | PDO::FETCH_CLASSTYPE), název třídy bude určen z hodnoty prvního sloupce.

Poznámka: Toto není úplný seznam, všechny možné konstanty a jejich kombinace jsou dostupné v dokumentaci.

Příklad získání asociativního pole:

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

$statement = $connection ->

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

echo $row [ "id" ] . " ". $row["jméno"];

Poznámka: Doporučuje se vždy specifikovat režim vzorkování, protože režim PDO::FETCH_BOTH bude vyžadovat dvakrát tolik paměti – ve skutečnosti se vytvoří dvě pole, asociativní a regulární.

Zvažte použití režimu vzorkování PDO::FETCH_CLASS. Vytvořme třídu Uživatel:

class User ( chráněné $id; chráněné $jméno; veřejná funkce getId() ( return $this->id; ) veřejná funkce setId($id) ( $this->id = $id; ) veřejná funkce getName() ( return $this->name; ) veřejná funkce setName($name) ( $this->name = $name; ) )

třída Uživatel

chráněno $id ;

chráněné $jméno ;

veřejná funkce getId()

return $this -> id ;

veřejná funkce setId ($id)

$this -> id = $id ;

veřejná funkce getName()

return $this -> jmeno ;

veřejná funkce setName ($name)

$toto -> jmeno = $jmeno ;

Nyní vybereme data a zobrazíme data pomocí metod třídy:

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

$statement = $connection -> dotaz ("SELECT * FROM users" ) ;

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

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

Připravené dotazy a vazba parametrů

Abyste pochopili podstatu a všechny výhody vazby parametrů, musíte se blíže podívat na mechanismy CHOP. Při volání $statement -> query() ve výše uvedeném kódu, CHOP připraví požadavek, provede jej a vrátí výsledek.

Při volání $connection -> připravit() je vytvořena připravená žádost. Připravené dotazy jsou schopností systému správy databází přijmout šablonu dotazu, zkompilovat ji a provést po načtení hodnot proměnných použitých v šabloně. Šablonové motory fungují podobným způsobem. Smarty A Větvička.

Při volání $statement -> execute() hodnoty pro substituci se přenesou do šablony dotazu a DBMS provede dotaz. Tato akce je podobná volání funkce šablony poskytnout().

Příklad použití připravených dotazů v PHP PDO:

V kódu výše je připraven požadavek na výběr záznamu s polem id rovná hodnotě, která bude nahrazena : id. V této fázi bude DBMS analyzovat a kompilovat požadavek, případně pomocí ukládání do mezipaměti (v závislosti na nastavení).

Nyní musíte předat chybějící parametr a provést požadavek:

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

Výhody použití propojených parametrů

Možná po přezkoumání toho, jak fungují připravené dotazy a související parametry, vyjdou najevo výhody jejich používání.

CHOP poskytuje pohodlný způsob, jak uniknout uživatelským datům, například kód, jako je tento, již není potřeba:

Místo toho je nyní vhodné provést toto:

Kód můžete dokonce ještě zkrátit použitím číslovaných parametrů namísto pojmenovaných:

Použití připravených dotazů zároveň zlepšuje výkon při vícenásobném použití stejné šablony dotazu. Příklad výběru pěti náhodných uživatelů z databáze:

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

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

$users = ;

pro ($i = 1; $i<= 5 ; $i ++ ) {

$id = rand (1, $početUživatelů) ;

$users = $příkaz -> provést ([ $id ] ) -> načíst (PDO::FETCH_OBJ ) ;

Při volání metody připravit(), DBMS analyzuje a zkompiluje požadavek, v případě potřeby pomocí ukládání do mezipaměti. Později v cyklu pro, jsou vzorkována pouze data se zadaným parametrem. Tento přístup vám umožňuje získávat data rychleji a zkracovat dobu běhu aplikace.

Při získávání celkového počtu uživatelů v databázi byla použita metoda fetchColumn(). Tato metoda načte hodnotu jednoho sloupce a je užitečná při načítání skalárních hodnot, jako je počet, součet, maximální nebo minimální hodnoty.

Vázané hodnoty a operátor IN

Často při zahájení práce s CHOP, vznikají potíže s operátorem V. Představte si například, že uživatel zadá několik jmen oddělených čárkami. Vstup uživatele je uložen v proměnné $names.

Mnoho z vyspělejších databází podporuje koncept připravených výkazů. Co jsou? Lze je považovat za jakousi kompilovanou šablonu pro SQL, kterou chce aplikace spouštět, kterou lze přizpůsobit pomocí proměnných parametrů. Připravená prohlášení nabízejí dvě hlavní výhody:

  • Dotaz stačí analyzovat (nebo připravit) pouze jednou, ale lze jej provést vícekrát se stejnými nebo různými parametry. Když je dotaz připraven, databáze analyzuje, sestavuje a optimalizuje svůj plán pro provedení dotazu. U složitých dotazů může tento proces zabrat dost času na to, aby znatelně zpomalil aplikaci, pokud je potřeba opakovat stejný dotaz mnohokrát s různými parametry. Použitím připraveného příkazu se aplikace vyhne opakování cyklu analýzy/kompilace/optimalizace. To znamená, že připravené příkazy spotřebovávají méně zdrojů, a proto běží rychleji.
  • Parametry připravených příkazů není třeba uvádět, ovladač to zvládá automaticky. Pokud aplikace používá výhradně připravené příkazy, vývojář si může být jistý, že nedojde k žádné injekci SQL (pokud se však sestavují další části dotazu s neuvedeným vstupem je injekce SQL stále možná).

Připravené příkazy jsou tak užitečné, že jsou jedinou funkcí, kterou bude PDO emulovat pro ovladače, které je nepodporují. To zajišťuje, že aplikace bude moci používat stejné paradigma přístupu k datům bez ohledu na možnosti databáze.

Příklad č. 1 Opakované vkládání pomocí připravených příkazů

název a hodnota pro jmenované zástupné symboly.

$stmt = $dbh -> připravit ( "INSERT IN TO REGISTRY (název, hodnota) HODNOTY (:název, :hodnota)");
$stmt -> bindParam (":name" , $name );
$stmt -> bindParam (":value" , ​​​​$value );

// vložte jeden řádek
$jméno = "jeden" ;
$hodnota = 1 ;
$stmt -> vykonat();

$jméno = "dva" ;
$hodnota = 2 ;
$stmt -> vykonat();
?>

Příklad č. 2 Opakované vkládání pomocí připravených příkazů

Tento příklad provede dotaz INSERT nahrazením a název a hodnota pro poziční ? zástupné symboly.

$stmt = $dbh -> připravit ( "INSERT IN TO REGISTRY (název, hodnota) HODNOTY (?, ?)");
$stmt -> bindParam(1, $jméno);
$stmt -> bindParam (2 , $value );

// vložte jeden řádek
$jméno = "jeden" ;
$hodnota = 1 ;
$stmt -> vykonat();

// vloží další řádek s jinými hodnotami
$jméno = "dva" ;
$hodnota = 2 ;
$stmt -> vykonat();
?>

Příklad č. 3 Načítání dat pomocí připravených příkazů

Příklad #4 Volání uložené procedury s výstupním parametrem

Pokud to databázový ovladač podporuje, aplikace může také svázat parametry pro výstup i vstup. Výstupní parametry se obvykle používají k načtení hodnot z uložených procedur. Použití výstupních parametrů je o něco složitější než vstupních parametrů, protože vývojář musí vědět, jak velký může být daný parametr, když jej váže. Pokud se ukáže, že hodnota je větší než navrhovaná velikost, dojde k chybě.

$stmt = $dbh -> připravit ("CALL sp_returns_string(?)" );
$stmt -> bindParam(1, $return_value, PDO::PARAM_STR, 4000);

// volání uložené procedury
$stmt -> vykonat();

print "postup vrácen $return_value \n" ;
?>

Příklad č. 5 Volání uložené procedury se vstupním/výstupním parametrem

Vývojáři mohou také specifikovat parametry, které obsahují hodnoty jak vstupu, tak výstupu; syntaxe je podobná výstupním parametrům. V tomto dalším příkladu je řetězec "hello" předán do uložené procedury a když se vrátí, hello je nahrazeno návratovou hodnotou procedury.

$stmt = $dbh -> připravit ( "CALL sp_takes_string_returns_string(?)");
$value = "ahoj" ;!}
$stmt -> bindParam (1 , $value , PDO :: PARAM_STR | PDO :: PARAM_INPUT_OUTPUT , 4000 );

// volání uložené procedury
$stmt -> vykonat();

print "postup vrácen $hodnota \n" ;
?>

Toto jsou tabulky, ale pouze pro čtení (můžete provést nějaké změny, ale jsou extrémně omezené). V podstatě se jedná o běžnou tabulku, která je však vytvořena na základě nějakého dotazu (jiné tabulky), tzn. toto je ‚odkaz‘ na nějakou žádost. Podívejme se na příklad:

CREATE TABLE t(název, cena); //vytvoření tabulky CREATE VIEW v AS SELECT název, cena, název * cena AS hodnota FROM t;//vytvoří další tabulku, třetí pole jako součin prvních dvou SELECT * FROM v; //vezme data z tabulky

Tito. vytvořili jsme tabulku se třetím polem, o kterém nikdo neví. A nemusíte to všem ukazovat. Tito. tabulku můžeme pomocí View vytvořit např. ve firmě, pro HR oddělení, pro zaměstnance, pro školení, pro účetnictví. Akce je podobná použití první tabulky jako šablony a přidání nových polí do ní.

Připravené dotazy

Jsou situace, kdy máme v databázi hodně záznamů (například 50000) a ty se vybírají ve smyčce. Pokud tam vložíme mysql_query, bude tento dotaz analyzován 50 000krát. Abychom neztráceli čas takovou analýzou, je připravený dotaz - to je dotaz, který se předem odešle do databáze, jednou se analyzuje a databáze je připravena jej přijmout. Příklad:

Mysql_connect("localhost", "root", "heslo"); mysql_select_db("test"); mysql_query("PREPARE myinsert FROM // napište název připraveného dotazu "INSERT INTO test_table (název, cena) VALUES (?, ?)""); //zde je připravený dotaz pro ($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();

V připraveném řádku otázky jsou vložené hodnoty neznámé (znaménko?). Poté ve smyčce vložíme hodnoty do tabulky. Tito. uvnitř jazyka mysql vidíme naše proměnné, naše funkce.












PDO má svůj vlastní chytrý způsob připojení zvaný . Navíc během připojení můžete nastavit spoustu možností, z nichž některé jsou velmi užitečné. Kompletní seznam lze nalézt, ale jen některé jsou důležité.

Příklad správného zapojení:

$hostitel = "127.0.0.1" ;
$db = "test" ;
$user = "root" ;
$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 => nepravda,
];
$pdo = nové PDO ($dsn, $user, $pass, $opt);

Co se tam děje?

$dsn určuje typ databáze, se kterou budeme pracovat (mysql), hostitele, název databáze a znakovou sadu.
- následuje uživatelské jméno a heslo
- načež je specifikováno pole voleb, o kterých se v žádném z manuálů nepíše.

Nehledě na to, že toto pole je nesmírně užitečná věc, jak již bylo zmíněno výše. Nejdůležitější je, že chybový režim by měl být nastaven pouze ve formě výjimek.
- Za prvé, protože ve všech ostatních režimech PDO nehlásí nic srozumitelného o chybě,
- za druhé, protože výjimka vždy obsahuje nenahraditelné trasování zásobníku,
- za třetí, s výjimkami se velmi pohodlně manipuluje.

Navíc je velmi výhodné nastavit FETCH_MODE ve výchozím nastavení, abyste jej nezapisovali do KAŽDÉ žádosti, jak to pilní křečci opravdu rádi dělají.
Také zde můžete nastavit režim pconnect, emulaci připravených výrazů a mnoho dalších děsivých slov.

Výsledkem je proměnná $pdo, se kterou pracujeme v celém skriptu.

K provádění dotazů můžete použít dvě metody.
Pokud požadavku nejsou předány žádné proměnné, můžete použít funkci query(). Provede požadavek a vrátí speciální objekt - příkaz PDO. Velmi zhruba to můžete porovnat se zdrojem mysql, který vrátil mysql_query(). Data z tohoto objektu můžete získat buď tradičním způsobem, pomocí while nebo foreach(). Můžete také požádat o vrácení přijatých dat ve speciálním formátu, který je popsán níže.
$stmt = $pdo -> dotaz ("VYBRAT jméno FROM uživatelů" );
while ($row = $stmt -> fetch())
{
}

Pokud je požadavku předána alespoň jedna proměnná, musí být tento požadavek proveden pouze prostřednictvím připravené výrazy. co to je? Jedná se o běžný SQL dotaz, ve kterém je místo proměnné umístěna speciální značka – zástupný symbol. PDO podporuje poziční zástupné symboly (?), pro které je důležité pořadí předávaných proměnných, a pojmenované zástupné symboly (:name), pro které pořadí není důležité. Příklady:
$sql = ;
$sql = ;

Aby bylo možné takový dotaz provést, musí být nejprve připraven pomocí funkce Prepare(). Vrátí také příkaz PDO, ale zatím bez jakýchkoliv dat. Chcete-li je získat, musíte provést tento požadavek a předtím do něj předat proměnné. Přenést jej můžete dvěma způsoby:
Nejčastěji můžete jednoduše spustit metodu execute() a předat jí pole proměnných:
$stmt = $pdo -> připravit ( "SELECT name FROM users WHERE email =?");
$stmt -> vykonat (pole($email ));

$stmt = $pdo -> připravit ( "SELECT name FROM users WHERE email = :email");
$stmt -> vykonat (array("email" => $email ));
Jak můžete vidět, v případě pojmenovaných zástupných symbolů musí být předáno pole, ve kterém se klíče musí shodovat se jmény zástupných symbolů, aby se vykonala().

Někdy, velmi výjimečně, může být vyžadována druhá metoda, když jsou proměnné nejprve svázány s požadavkem jedna po druhé pomocí bindValue() / bindParam() a pak teprve provedeny. V tomto případě se funkci execute() nic nepředá. Příklad najdete v návodu.
Měla by být při použití této metody vždy upřednostňována metoda bindValue()? protože chování bindParam() není pro začátečníky zřejmé a povede k problémům.

Poté můžete použít příkaz PDO stejným způsobem jako výše. Například přes foreach:
$stmt = $pdo -> připravit ( "SELECT name FROM users WHERE email =?");
$stmt ->
foreach ($stmt jako $row)
{
echo $row [ "jméno" ] . "\n" ;
}

DŮLEŽITÉ: Připravené výrazy jsou hlavním důvodem pro použití PDO, protože to jediný bezpečný způsob provádění SQL dotazů, které zahrnují proměnné.

Připravit()/vykonat() lze také použít k opakovanému provádění jednou připraveného dotazu s různými datovými sadami. V praxi je to potřeba extrémně zřídka a nepřináší to velké zvýšení rychlosti. Ale v případě, že potřebujete vytvořit mnoho dotazů stejného typu, můžete to napsat takto:

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

$stmt = $pdo -> připravit ( "AKTUALIZOVAT uživatele SET bonus = bonus + ? KDE id = ?");
foreach ($data jako $id => $bonus)
{
$stmt -> provést ([ $bonus , $id ]);
}

Zde žádost jednou připravíme a poté mnohokrát vykonáme.

S metodou fetch(), která slouží k sekvenčnímu získávání řádků z databáze, jsme se již seznámili. Tato metoda je obdobou funkce mysq_fetch_array() a podobných, ale chová se jinak: místo mnoha funkcí je zde použita jedna, její chování je však specifikováno předávaným parametrem. O těchto parametrech se podrobně rozepíšu později, ale jako krátké doporučení bych doporučil použít fetch() v režimu FETCH_LAZY:
$stmt = $pdo -> připravit ( "SELECT name FROM users WHERE email =?");
$stmt -> execute([ $_GET [ "e-mail" ]]);
while ($row = $stmt -> načíst (PDO :: FETCH_LAZY ))
{
echo $row [ 0 ] . "\n" ;
echo $row [ "jméno" ] . "\n" ;
echo $row -> jméno . "\n" ;
}

V tomto režimu nedochází k plýtvání další pamětí a kromě toho lze ke sloupcům přistupovat kterýmkoli ze tří způsobů – prostřednictvím indexu, názvu nebo vlastnosti.

Příkaz PDO má také pomocnou funkci pro získání hodnoty jednoho sloupce. Je velmi výhodné, pokud požadujeme pouze jedno pole - v tomto případě je množství psaní výrazně sníženo:
$stmt = $pdo -> připravit ( "SELECT name FROM table WHERE id=?");
$stmt -> vykonat (pole($id ));
$name = $stmt -> fetchColumn();

Ale nejzajímavější funkcí s největší funkčností je fetchAll(). Právě to dělá z PDO knihovnu na vysoké úrovni pro práci s databází a ne pouze jako ovladač na nízké úrovni.

FetchAll() vrátí pole, které se skládá ze všech řádků, které dotaz vrátil. Z čehož lze vyvodit dva závěry:
1. Tato funkce by se neměla používat, když dotaz vrací velké množství dat. V tomto případě je lepší použít tradiční smyčku s fetch()
2. Vzhledem k tomu, že v moderních aplikacích PHP nejsou data nikdy vydána ihned po přijetí, ale jsou za tímto účelem přenesena do šablony, stává se fetchAll() jednoduše nenahraditelným, což vám umožní vyhnout se ručnímu psaní smyček, a tím snížit množství kódu.

Získání jednoduchého pole.
Tato funkce, volaná bez parametrů, vrací běžné indexované pole obsahující řádky z databáze ve formátu zadaném ve výchozím nastavení v FETCH_MODE. Konstanty PDO::FETCH_NUM, PDO::FETCH_ASSOC, PDO::FETCH_OBJ mohou měnit formát za běhu.

Získání sloupce.
Někdy potřebujete získat jednoduché jednorozměrné pole tím, že požádáte o jediné pole z hromady řetězců. K tomu použijte režim PDO::FETCH_COLUMN
$data = $pdo -> dotaz ("SELECT name FROM users" ) -> fetchAll (PDO :: FETCH_COLUMN );
pole (
0 => "Jan",
1 => "Mike",
2 => "Marie",
3 => "Kathy",
)

Načítání párů klíč–hodnota.
Také oblíbený formát, když je žádoucí získat stejný sloupec, ale indexovaný nikoli čísly, ale jedním z polí. Za to je zodpovědná konstanta PDO::FETCH_KEY_PAIR.
$data = $pdo -> dotaz ("SELECT id, jméno FROM uživatelů" ) -> fetchAll (PDO :: FETCH_KEY_PAIR );
pole (
104 => "Jan",
110 => "Mike",
120 => "Marie",
121 => "Kathy",
)

Získejte všechny řádky indexované podle pole.
Často je také nutné získat všechny řádky z databáze, ale také indexované nikoli čísly, ale jedinečným polem. To dělá konstanta PDO::FETCH_UNIQUE.
$data = $pdo -> dotaz ("SELECT * FROM users") -> fetchAll (PDO :: FETCH_UNIQUE );
pole (
104 => pole (
"jméno" => "Jan" ,
"auto" => "Toyota" ,
),
110 => pole (
"name" => "Mike" ,
"auto" => "Ford" ,
),
120 => pole (
"jméno" => "Marie" ,
"auto" => "Mazda" ,
),
121 => pole (
"jméno" => "Kathy" ,
"auto" => "Mazda" ,
),
)

Je třeba si uvědomit, že nejprve musíte ve sloupci vybrat jedinečné pole.

V PDO existuje více než jeden a půl tuctu různých režimů sběru dat. Navíc je můžete kombinovat! Ale to je téma na samostatný článek.

Při práci s připravenými výrazy byste měli pochopit, že zástupný symbol může nahradit pouze řetězec nebo číslo. Prostřednictvím zástupného symbolu nelze nahradit ani klíčové slovo, ani identifikátor, ani část řetězce nebo sady řetězců. Proto pro LIKE musíte nejprve připravit celý hledaný řetězec a poté jej dosadit do dotazu:

$jméno = "% $jméno %" ;
$stm = $pdo -> připravit ( "SELECT * FROM table WHERE jméno LIKE?");
$stm -> vykonat (pole($name ));
$data = $stm -> fetchAll();

No, rozumíte tomu. Tady je taky všechno špatně. PDO neposkytuje vůbec žádné nástroje pro práci s identifikátory a je nutné je formátovat staromódním způsobem, ručně (nebo se však poohlédnout po SafeMysql, ve kterém je to, jako mnoho jiných věcí, vyřešeno jednoduše a elegantně).
Je třeba si uvědomit, že pravidla pro formátování identifikátorů se pro různé databáze liší.

Chcete-li v mysql ručně naformátovat identifikátor, musíte udělat dvě věci:
- uzavřete jej zpětnými znaménky ("`").
- hledat tyto znaky uvnitř identifikátoru zdvojením.

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

Je zde však jedno upozornění. Samotné formátování nemusí stačit. Výše uvedený kód nás chrání před klasickou injekcí, ale v některých případech může nepřítel přesto napsat něco nechtěného, ​​pokud bezmyšlenkovitě dosadíme názvy polí a tabulek přímo do dotazu. Například v tabulce uživatelů je pole admin. Pokud nejsou názvy příchozích polí filtrovány, pak každý blázen napíše do tohoto pole jakékoli ošklivé věci, když automaticky generuje požadavek z POST.

Proto je vhodné zkontrolovat platnost názvů tabulek a polí pocházejících od uživatele, jako v příkladu níže

Jakýkoli kód pro vložení, který lze vidět v mnoha tutoriálech, přináší melancholii a touhu zabít apstena. Vícekilometrové konstrukce s opakováním stejných jmen - v indexech $_POST, v názvech proměnných, v názvech polí v požadavku, v zástupných názvech v požadavku, v zástupných názvech a názvech proměnných při vazbě.
Při pohledu na tento kód mám chuť někoho zabít, nebo to alespoň trochu zkrátit.

To lze provést přijetím konvence, že názvy polí ve formuláři odpovídají názvům polí v tabulce. Pak lze tato jména vypsat pouze jednou (z důvodu ochrany proti záměně, která byla zmíněna výše) a pro sestavení dotazu použít malou pomocnou funkci, která je vzhledem ke zvláštnostem mysql vhodná jak pro INSERT, tak pro AKTUALIZOVANÉ dotazy:

funkce pdoSet ($allowed , & $values ​​​​, $source = array()) (
$set = "" ;
$hodnoty = pole();
if (! $zdroj ) $zdroj = & $_POST ;
foreach ($povoleno jako $pole) (
if (isset($source [ $pole ])) (
$set .= "`" . str_replace ("`" , "``" , $pole). "`". "=: $pole , " ;
$values ​​​​[ $pole ] = $zdroj [ $pole];
}
}
return substr ($set, 0, - 2);
}

V souladu s tím bude kód pro vložení

$allowed = array("jméno" , "příjmení" , "e-mail" ); // povolená pole
$sql = "VLOŽTE DO SADA uživatelů" . pdoSet ($povoleno, $hodnoty);
$stm = $dbh -> připravit ($sql );
$stm -> vykonat ($values);

A pro aktualizaci - toto:

$allowed = array("jméno" , "příjmení" , "e-mail" , "heslo" ); // povolená pole
$_POST ["heslo" ] = MD5 ($_POST [ "přihlášení" ]. $_POST [ "heslo" ]);
$sql = "AKTUALIZOVAT NASTAVENÍ uživatelů " . pdoSet ($povoleno, $hodnoty). "KDE id = :id" ;
$stm = $dbh -> připravit ($sql );
$values ​​​​["id" ] = $_POST ["id" ];
$stm -> vykonat ($values);

Ne příliš působivé, ale velmi účinné. Dovolte mi, abych vám mimochodem připomněl, že pokud používáte Class pro bezpečnou a pohodlnou práci s MySQL, pak se to všechno děje ve dvou řádcích.

CHOP a klíčová slova
Zde nelze vymyslet nic jiného než filtrování. Proto je hloupé spouštět všechny operátory, které nejsou přímo uvedeny v požadavku, prostřednictvím bílé listiny:

$dirs = array("ASC" , "DESC" );
$key = array_search($_GET["dir"], $dirs));
$dir = $objednávky [ $klíč ];
$sql = "VYBRAT * Z "tabulky" ORDER BY$pole $dir ";

V tomto posledním článku se podíváme na to, jaké jsou připravené dotazy, jak zachytit chyby A co jsou transakce v CHOP.

Připravené dotazy

Když spustíme dotaz na databázi, je analyzována a optimalizována, což přirozeně vyžaduje čas. Pokud máme mnoho složitých dotazů, může jejich dokončení trvat velmi dlouho. Pomocí stejného připravené dotazy, to se provede jednou a pak můžeme náš dotaz použít tolikrát, kolikrát chceme. Také nepotřebujeme unikat parametry, protože databázový ovladač udělá všechno sám. Podívejme se, jak je používat.

$stmt = $db->prepare("VLOŽTE DO Článků (název, text) HODNOTY (:název, :text)");
$stmt->bindParam(":title", $title);
$stmt->bindParam(":text", $text);



$stmt->execute();



$stmt->execute();

Abychom žádost připravili, zapíšeme ji do metody připravit, kde místo hodnot označujeme řádek takto: ":Název". V metodě bindParam uvedeme, ke kterému řádku se mají připojit jaká data. V našem případě na čáru :titul data z proměnné jsou vázána $title a na čáru :text- data z proměnné $text. Chcete-li provést požadavek, musíte zavolat metodu vykonat. Takové parametry se nazývají jmenoval, teď se podívejme bezejmený.

$stmt = $db->prepare("VLOŽTE DO článků (nadpis, text) HODNOTY (?, ?)");
$stmt->bindParam(1, $title);
$stmt->bindParam(2, $text);

$title = "(!JAZYK:název článku 1";!}
$text = "Nějaký text pro první článek";
$stmt->execute();

$title = "(!JAZYK:název článku 2";!}
$text = "Nějaký text pro druhý článek";
$stmt->execute();

Všechno je zde identické, až na to, že místo čáry :Název je uveden otazník a v metodě bindParamčíslo 1 prostředek První otazník a číslo 2 - druhý otazník. Použijte metodu, která se vám nejvíce líbí.

Chytání chyb

K zachycení chyb používáme konstrukci, která je nám již známá Zkus chytit a třída Výjimka PDO.

Snaž se (
$db = new PDO("myql:host=$host;dbname=$dbname", $user, $pass);
) catch(PDOException $e) (
echo "Máte chybu: ".$e->getMessage()."
";
echo "On line: ".$e->getLine();
}

Jako příklad jsem udělal chybu a napsal myql, ale ne mysql. Tato chyba bude zachycena a ukáže se nám její text a na kterém řádku k chybě došlo.

Transakce

uvažujme transakce hned s příkladem.

Snaž se (
$db = new PDO("mysql:host=$host;dbname=$dbname", $user, $pass);
$db->beginTransaction();

$stmt = $db->exec("INSERT INTO `articles`(`title`) VALUES("title1")");
$stmt = $db->exec("INSERT INTO `články`(`title`) VALUES("title2")");
exit("chyba");

$stmt = $db->exec("INSERT INTO `články`(`title`) VALUES("title3")");
$db->commit();

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

začítTransakce znamená, že zahajujeme transakci. Spáchat potvrzuje změny a vrátit zpět vše zruší.

Podstatou transakcí je, že buď děláme všechno, nebo neděláme nic. V našem příkladu vkládáme do tabulky články hodnoty titul1, titul2, titul 3. Ale po vložení druhé hodnoty jsme simulovali chybu zastavením používání skriptu výstup. Pokud bychom nepoužili transakce, pak máme první dva titul byl by vložen, ale poslední nikoli. V našem příkladu to není podstatné, ale existují případy, kdy to může vést k vážným selháním aplikace. Abychom tomu zabránili, používáme transakce, kde metoda vrátit zpět vrátí vše do původní podoby a naše první dva titul se také nevloží, a pokud vše proběhlo v pořádku, bez chyb, tak metoda spáchat potvrdí změny a všechny tři titul bude úspěšně vložen.

Závěr

Takže v našich třech článcích věnovaných učení PDO, probrali jsme vše, co potřebujete k snadnému používání tohoto rozhraní. Myslím, že chápete jak CHOP usnadňuje nám život a využijete to ve svých projektech. Hodně štěstí!