<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"><channel><title>Albi's Jogger - z pamiętnika młodego programisty</title><link>http://blog.albitos.eu/</link><description>Wpisy z dziennika internetowego Jogger, wspomaganego przez Jabbera</description><lastBuildDate>Sun, 05 Feb 2012 05:39:29 +0100</lastBuildDate><generator>JoggerPL</generator><item><title>Generowanie n rekordów w Oracle</title><link>http://blog.albitos.eu/2011/10/26/generowanie-n-rekordow-w-oracle/</link><description>&lt;p&gt;Przydatna sztuczka - generuje n rekordów z liczbami od 1 do n. Potrzebowałem tego w pracy w celu wyświetlenia nagłówków w Jasper Reports gdy nie istnieją rekordy w grupie, a jednak mimo to chcemy mieć nagłówek. &lt;code&gt;SELECT rownum FROM DUAL CONNECT BY ROWNUM &amp;lt; 1000&lt;/code&gt;&lt;/p&gt;
</description><pubDate>Wed, 26 Oct 2011 13:39:29 +0200</pubDate><guid>http://blog.albitos.eu/2011/10/26/generowanie-n-rekordow-w-oracle/</guid><category>Wszystkie</category></item><item><title>Kurs PDO - podpinanie parametrów cz.2</title><link>http://blog.albitos.eu/2009/02/22/kurs-pdo-podpinanie-parametrow-cz-2/</link><description>&lt;p&gt;Witam wszystkich po dłuższej przerwie spowodowanej głównie moim lenistwem ;). Inaczej nie da się wytłumaczyć tego, że przez dwa tygodnie wolnego (ferie) nie napisałem nic na blogu. Dzisiaj jednak zamierzam dodać kolejny artykuł do serii na temat PDO. Z tego wpisu dowiecie się jak za pomocą podpinania zmiennych do kolumn pobierać dane z bazy.&lt;/p&gt;
&lt;p&gt;Wszystkie dane pobrane z bazy zawsze znajdują się w obiekcie klasy PDOStatement. Dlatego musimy przekazać mu informację o tym, do jakich zmiennych mają trafiać. Aby to osiągnąć wykorzystamy poznany przez nas już wcześniej mechanizm - FETCH_MODE. By to zrobić cel mamy dwie drogi:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Przekazanie stałej PDO::FETCH_BOUND do metody PDOStatement::fetch() (lub PDOStatement::fetchAll())&lt;/li&gt;
&lt;li&gt;Przekazanie stałej PDO::FETCH_BOUND do metody PDOStatement::setFetchMode()&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Ponadto, podobnie jak w przypadku podpinania parametrów do zapytania mamy dwa sposoby identyfikowania kolumn - za pomocą nazwy oraz przez numer porządkowy kolumny. W pierwszym przypadku podajemy nazwę kolumny zwracaną przez bazę, w drugim natomiast jej kolejność. &lt;strong&gt;Należy jedynie pamiętać, że kolejne kolumny liczone są od jedynki.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;W przypadku wywołania PDOStatement::fetch(PDO::FETCH_BOUND) podpięcie kolumn zastosowane zostanie jedynie do aktualnego wywołania metody PDOStatement::fetch(). Czasami jednak pozwala to skrócić zapis o niepotrzebne wywołanie PDOStatement::setFetchMode() - zazwyczaj gdy rekordy wyciągane są z obiektu tylko raz.&lt;/p&gt;
&lt;p&gt;{geshi lang=php} $players = $pdo-&amp;gt;query('SELECT id, user, ip FROM players'); $players-&amp;gt;bindColumn(1, $id); //indeksowanie numeryczne od jedynki $players-&amp;gt;bindColumn(2, $user); $players-&amp;gt;bindColumn('ip', $ip); //indeksowanie za pomocą nazy kolumny while ($players-&amp;gt;fetch(PDO::FETCH_BOUND)) //wartość zwracana to true/false { echo $id; echo $user; } {/geshi}&lt;/p&gt;
&lt;p&gt;W prezentowanym powyżej przypadku dane trafiają tylko i wyłącznie do podpiętych zmiennych. Metoda PDOStatement::fetch(PDO::FETCH_BOUND) zwraca jedynie wartość true/false do określenia, czy zostały pobrane wszystkie rekordy. Ponadto zastosowaliśmy dwie metody indentyfikowania kolumn.&lt;/p&gt;
&lt;p&gt;Drugi sposób jest bardziej uniwersalny, jednak zajmuje minimalnie więcej kodu (osobiście jestem minimalistą i nie lubię jak mi się zbytnio po ekranie rozłazi ;)):&lt;/p&gt;
&lt;p&gt;{geshi lang=php} $players = $pdo-&amp;gt;query('SELECT id, user, ip FROM players'); $players-&amp;gt;bindColumn(1, $id); //indeksowanie numeryczne od jedynki $players-&amp;gt;bindColumn(2, $user); $players-&amp;gt;bindColumn('ip', $ip); //indeksowanie za pomocą nazy kolumny $players-&amp;gt;setFetchMode(PDO::FETCH_BOUND); while ($players-&amp;gt;fetch()) //wartość zwracana to true/false { echo $id; echo $user; } {/geshi}&lt;/p&gt;
&lt;p&gt;Od tej pory dla określonego obiektu klasy PDOStatement stale obowiązuje ustawienie PDO::FETCH_BOUND. Kiedy możemy to wykorzystać? Najszybciej na myśl przychodzi mi połączenie z podpinaniem parametrów:&lt;/p&gt;
&lt;p&gt;{geshi lang=php} $players = $pdo-&amp;gt;prepare('SELECT id, user, ip FROM players WHERE pass = ?'); $players-&amp;gt;bindColumn(1, $id); //indeksowanie numeryczne od jedynki $players-&amp;gt;bindColumn(2, $user); $players-&amp;gt;bindColumn('ip', $ip); //indeksowanie za pomocą nazy kolumny $players-&amp;gt;bindParam(1, $pass); $players-&amp;gt;setFetchMode(PDO::FETCH_BOUND); $players-&amp;gt;execute(array('x')); while ($players-&amp;gt;fetch()) //wartość zwracana to true/false { echo $id; echo $user; } $players-&amp;gt;execute(array('y')); while ($players-&amp;gt;fetch()) //wartość zwracana to true/false { echo $id; echo $user; } $players-&amp;gt;execute(array('z')); while ($players-&amp;gt;fetch()) //wartość zwracana to true/false { echo $id; echo $user; } {/geshi}&lt;/p&gt;
&lt;p&gt;Oczywiście zaprezentowany przeze mnie przykład jest nieco bezużyteczny, gdyż dałoby się to pobrać za pomocą zwykłego OR, jednak załóżmy że nie jest to bezsensowne i dobrze ilustruje to, co chcemy zrobić ;).&lt;/p&gt;
&lt;p&gt;To już wszystko co chciałem dzisiaj pokazać. Wkrótce pojawi się na tym blogu nieco więcej - moje długoterminowe plany zmian wkrótce wejdą w życie :).&lt;/p&gt;
</description><pubDate>Sun, 22 Feb 2009 15:20:39 +0100</pubDate><guid>http://blog.albitos.eu/2009/02/22/kurs-pdo-podpinanie-parametrow-cz-2/</guid><category>(x)HTML/CSS</category><category>PHP/MySQL</category><category>Techblog</category><category>Wszystkie</category><category>php mysql programowanie pdo</category></item><item><title>Kurs PDO - podpinanie parametrów cz.1</title><link>http://blog.albitos.eu/2008/12/26/kurs-pdo-podpinanie-parametrow-cz-1/</link><description>&lt;p&gt;Dzisiejszy wpis będzie obejmował tematykę znaną już z serii na temat ADOdb. Dowiecie się w jaki sposób realizować podpinanie parametrów w PDO oraz na czym polegają różnice między obydwiema bibliotekami. Dla tych, którzy nie wiedzą co to jest, przedstawię także zasadę działania oraz powody dla których używa się tej funkcjonalności. Warto jedynie wspomnieć, że PDO obsługuje znacznie więcej możliwości związanych z podpinaniem parametrów.&lt;/p&gt;
&lt;h3&gt;Dlaczego stosować?&lt;/h3&gt;
&lt;p&gt;Podpinanie parametrów ma bardzo wiele zalet nad zwyczajnym filtrowaniem danych i podklejaniem ich do zapytań. Jedną z najważniejszych jest czytelność. Dzięki odpowiednim identyfikatorom wiemy, która zmienna pod jakie miejsce w zapytaniu trafia. Nie musimy się bawić w łączenie długich ciągów znaków, rzutowanie typów i setki filtrów, PDO zrobi to za nas samo. Osobiście znam pewną osobę która po prostu gubi się w tych wszystkich apostrofach gdy nadchodzi potrzeba dołączenia kilku zmiennych do zapytania, nawet bez filtrowania zmiennych!&lt;/p&gt;
&lt;p&gt;Pomimo tego najważniejszą zaletą takiego działania jest zabezpieczenie przed ataki typu &lt;a href=&quot;http://albi.vxe.pl/2007/02/26/sql-injection/&quot;&gt;SQL Injection&lt;/a&gt;. Dane które wstawiamy do zapytań zawsze są filtrowane pod względem znaków niebezpiecznych dla bazy danych której używamy, ponadto PDO bierze pod uwagę typ danych który wysyłamy (jeżeli podamy jaki to typ).&lt;/p&gt;
&lt;h3&gt;Jak tego używać?&lt;/h3&gt;
&lt;p&gt;Jak dobrze dobrze zapewne pamiętacie (a jeżeli nie, to polecam ich ponowną lekturę) z poprzednich wpisów, wysyłanie zapytania pobierającego dane w PDO składa się z dwóch etapów:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Przekazaniu zapytania do PDO::query()&lt;/li&gt;
&lt;li&gt;Pobranie danych przy pomocy zwróconego nam obiektu klasy PDOStatement&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;W przypadku podpinania parametrów także użyjemy klasy PDOStatement, jednak tym razem cała operacja będzie nieco bardziej skomplikowana. Pozwala to na zwiększenie możliwości, jednak znacznie zmniejsza wygodę użytkowania. Nic nie stoi na przeszkodzie, aby napisać sobie niewielką nakładkę dla ułatwienia niektórych operacji. Zapoznajmy się w takim razie z kolejnymi krokami, jakie należy wykonać:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Przygotowanie zapytania przy pomocy PDO::prepare()&lt;/li&gt;
&lt;li&gt;Podpięcie parametrów przy pomocy obiektu klasy PDOStatement&lt;/li&gt;
&lt;li&gt;Wykonanie zapytania przy pomocy PDOStatement::execute()&lt;/li&gt;
&lt;li&gt;Pobranie danych z obiektu klasy PDOStatement()&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;PDO pozwala na podpinanie parametrów na dwa sposoby. Przed wykonaniem zapytania, przy pomocy metody PDOStatement::bindValue(), lub podczas wykonywania zapytania metodą PDOStatement::execute(). Ponadto biblioteka obsługuje dwa sposoby identyfikacji parametrów. Przy pomocy liczb oraz nazw.&lt;/p&gt;
&lt;h3&gt;PDO::bindValue()&lt;/h3&gt;
&lt;p&gt;W przypadku podpinania danych poprzez PDO::bindValue() uzyskujemy możliwość dokładnego określenia rodzaju danych, które wysyłamy do zapytania. Dokonujemy tego podczas przypisywania kolejnych zmiennych do identyfikatorów/liczb. Kilka przykładów:&lt;/p&gt;
&lt;p&gt;{geshi lang=php} $stmt = $db-&amp;gt;prepare('SELECT * FROM users WHERE id = ? AND password = ?'); $stmt -&amp;gt; bindValue(0, $_SESSION['user_id'], PDO::PARAM_INT); //Podpinamy zmienną $_SESSION['user_id'] do pierwszego znaku zapytania jako liczbę $stmt -&amp;gt; bindValue(1, $_SESSION['password'], PDO::PARAM_STR, 32); //Podpinamy zmienną $_SESSION['password'] zamiast drugiego znaku zapytania jako 32 literowy ciąg znaków $stmt-&amp;gt;execute(); {/geshi}&lt;/p&gt;
&lt;p&gt;Przypadek z numerycznym umieszczaniem parametrów (ang. placeholders). Każdy parametr posiada swój numer według kolejności występowania znaków zapytania. Liczenie zaczynamy od jedynki (w przypadku używania metody PDOStatement::bindValue()).&lt;/p&gt;
&lt;p&gt;{geshi lang=php} $stmt = $db-&amp;gt;prepare('SELECT * FROM users WHERE id = :user_id AND password = :user_pass'); $stmt -&amp;gt; bindValue(':user_id', $_SESSION['user_id'], PDO::PARAM_INT); //Podpinamy zmienną $_SESSION['user_id'] do parametru o nazwie :user_id jako liczbę $stmt -&amp;gt; bindValue(':user_pass', $_SESSION['password'], PDO::PARAM_STR, 32); //Podpinamy zmienną $_SESSION['password'] zamiast identyfikatora :user_pass jako 32 literowy ciąg znaków $stmt-&amp;gt;execute(); {/geshi}&lt;/p&gt;
&lt;p&gt;Przypadek z nazwami jako identyfikatory parametrów (ang. named parameters). Każdy parametr posiada swoją własną nazwę według której podpinane są wartości.&lt;/p&gt;
&lt;p&gt;Warto wspomnieć jeszcze jednej funkcji do popinania parametrów - PDOStatement::bindParam(). Jedyna różnica w stosunku do PDOStatement::bindValue() jest taka, że zmienne przekazane jako parametry podpinane są przez referencję, co umożliwia wykonanie kilki podobnych zapytań zaraz po sobie, podobnie jak robiliśmy to w przypadku ADOdb. Wystarczy, że zmienimy wartość umieszczoną w zmiennej podpiętej do zapytania i ponownie wykonamy metodę execute().&lt;/p&gt;
&lt;p&gt;{geshi lang=php} $user = 'Klaus'; $players = $pdo -&amp;gt; prepare('SELECT * FROM players WHERE user = ?'); $players -&amp;gt; bindParam(1, $user); $players -&amp;gt; execute(); $player = $players -&amp;gt; fetch(); echo $player['email'].'&lt;br&gt;
'; $players -&amp;gt; closeCursor(); $user = 'PQA'; $players -&amp;gt; execute(); $player = $players -&amp;gt; fetch(); echo $player['email'].'&lt;br&gt;
'; $players -&amp;gt; closeCursor(); $user = 'sss'; $players -&amp;gt; execute(); $player = $players -&amp;gt; fetch(); echo $player['email'].'&lt;br&gt;
'; $players -&amp;gt; closeCursor(); {/geshi}&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h3&gt;Przekazywanie parametrów przy PDOStatement::execute()&lt;/h3&gt;
&lt;p&gt;Innym sposobem na umieszczenie wartości w zapytaniu jest podanie ich tablicy do metody PDOStatement::execute(). Jej indeksowanie zależy od wybranego przez nas sposobu identyfikowania parametrów. W przypadku parametrów z nazwami, używamy ich podobnie jak przy PDOStatement::bindValue(). Jeżeli natomiast numerujemy parametry, to ich indeks numeryczny w tablicy będzie odpowiadał kolejnym znakom zapytania.&lt;/p&gt;
&lt;p&gt;{geshi lang=php} $stmt = $db-&amp;gt;prepare('SELECT * FROM users WHERE id = :user_id AND password = :user_pass'); $stmt-&amp;gt;execute(array( ':user_id' =&amp;gt; $_SESSION['user_id'], ':user_pass' =&amp;gt; $_SESSION['password'] )); {/geshi}&lt;/p&gt;
&lt;p&gt;Przypadek z nazwami jako identyfikatorami. Każdej nazwie podstawiana jest odpowiednia warość z tablicy przekazanej do PDOStatement::execute() o kluczu zależnym od identyfikatora parametru.&lt;/p&gt;
&lt;p&gt;{geshi lang=php} $stmt = $db-&amp;gt;prepare('SELECT * FROM users WHERE id = ? AND password = ?'); $stmt-&amp;gt;execute(array($_SESSION['user_id'], $_SESSION['password'])); {/geshi}&lt;/p&gt;
&lt;p&gt;Przypadek ze znakami zapytania. Tym razem nie musimy podawać indeksów dla tablicy, ponieważ jest ona i tak domyślnie numerowana od zera. Osobiście używam właśnie tego sposobu ze względu na zwięzłość zapisu.&lt;/p&gt;
&lt;p&gt;Dalej dane pobieramy już tak jak zwykle, przy pomocy metod PDOStatement::fetch(), PDOStatement::fetchAll() lub PDOStatement::fetchColumn(). Warto jedynie pamiętać, że PDOStatement zwraca jedynie wartość typu bool, która zawiera informację o powodzeniu wykonania zapytania. Wszelkie dane pobrane z bazy znajdują się nadal w obiekcie klasy PDOStatement na którym wykonaliśmy metodę execute().&lt;/p&gt;
&lt;p&gt;{geshi lang=php} $stmt = $db-&amp;gt;prepare('SELECT * FROM users WHERE id = ? AND password = ?'); $stmt-&amp;gt;execute(array($_SESSION['user_id'], $_SESSION['password'])); foreach($stmt as $user) { echo $user['login'].'&lt;br&gt;
'; } {/geshi}&lt;/p&gt;
&lt;h3&gt;Zakończenie&lt;/h3&gt;
&lt;p&gt;To już wszystko co chciałem przedstawić w dzisiejszym wpisie. Następnym razem dowiemy się, w jaki sposób przy pomocy podpinania kolumn do zmiennych pobierać dane z bazy. Jeszcze tylko pytanie do czytelników: czy wpisy z serii na temat PDO są dla was przydatne? Jeżeli czegoś im brakuje, bardzo proszę o jakiś komentarz, chciałbym aby były one możliwie najlepszym źródłem wiedzy dla początkujących.&lt;/p&gt;
</description><pubDate>Fri, 26 Dec 2008 16:26:51 +0100</pubDate><guid>http://blog.albitos.eu/2008/12/26/kurs-pdo-podpinanie-parametrow-cz-1/</guid><category>PHP/MySQL</category><category>Techblog</category><category>Wszystkie</category><category>php mysql programowanie pdo</category></item><item><title>Zwracanie wartości przy include()?</title><link>http://blog.albitos.eu/2008/11/28/zwracanie-wartosci-przy-include/</link><description>&lt;p&gt;Dzisiaj spotkałem się z bardzo ciekawym rozwiązaniem o którym wcześniej nie wiedziałem, dlatego postanowiłem podzielić się nim z innymi czytelnikami. Jednocześnie przepraszam za moją dość długą nieobecność i obiecuję poprawę w najbliższym czasie.&lt;/p&gt;
&lt;p&gt;Wracając do tematu, czy wiecie że możliwe jest zwracanie wartości podczas wykonywania pliku PHP załadowanego przy &lt;a href=&quot;http://www.php.net/manual/en/function.include.php&quot;&gt;include&lt;/a&gt;/&lt;a href=&quot;http://www.php.net/manual/en/function.require.php&quot;&gt;require&lt;/a&gt;? Ciekaw jestem, ilu z was to wiedziało... Przykładowe kody wyglądają tak:&lt;/p&gt;
&lt;h4&gt;Przykład 1&lt;/h4&gt;
&lt;p&gt;file.php&lt;/p&gt;
&lt;p&gt;{geshi lang=php} &lt;?php return array('asd'); ?&gt; {/geshi}&lt;/p&gt;
&lt;p&gt;file2.php&lt;/p&gt;
&lt;p&gt;{geshi lang=php} &lt;?php
$array = include('file.php');
echo $array[0];
?&gt; {/geshi}&lt;/p&gt;
&lt;h4&gt;Przykład 2&lt;/h4&gt;
&lt;p&gt;configuration.php&lt;/p&gt;
&lt;p&gt;{geshi lang=php} &lt;?php
$config['webhost'] = 'http://localhost/';
$config['dbhost'] = 'localhost';
$config['dbuser'] = 'root';
$config['dbpass'] = 'password';
$config['dbname'] = 'database';
return $config;
?&gt; {/geshi}&lt;/p&gt;
&lt;p&gt;index.php&lt;/p&gt;
&lt;p&gt;{geshi lang=php} &lt;?php
$data = require_once('config.php');
mysql_connect($data['dbhost'], $data['dbuser'], $data['dbpass']);
mysql_select_db($data['dbname']);
?&gt; {/geshi}&lt;/p&gt;
&lt;p&gt;Ciekaw jestem ilu z was wiedziało o takiej możliwości. Czy tylko ja czytam niedokładnie manual? Warto czytać to wszystko od deski do deski? Może więcej takich ciekawych funkcji udałoby się wyłapać... Jak sądzicie? Czekam na komentarze.&lt;/p&gt;
&lt;p&gt;Źródło: &lt;a href=&quot;http://www.urdalen.com/blog/?p=257&quot;&gt;Kurt Urdalen's Blog&lt;/a&gt;&lt;/p&gt;
</description><pubDate>Fri, 28 Nov 2008 19:38:57 +0100</pubDate><guid>http://blog.albitos.eu/2008/11/28/zwracanie-wartosci-przy-include/</guid><category>PHP/MySQL</category><category>Techblog</category><category>Wszystkie</category><category>programowanie ciekawostki php</category></item><item><title>FETCH_ASSOC vs FETCH_NUM</title><link>http://blog.albitos.eu/2008/10/06/fetch-assoc-vs-fetch-num/</link><description>&lt;p&gt;Jak zapewne część z was wie (albo i nie) pracuję obecnie nad projektem zwanym Orodlin. W tymże właśnie zespole, ktoś niesamowicie genialny wpadł na pomysł używania numerycznego pobierania pól przy pomocy ADOdb (wszystko co w tym poście zostanie napisane, odnosi się także do PDO oraz mysql_fetch_num()). Istnieje pogląd, że numeryczne pobieranie pól jest szybsze...&lt;/p&gt;
&lt;p&gt;W porządku. Mogę zrozumieć pewne względy wydajności przy pisaniu skryptów. Jednak nie potrafię znieść przedkładania wydajności kodu całkowicie ponad jego czytelność oraz elastyczność. Całą sytuację postaram się zobrazować na przykładzie jednego prostego kawałka kodu (przepisany na PDO dla lepszej czytelności):&lt;/p&gt;
&lt;p&gt;{geshi lang=php} $players = $pdo -&amp;gt; query('SELECT id, user, email, pass, tribe, tribe_rank, class, race FROM players'); $players -&amp;gt; setFetchMode(PDO::FETCH_NUM); foreach($players as $player) { echo 'ID:'.$player[0].' Imię: '.$player[1].' Rasa: '.$player[7].' Klasa: '.$player[6]; } {/geshi}&lt;/p&gt;
&lt;p&gt;Kod oczywiście działa i ma się świetnie... Moim zadaniem w tym miejscu była prosta zmiana - wyrzucenie pól odnośnie klanów z zapytania (tribe, tribe_rank) ponieważ pola te nie znajdowały się już w bazie (całkowite przepisanie systemu klanowego). Niestety, pola pobrane numerycznie z tego zapytania wykorzystywane były w kilku miejscach poniżej. Zmiana indeksów w każdym z tych miejsc całkowicie nie wchodziła w grę. W tym momencie wszedł brzydki-hack-tm, czyli pobieranie zer na miejsce usuniętych pól.&lt;/p&gt;
&lt;p&gt;Do czego doprowadza taki styl kodowania? Jako ciekawostkę zobaczcie sobie skrypt poniżej ;)&lt;/p&gt;
&lt;p&gt;{geshi lang=php} if ($arrPlayers[$i][2] == 'Member') { if ($arrPlayers[$i][6] == 'F') { $arrRankImages['Member'] = 'f_member'; } if ($arrPlayers[$i][6] == 'M') { $arrRankImages['Member'] = 'm_member'; } } $playerName = Player::getTaggedPlayerName($arrPlayers[$i][0]); //id $arrPlayers2[$i]['id'] = $arrPlayers[$i][0]; //name $arrPlayers2[$i]['name'] = $playerName; //opis $arrPlayers2[$i]['opis'] = $arrPlayers[$i][5]; //rankIcon $arrPlayers2[$i]['rankIcon'] = $rankIcon; //rankName $arrPlayers2[$i]['rankName'] = $rankName; //reputation $arrPlayers2[$i]['reputation'] = (empty($arrPlayers[$i][7])) ? 0 : $arrPlayers[$i][7]; //place $arrPlayers2[$i]['place'] = $arrPlayers[$i][9]; //rasa $arrPlayers2[$i]['rasa'] = $arrPlayers[$i][10]; //hp $arrPlayers2[$i]['hp'] = ($arrPlayers[$i][11] &amp;gt; 0)? 1 : 0; //gender $arrPlayers2[$i]['gender'] = $arrPlayers[$i][6]; //avatar $arrPlayers2[$i]['avatar'] = $arrPlayers[$i][12]; {/geshi}&lt;/p&gt;
&lt;p&gt;No przepraszam, za takie kwiatki to ja dziękuję... Totalnie nieczytelny kod, gdyby nie komentarze, pozostałoby mi się jedynie pochlastać.&lt;/p&gt;
&lt;p&gt;EDIT:&lt;/p&gt;
&lt;p&gt;Jeszcze jedna sytuacja, która przypomniała mi się dopiero po publikacji wpisu - nasz kod obecnie używa mieszanych typów. Dlatego praktycznie w każdym miejscu dochodzi taki kwiatek:&lt;/p&gt;
&lt;p&gt;{geshi lang=php} $oldFetchMode = $db -&amp;gt; SetFetchMode(ADODB_FETCH_NUM); // TUTAJ KOD KORZYSTAJACY Z FETCHA KTOREGO TY LUBISZ $db -&amp;gt; SetFetchMode($oldFetchMode); {/geshi}&lt;/p&gt;
&lt;p&gt;No i gdzie tu sens?&lt;/p&gt;
&lt;p&gt;Jak jest z wami? Spotkaliście się kiedyś z podobnym wykorzystaniem tej opcji w skryptach? Do czego używanie mysql_fetch_num/PDO::FETCH_NUM? A może ta opcja jest całkowicie bezużyteczna? Czekam na wasze opinie.&lt;/p&gt;
</description><pubDate>Mon, 06 Oct 2008 19:54:18 +0200</pubDate><guid>http://blog.albitos.eu/2008/10/06/fetch-assoc-vs-fetch-num/</guid><category>PHP/MySQL</category><category>Techblog</category><category>Wszystkie</category><category>php mysql programowanie</category></item><item><title>Kurs PDO - CRUD (Create, Retrieve, Update, Delete)</title><link>http://blog.albitos.eu/2008/09/29/kurs-pdo-crud-create-retrieve-update-delete/</link><description>&lt;p&gt;W dzisiejszym wpisie zamierzam kontynuować rozpoczęty ostatnio kurs PDO. Tym razem nauczymy się podstaw wstawiania, usuwania, pobierania i aktualizacji rekordów w bazie danych. Razem wszystkie te operacje nazywane są często CRUD (z angielskiego Create-Retrive-Update-Delete).&lt;/p&gt;
&lt;p&gt;W przypadku dawnego sposobu wykonywania zapytań używanego w PHP, jedna funkcja (mysql_query) służyła do obsłużenia wszystkich ich rodzajów. W przypadku PDO pobieranie jest potraktowane w sposób szczególny, natomiast pozostałe zapytania wykonujemy przy pomocy jednej funkcji.&lt;/p&gt;
&lt;h3&gt;Pobieranie danych&lt;/h3&gt;
&lt;p&gt;W poprzedniej części nauczyliśmy się pobierać dane z bazy danych przy pomocy metody PDO::query() oraz klasy PDOStatement. Dzisiaj dowiemy się w jaki sposób decydować o sposobie ich umieszczania w wynikowym obiekcie. Służą do tego metody PDOStatement::setFetchMode(). Przy jej pomocy możemy ustawić jeden z poniższych atrybów:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;b&gt;PDO::FETCH_NUM&lt;/b&gt; - pobieranie numeryczne. Kluczami dla kolejnów pól w rekordach są liczby naturalne. Tak więc pole pobrane jako &lt;i&gt;1&lt;/i&gt; będzie miało indeks &lt;i&gt;0&lt;/i&gt; a każde następne o jeden większy.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;{geshi lang=php} $players = $pdo-&amp;gt;query('SELECT * FROM players'); $players-&amp;gt;setFetchMode(PDO::FETCH_NUM); print_r($players-&amp;gt;fetch()); {/geshi}&lt;/p&gt;
&lt;pre&gt;
Array
(
    [0] =&amp;gt; 7399
    [1] =&amp;gt; Klaus Korner
    [2] =&amp;gt; albi@jabster.pl
)
&lt;/pre&gt;
&lt;p&gt;&lt;b&gt;PDO::FETCH_ASSOC&lt;/b&gt; - pobieranie asocjacyjne. Kluczami są nazwy pobranych kolumn. Tak więc pole &lt;i&gt;`username`&lt;/i&gt; znajdzie się pod kluczem &lt;i&gt;`username`&lt;/i&gt;. Jeżeli w wyniku zapytania znajdą się dwa pola o tej samej nazwie to zwrócone zostanie tylko pierwsze. Bardzo wygodne, jednak nieco wolniejsze (podobno) od numerycznego. Osobiście nagminnie z niego korzystam.&lt;/p&gt;
&lt;p&gt;{geshi lang=php} $players = $pdo-&amp;gt;query('SELECT * FROM players'); $players-&amp;gt;setFetchMode(PDO::FETCH_ASSOC); print_r($players-&amp;gt;fetch()); {/geshi}&lt;/p&gt;
&lt;pre&gt;
Array
(
    [id] =&amp;gt; 7399
    [user] =&amp;gt; Klaus Korner
    [email] =&amp;gt; albi@jabster.pl
)
&lt;/pre&gt;
&lt;p&gt;&lt;b&gt;PDO::FETCH_NAMED&lt;/b&gt; - podobnie jak w przypadku FETCH_ASSOC dane umieszczane są na podstawie nazwy kolumny. Jedyna różnica polega na tym, że w razie wystąpienia wielu wartości o tej samej nazwie pola zwrócona zostanie tablica wszystkich pól o tym indeksie zamiast pierwszego wystąpienia.&lt;/p&gt;
&lt;p&gt;{geshi lang=php} $players = $pdo -&amp;gt; query('SELECT id,user,email,pass as email FROM players'); $players-&amp;gt;setFetchMode(PDO::FETCH_NAMED); print_r($players-&amp;gt;fetch()); {/geshi}&lt;/p&gt;
&lt;pre&gt;
Array
(
    [id] =&amp;gt; 7399
    [user] =&amp;gt; Klaus Korner
    [email] =&amp;gt; Array
        (
            [0] =&amp;gt; albi@jabster.pl
            [1] =&amp;gt; 7815696ecbf1c96e6897b779456d330e
        )

)
&lt;/pre&gt;
&lt;p&gt;W powyższym przykładzie specjalnie zastosowałem małą sztuczkę w zapytaniu, aby zwróciło dwie kolumny o tej samej nazwie. To powinno lepiej zobrazować działanie powyższej opcji.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;PDO::FETCH_BOTH&lt;/b&gt; - połączenie pobierania numerycznego oraz asocjacyjnego. Możliwe jest używanie obydwu typów indeksów, jednak powoduje to podwojenie ilości danych i spowolnienie skryptu. Ponadto podczas iteracji w pętli foreach wszystkie kolumny w rekordach wyświetlane są dwukrotnie. Czasem może być to jednak przydatne.&lt;/p&gt;
&lt;p&gt;{geshi lang=php} $players = $pdo -&amp;gt; query('SELECT id,user,email FROM players'); $players-&amp;gt;setFetchMode(PDO::FETCH_BOTH); print_r($players-&amp;gt;fetch()); {/geshi}&lt;/p&gt;
&lt;pre&gt;
Array
(
    [id] =&amp;gt; 7399
    [0] =&amp;gt; 7399
    [user] =&amp;gt; Klaus Korner
    [1] =&amp;gt; Klaus Korner
    [email] =&amp;gt; albi@jabster.pl
    [2] =&amp;gt; albi@jabster.pl
)
&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;PDO::FETCH_OBJ&lt;/b&gt; - pobiera dane do obiektu. Właściwości takiego obiektu są nazwami pól w bazie.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;{geshi lang=php} $players = $pdo -&amp;gt; query('SELECT id,user,email FROM players'); $players-&amp;gt;setFetchMode(PDO::FETCH_OBJ); print_r($players-&amp;gt;fetch()); {/geshi}&lt;/p&gt;
&lt;pre&gt;
stdClass Object
(
    [id] =&amp;gt; 7399
    [user] =&amp;gt; Klaus Korner
    [email] =&amp;gt; albi@jabster.pl
)
&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;PDO::FETCH_BOUND&lt;/b&gt; - umieszcza dane w odpowiednich zmiennych które poprzednio zostały podpięte poprzez metody PDOStatement::bindParam() oraz PDOStatement::bindColumn(). Dokładniej zostanie omówiony przy wpisie na temat podpinania parametrów.&lt;/li&gt;
&lt;li&gt;PDO::FETCH_COLUMN&lt;/li&gt;
&lt;li&gt;PDO::FETCH_CLASS&lt;/li&gt;
&lt;li&gt;PDO::FETCH_INTO&lt;/li&gt;
&lt;li&gt;PDO::FETCH_FUNC&lt;/li&gt;
&lt;li&gt;PDO::FETCH_GROUP&lt;/li&gt;
&lt;li&gt;PDO::FETCH_UNIQUE&lt;/li&gt;
&lt;li&gt;PDO::FETCH_KEY_PAIR&lt;/li&gt;
&lt;li&gt;PDO::FETCH_CLASSTYPE&lt;/li&gt;
&lt;li&gt;PDO::FETCH_SERIALIZE&lt;/li&gt;
&lt;li&gt;PDO::FETCH_PROPS_LATE&lt;/li&gt;
&lt;li&gt;PDO::FETCH_LAZY&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Tak więc przykładowe zapytanie oraz pobranie danych we wcześniej ustalony sposób powinno wyglądać tak:&lt;/p&gt;
&lt;p&gt;{geshi lang=php} $players = $pdo -&amp;gt; query('SELECT id,user,email FROM players'); $players -&amp;gt; setFetchMode(PDO::FETCH_ASSOC); foreach($players-&amp;gt;fetch() as $key =&amp;gt; $value) { echo $key.' ma wartość '.$value.&quot;\n&quot;; } $players -&amp;gt; closeCursor(); //nie zapominamy zamknąć kursora {/geshi}&lt;/p&gt;
&lt;p&gt;Powyższy skrypt wyświetli rezultat z listingu poniżej. Dzięki zastosowaniu metody PDOStatement::fetch() uzyskaliśmy dostęp do pojedyńczego wiersza zwróconego przez bazę danych. Moglibyśmy także pobrać wszystkie wiersze, jednak wtedy musielibyśmy użyć dwóch pętli aby wyświetlic po kolei każdy wiersz oraz wszystkie pola. Możnaby to zrobić za pomocą PDOStatement::fetchAll() lub używając wbudowanego w PHP mechanizmu iteracji (to coś dla bardziej zaawansowanych, ogółem chodzi o to, że obiekt klasy PDOStatement można &quot;potraktować&quot; pętlą foreach).&lt;/p&gt;
&lt;pre&gt;
id ma wartość 7399
user ma wartość Klaus Korner
email ma wartość albi@jabster.pl
&lt;/pre&gt;
&lt;h3&gt;Usuwanie danych&lt;/h3&gt;
&lt;p&gt;Usuwanie oraz edycja danych przy pomocy PDO nie różni się niczym od wykonania zwykłego zapytania do bazy danych. Ponieważ jednak zapytania pracujące na danych nic nie zwracają, używamy do tego celu metody PDO::exec(). Dzięki temu nie jest tworzony obiekt klasy PDOStatement, co przyspiesza działanie skryptu (po co tworzyć fabrykę, która niczego nie będzie produkować?). Przykładowy kod może wyglądać tak:&lt;/p&gt;
&lt;p&gt;{geshi lang=php} $count = $pdo-&amp;gt;exec('DELETE FROM players'); echo 'Usunięto '.$count.' graczy'; {/geshi}&lt;/p&gt;
&lt;p&gt;Jak widać w naszym kodzie, metoda ta zwraca ilość zmodyfikowanych/usuniętych/dodanych pól.&lt;/p&gt;
&lt;p&gt;To już wszystko co musicie wiedzieć na temat podstawowych operacji przy pomocy PDO. W dalszej części tego kursu omówię technikę, ktorą poznaliście przy okazji kursu ADOdb - param binding. Oprócz tego będzie nieco na temat innych użytecznych metod.&lt;/p&gt;
</description><pubDate>Mon, 29 Sep 2008 16:19:30 +0200</pubDate><guid>http://blog.albitos.eu/2008/09/29/kurs-pdo-crud-create-retrieve-update-delete/</guid><category>PHP/MySQL</category><category>Techblog</category><category>Wszystkie</category><category>php pdo programowanie</category></item><item><title>Kurs PDO - wprowadzenie</title><link>http://blog.albitos.eu/2008/09/22/kurs-pdo-wprowadzenie/</link><description>&lt;p&gt;Tak jak zapowiadałem, w dzisiejszym wpisie zajmiemy się biblioteką PDO. Przy jej pomocy można w bardzo szybki i wygodny sposób pobrać dane z wielu popularnych baz danych (MSSQL, Firebird, MySQL, Informix, Oracle, ODBC, DB2, SQLite, PostgreSQL). Większość operacji poznanych przez nas wcześniej przy ADOdb możliwe jest do wykonania wzykorzystując jej możliwości, przy jednoczesnym znacznym przyspieszeniu i większej wygodzie użytkowania.&lt;/p&gt;
&lt;h3&gt;Dlaczego PDO?&lt;/h3&gt;
&lt;p&gt;PDO (PHP Data Objects) jest biblioteką która ma za zadanie wprowadzić jednolity sposób dostępu do baz danych. Poprzednie rozwiązanie było bardzo niedoskonałe. Nazwy funkcji dla każdej bazy były inne (mysq_connect, pg_connect), a możliwości dość mocno ograniczone (brak bindowania parametrów, zwracania całej tablicy czy obsługi wyjątków).&lt;/p&gt;
&lt;p&gt;Obecnie problem ten rozwiązuje PDO, które jest dostępne domyślnie od PHP 5.1. Dostęp do każdej bazy danych jest realizowany przy pomocy tych samych funkcji i klas (typ bazy pobierany jest jedynie z konfiguracji), SQL Injection przestaje być problemem, a czas wykonywania jest znacznie mniejszy niż u konkurencyjnego ADOdb czy Creole.&lt;/p&gt;
&lt;h3&gt;Zaczynamy pracę - połączenie z bazą&lt;/h3&gt;
&lt;p&gt;Największą różnicą w tym miejscu w stosunku do ADOdb będzie wykorzystanie bloku try-catch do obsługi wyjątków. Dzięki temu uzyskamy dokładne informacje odnośnie błędu w razie niepowodzenia i będziemy mogli odpowiednio go obsłużyć (na przykład wyświetlić stronę z przeprosinami).&lt;/p&gt;
&lt;p&gt;Parametry bazy danych podajemy do PDO podczas tworzenia obiektu klasy PDO służącego do obsługi połączenia. Aby to zrobić musimy przekazać do konstruktora specjalny ciąg znaków zwany DSN. Za jego pomocą określamy rodzaj sterownika bazy, jej nazwę oraz host wraz z portem. Nazwę użytkownika oraz hasło podajemy kolejno w drugim i trzecim parametrze. Możliwe jest także podanie pliku w którym znajduje się ciąg znaków DSN. Ostatnia opcja to zdefiniowanie tych danych w pliku php.ini i podanie nazwy dyrektywy konfiguracyjnej zamiast DSN.&lt;/p&gt;
&lt;p&gt;{geshi lang=php} try { $pdo = new PDO('mysql:host=localhost;dbname=jakasnazwa', 'root', 'root'); echo 'Nawiązałem połączenie'; } catch(PDOException $e) { echo 'Błąd:'.$e-&amp;gt;getMessage(); } {/geshi}&lt;/p&gt;
&lt;p&gt;Użyty zostanie DSN z parametru.&lt;/p&gt;
&lt;p&gt;{geshi lang=php} try { $pdo = new PDO('uri:file:///www/account/path/to/dsn', 'root', 'root'); echo 'Nawiązałem połączenie'; } catch(PDOException $e) { echo 'Błąd:'.$e-&amp;gt;getMessage(); } {/geshi}&lt;/p&gt;
&lt;p&gt;DSN zostanie pobrany z pliku do którego podaliśmy ścieżkę.&lt;/p&gt;
&lt;p&gt;{geshi lang=php} try { $pdo = new PDO('database1', 'root', 'root'); //dyrektywa php.ini - pdo.dsn.database1 echo 'Nawiązałem połączenie'; } catch(PDOException $e) { echo 'Błąd:'.$e-&amp;gt;getMessage(); } {/geshi}&lt;/p&gt;
&lt;p&gt;Dane zostaną pobrane z php.ini - dyrektywa &lt;i&gt;pdo.dsn.database1&lt;/i&gt;.&lt;/p&gt;
&lt;p&gt;Jako ostatni parametr możemy także ustawić nieco innych opcji sterownika bazy danych opisanych w manualu. Przykład ustawienia kodowania dla połączenia z bazą:&lt;/p&gt;
&lt;p&gt;{geshi lang=php} $pdo = new PDO('mysql:host=localhost;dbname=jakasnazwa', 'root', 'root', array(PDO::MYSQL_ATTR_INIT_COMMAND =&amp;gt; &quot;SET NAMES utf8&quot;)); {/geshi}&lt;/p&gt;
&lt;h3&gt;Wykonywanie zapytań&lt;/h3&gt;
&lt;p&gt;Wykonywanie zapytań do bazy danych z PDO jest o wiele ławiejsze niż w przypadku ADOdb. Biblioteka ta posiada całą masę funkcji z których każda pobiera i zwraca dane w inny sposób. W przypadku PDO istnieją trzy funkcje służące do wywoływania zapytań:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;PDO::query() - funkcja używana w przypadku pobierania danych z bazy&lt;/li&gt;
&lt;li&gt;PDO::exec() - funkcja używana, gdy chcemy wywołać zapytanie które nie zwraca żadnego rezultatu&lt;/li&gt;
&lt;li&gt;PDO::prepare() - funkcja wywoływana gdy używamy &lt;i&gt;prepared statements&lt;/i&gt; (więcej na ten temat w następnych wpisach o PDO)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Zasadnicza reguła między ADOdb a PDO jest taka, że w przypadku ADOdb sposób dostępu do danych z zapytania określany był przy pomocy użytej funkcji. W przypadku obecnie omawianej biblioteki wszystko jest dużo bardziej przejrzyste. Każda metoda klasy PDO zwraca obiekt klasy PDOStatement, za pomocą którego uzyskujemy dostęp do danych.&lt;/p&gt;
&lt;p&gt;Jak zatem uzyskać efekty podobne do tych z ADOdb? Wszystko jest tutaj możliwe dzięki potędze PHP5 oraz SPL'a. Implementacja odpowiednich interfejsów pozwala na ietrację zwracanego przez metodę PDO::query() obiektu PDOStatement w pętli foreach. Ponadto posiada on wiele użytecznych funkcji, które pozwalają na manipulowanie nim oraz pobieranie danych.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;PDOStatement::fetch() - pobiera pojedynczy rekord z wyniku. Może być używana wiele razy - każde wywołanie pobierze nowy rekord.&lt;/li&gt;
&lt;li&gt;PDOStatement::fetchAll() - pobiera wszystkie rekordy z wyniku&lt;/li&gt;
&lt;li&gt;PDOStatement::fetchColumn() - pobiera wartość kolumny z wyniku. Może być używana wiele razy - każde wywołanie pobierze nowy rekord.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Przykłady użycia:&lt;/p&gt;
&lt;p&gt;{geshi lang=php} $db = new PDO($dsn, $user, $password); $players = $db -&amp;gt; query('SELECT * FROM players'); while($row = $players-&amp;gt;fetch()) { echo $row['login']; } foreach($players-&amp;gt;fetchAll() as $row) { echo $row['login']; } echo $players-&amp;gt;fetchColumn(); //zakladamy, ze zadane pole zostalo pobrane jako pierwsze {/geshi}&lt;/p&gt;
&lt;p&gt;Wykonywanie zapytania które nie zwraca żadnej wartości jest dużo szybsze i prostsze:&lt;/p&gt;
&lt;p&gt;{geshi lang=php} $db-&amp;gt;exec('DELETE FROM players'); {/geshi}&lt;/p&gt;
&lt;p&gt;Na zakończenie warto zobaczyć potęgę SPL'a w akcji. Podobne możliwości dawało ADOdb, jednak tam musieliśmy wykonywać zapytanie przy pomocy funkcji Execute(), co uniemożliwiało nam dostęp do danych na inne sposoby. Warto zwrócić uwagę na to, że poniższy kod nie używa metody fetchAll(). Dzięki temu ilość wykonanych pętli zmiejszy się (nie musimy wykonywać pętli aby pobrać wszystkie rekordy do tablicy, zamiast tego pobieramy je po jednym).&lt;/p&gt;
&lt;p&gt;{geshi lang=php} $players = $db -&amp;gt; query('SELECT * FROM players'); foreach($players as $row) { echo $row['login']; } {/geshi}&lt;/p&gt;
&lt;p&gt;EDIT: Kiri przypomniała mi, że aby wszystko działało prawidłowo &lt;strong&gt;konieczne jest&lt;/strong&gt; zamknięcie kursora do obiektu klasy PDOStatement. Wykonuje się to za pomocą metody PDOStatement::closeCursor().&lt;/p&gt;
&lt;p&gt;{geshi lang=php} $players = $db -&amp;gt; query('SELECT * FROM players'); foreach($players as $row) { echo $row['login']; } $player -&amp;gt; closeCursor(); {/geshi}&lt;/p&gt;
&lt;p&gt;Jeżeli jej nie użyjemy, mogą pojawić się problemy z wykonaniem kolejnego zapytania. Nie pytajcie dlaczego tak jest ;).&lt;/p&gt;
&lt;h3&gt;Zakończenie&lt;/h3&gt;
&lt;p&gt;To już koniec dzisiejszego wpisu. Chciałbym was zapytać, które API wy preferujecie? Osobiście uważam, że droga obrana przez PDO jest słuszna i bardzo intuicyjna. W przypadku ADOdb ciężko było połapać się w niezliczonej ilości metod. Ponadto obsługa wyjątków sprawia, że mogę dokładnie zdecydować, co zrobić z błędem związanym z bazą danych. Dlaczego reszta całego PHP nie zdąża w tym kierunku?&lt;/p&gt;
</description><pubDate>Mon, 22 Sep 2008 21:57:16 +0200</pubDate><guid>http://blog.albitos.eu/2008/09/22/kurs-pdo-wprowadzenie/</guid><category>PHP/MySQL</category><category>Techblog</category><category>Wszystkie</category><category>php pdo programowanie dao</category></item><item><title>ADOdb vs PDO</title><link>http://blog.albitos.eu/2008/09/19/adodb-vs-pdo/</link><description>&lt;p&gt;PDO jest kolejną biblioteką dostępu do bazy danych którą będę omawiał na łamach mojego bloga. W dzisiejszym wpisie chciałbym dość pokrótce omówić różnice w stosunku do ADOdb na temat którego pisałem we wcześniejszych postach.&lt;/p&gt;
&lt;p&gt;Najważniejszą sprawą dla wszystkich będzie fakt, że PDO jest biblioteką wbudowaną w PHP i dostępną jako rozszerzenie PECL. Ponadto jest stale rozwijana w przeciwieństwie do ADOdb, które stanęło w miejscu kilka lat temu. Następstwem tego jest bardzo ważne dla twórców stron skrócenie czasu wykonywania skryptów wykorzystujących PDO.&lt;/p&gt;
&lt;p&gt;Olbrzymią różnicą pomiędzy ADOdb a PDO jest podejście do obsługi wielu baz danych. Pierwsza z nich udostępnia specjalne funkcje, które pozwalają zamaskować niektóre różnice w implementacji standardu SQL w różnych systemach baz danych. PDO natomiast takiej funkcjonalności nie posiada, co przyspiesza jej działanie.&lt;/p&gt;
&lt;p&gt;Kolejna kwestia warta poruszenia to obsługa cache, sesji w bazie danych oraz innych &quot;bajerów&quot; które posiada ADOdb. Niestety w PDO ich nie doświadczymy. Czy to źle? Zdania z całą pewnością będą podzielone dlatego decyzję pozostawię czytelnikowi.&lt;/p&gt;
&lt;p&gt;Na koniec warto zaznaczyć, że o ile ADOdb była biblioteką bardzo bałaganiarską (konfiguracja w zmiennych globalnych, wiele aliasów metod, duplikacja funkcjonalności) o tyle PDO radzi sobie z tym o wiele lepiej. Wszystkie stałe związane z klasą znajdują się w niej samej zamiast w przestrzeni globalnej. Ponadto wszystkie nazwy funkcji są w jednym standardzie kodowania (camel case).&lt;/p&gt;
&lt;p&gt;Wpis ten jest jedynie krótkim wprowadzeniem do PDO mającym wskazać zalety tej biblioteki. Mam nadzieję, że przyda się on wszystkim, którzy chcieliby ją poznać lepiej. Już wkrótce pojawi się więcej wpisów na temat jej używania w swoich skryptach wraz z przykładami. Czy waszym zdaniem PDO prezentuje się lepiej? A może już z niego korzystacie i chcielibyście podzielić się wrażeniami? Zachęcam do dyskusji.&lt;/p&gt;
</description><pubDate>Fri, 19 Sep 2008 17:23:50 +0200</pubDate><guid>http://blog.albitos.eu/2008/09/19/adodb-vs-pdo/</guid><category>PHP/MySQL</category><category>Techblog</category><category>Wszystkie</category><category>adodb pdo php programowanie</category></item><item><title>Funkcje ADOdb i wykonywanie zapytań cz.3</title><link>http://blog.albitos.eu/2008/09/12/funkcje-adodb-i-wykonywanie-zapytan-cz-3/</link><description>&lt;p&gt;W dzisiejszym wpisie omówię wykorzystanie cache w bibliotece ADOdb oraz moduł ADOdb C. Dowiecie się jak zapisać wynik zapytania przy pomocy ADOdb tak, aby ponowne pobieranie niezmienionych danych zajmowało jak najmniej czasu.&lt;/p&gt;
&lt;h3&gt;Cache - co to jest?&lt;/h3&gt;
&lt;p&gt;Cache jest to mechanizm, który umożliwia szybszy dostęp do danych przy pomocy zapisywania ich kopii w miejscu o szybszym czasie odczytu. Dzięki temu gdy dane się nie zmieniły, lub nie zależy nam na ich aktualności, nie musimy pobierać ich z bazy danych, nawiązując połączenie i wysyłając zapytanie. Wystarczy odczytać je ze zwykłego pliku zapisanego na dysku, który jest znacznie szybciej odczytywany, niż baza danych.&lt;/p&gt;
&lt;h3&gt;ADOdb i cache zapytań&lt;/h3&gt;
&lt;p&gt;Na samym początku chciałbym wypisać funckje obsługujące cache w ADOdb. Są to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;$db -&amp;gt; cacheExecute()&lt;/li&gt;
&lt;li&gt;$db -&amp;gt; cacheGetAll()&lt;/li&gt;
&lt;li&gt;$db -&amp;gt; cacheGetRow()&lt;/li&gt;
&lt;li&gt;$db -&amp;gt; cacheGetOne()&lt;/li&gt;
&lt;li&gt;$db -&amp;gt; cacheSelectLimit()&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Jak łatwo się domyślić, działanie wszystkich wyżej wymienionych metod jest bardzo podobne do tych z &lt;a href=&quot;http://albi.vxe.pl/2008/08/23/funkcje-adodb-i-wykonywanie-zapytan-cz-1/&quot;&gt;poprzednich części&lt;/a&gt;, za jednym wyjątkiem - jako pierwszy parametr podajemy czas w sekundach, przez jaki wykonane zapytanie SQL ma być zapisane i pobierane z cache. Jeżeli funkcja wywoływana jest po raz pierwszy, lub czas cache dla danego zapytania minął, wtedy jest ono wykonywane. Inaczej dane zostaną pobrane ze specjalnego pliku cache zapisanego w odpowiednym katalogu przez ADOdb. Katalog ten określany jest przez globalną zmienną $ADODB_CACHE_DIR. Tak, też uważam to za dziwne rozwiązanie, jednak tak już po prostu jest.&lt;/p&gt;
&lt;p&gt;{geshi lang=php} $ADODB_CACHE_DIR = '/tmp'; $sql = 'SELECT * FROM players WHERE id=?' $db -&amp;gt; cacheExecute(3600, $sql, array($_GET['id'])); $db -&amp;gt; cacheGetAll(3600, $sql, array($_GET['id'])); $db -&amp;gt; cacheGetRow(3600, $sql, array($_GET['id'])); $db -&amp;gt; cacheGetOne(3600, $sql, array($_GET['id'])); $db -&amp;gt; cacheSelectLimit(3600, $sql, 1, 1, array($_GET['id'])); {/geshi}&lt;/p&gt;
&lt;p&gt;Możemy także nie podawać pierwszego parametru. Wtedy wykorzystana zostanie wartość $db -&amp;gt; cacheSecs (domyślnie ustawiona na 3600 sekund).&lt;/p&gt;
&lt;p&gt;{geshi lang=php} $db -&amp;gt; cacheSecs = 1200; $sql = 'SELECT * FROM players WHERE id=?' $db -&amp;gt; cacheExecute($sql, array($_GET['id'])); $db -&amp;gt; cacheGetAll($sql, array($_GET['id'])); $db -&amp;gt; cacheGetRow($sql, array($_GET['id'])); $db -&amp;gt; cacheGetOne($sql, array($_GET['id'])); $db -&amp;gt; cacheSelectLimit($sql, 1, 1, array($_GET['id'])); {/geshi}&lt;/p&gt;
&lt;p&gt;Czyszczenie cache polega na wywołaniu funkcji $db -&amp;gt; cacheFlush(). Jeżeli chcemy usunąć cache tylko dla jednego zapytania, podajemy je jako parametr naszej funkcji. Taki sposób nie jest możliwy w przypadku $db -&amp;gt; cacheSelectLimit(), ponieważ funkcja ta generuje swoje własne zapytanie zależnie od bazy danych. Wtedy należy tę funkcję wywołać z pierwszym parametrem jako zero.&lt;/p&gt;
&lt;p&gt;{geshi lang=php} $db -&amp;gt; cacheSelectLimit(3600, $sql, 1,1); //Pobranie danych i zapisanie do cache $db -&amp;gt; cacheSelectLimit(3600, $sql, 1,1); //Pobranie danych z cache $db -&amp;gt; cacheSelectLimit(0, $sql, 1,1); //Skasowanie cache {/geshi}&lt;/p&gt;
&lt;h3&gt;ADOdb extension&lt;/h3&gt;
&lt;p&gt;ADOdb extension powstało, aby przyspieszyć działanie biblioteki. Napisane jest w C i zgodne z PHP 4.3.*, 4.4.*, 5.0.* oraz 5.1.* (oficjalnie). Osobiście używamy wersji PHP 5.2 i wszystko działa jak do tej pory bezproblemowo. Rozszerzenie to jest modułem który nadpisuje niektóre funkcje zwykłego ADOdb w celu zwiększenia ich wydajności. Warto nim się zainteresować, jeżeli nasz projekt używa już ADOdb. W innym wypadku polecam PDO, które w całości napisane jest w C. To już koniec serii poświęconej ADOdb. Mam nadzieję, że opisane przeze mnie funkcje pomogły wam zrozumieć zasadę działania tej nierozwijanej już biblioteki. Była to pierwsza biblioteka DAO (wtedy jeszcze nie wiedziałem co to jest), z której korzystałem. W dalszej części przeglądu tego typu bibliotek będzie PDO.&lt;/p&gt;
</description><pubDate>Fri, 12 Sep 2008 15:14:03 +0200</pubDate><guid>http://blog.albitos.eu/2008/09/12/funkcje-adodb-i-wykonywanie-zapytan-cz-3/</guid><category>PHP/MySQL</category><category>Techblog</category><category>Wszystkie</category><category>adodb php programowanie</category></item><item><title>Funkcje ADOdb i wykonywanie zapytań cz.2</title><link>http://blog.albitos.eu/2008/09/10/funkcje-adodb-i-wykonywanie-zapytan-cz-2/</link><description>&lt;p&gt;W dzisiejszej części artykułu na temat ADOdb poznamy funkcje, które są nieco rzadziej używane oraz nauczymy się korzystać z tak zwanych &quot;prepared statements&quot; - specjalnego sposobu przekazywania parametrów do zapytań SQL który ma za zadania zapobiec atakom typu SQL Injection. Oto lista funkcji, które dzisiaj poznamy:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;$db -&amp;gt; AutoExecute()&lt;/li&gt;
&lt;li&gt;$db -&amp;gt; Replace()&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Tym razem będzie ich nieco mniej, ponieważ dużą część wpisu chciałbym poświęcić podpinaniu zmiennych pod zapytania SQL. Jest to bardzo ciekawa opcja, gdyż pozwala na zabezpieczenie się przed atakami typu SQL Injection w bardzo prosty sposób oraz poprawia czytelność zapytań. Poniżej kod wykorzystujący &lt;em&gt;variable binding&lt;/em&gt;:&lt;/p&gt;
&lt;p&gt;{geshi lang=php} $db-&amp;gt;Execute(&quot;SELECT * FROM players WHERE id=?&quot;, array($_GET['id'])); {/geshi}&lt;/p&gt;
&lt;p&gt;Kod taki spowoduje, że do zapytania zamiast znaku zapytania podstawiona zostanie wartość zmiennej $_GET['id']. Dodatkowo według manuala ADOdb, taki sposób podawania zmiennych do zapytania przyspiesza czas jego wykonywania i korzystania z cache. Teraz pora na nieco bardziej skomplikowany przykład:&lt;/p&gt;
&lt;p&gt;{geshi lang=php} $db-&amp;gt;Execute(&quot;SELECT * FROM players WHERE id=? AND ip=? AND user=?&quot;, array($_GET['id'], $_GET['ip'], $sUserName)); {/geshi}&lt;/p&gt;
&lt;p&gt;lub&lt;/p&gt;
&lt;p&gt;{geshi lang=php} $arrValues = array($_GET['id'], $_GET['ip'], $sUserName); $db-&amp;gt;Execute(&quot;SELECT * FROM players WHERE id=? AND ip=? AND user=?&quot;, $arrValues); {/geshi}&lt;/p&gt;
&lt;p&gt;W ten sposób do zapytania zostaną podstawione kolejno wartości z tablicy przekazanej jako parametr. A teraz zobaczmy kod który nie wykorzystuje tej techniki:&lt;/p&gt;
&lt;p&gt;{geshi lang=php} $db-&amp;gt;Execute('SELECT * FROM players WHERE id='.(int)$_GET['id'].' AND ip='.$db-&amp;gt;qstr($_GET['id']).' AND user='.$db-&amp;gt;qstr($sUserName)); {/geshi}&lt;/p&gt;
&lt;p&gt;I teraz czytelniku, który sposób jest czytelniejszy i bardziej zwięzły? Jest jeszcze jedna rzecz, którą musisz wiedzieć używając tego sposobu. Otóż działa on we wszystkich funkcjach, jakie do tej pory poznaliśmy i poznamy! Ale to nie koniec dobrej zabawy. Teraz &lt;strong&gt;dodamy&lt;/strong&gt; kilka rekordów &lt;strong&gt;i to za jednym zamachem&lt;/strong&gt;!&lt;/p&gt;
&lt;p&gt;{geshi lang=php} $arrValues = array( array($_GET['ip'], $_GET['user'], 'Człowiek'), array($_GET['ip2'], $_GET['user2'], 'Człowiek'), array($_GET['ip3'], $_GET['user3'], 'Człowiek'), ); $db-&amp;gt;Execute('INSERT INTO players(ip, user, rasa) VALUES(?,?,?)', $arrValues); {/geshi}&lt;/p&gt;
&lt;p&gt;Tak więc kiedy do funkcji przekazujemy tablicę dwuwymiarową, wtedy dla każdego jej elementu ADOdb generuje oddzielne zapytanie i podpina wartości z drugiego wymiaru tablicy. Warto jeszcze na końcu zaznaczyć, że podpinać parametry do zapytań można nie tylko w metodzie $db -&amp;gt; Execute(), lecz także w innych które do tej pory poznaliśmy. Kilka przykładów:&lt;/p&gt;
&lt;p&gt;{geshi lang=php} $db -&amp;gt; getAll('SELECT * FROM players WHERE level &amp;gt; ?', array($_GET['level'])); $db -&amp;gt; getRow('SELECT * FROM players WHERE id = ?', array($_GET['id'])); $db -&amp;gt; getRow('SELECT name FROM players WHERE id = ?', array($_GET['id'])); {/geshi}&lt;/p&gt;
&lt;p&gt;To wszystko, jeżeli chodzi o nasz nowy sposób dodawania zmiennych do zapytań. Teraz zajmijmy się nowymi funkcjami.&lt;/p&gt;
&lt;h2&gt;Funkcja ADOConnection::AutoExecute()&lt;/h2&gt;
&lt;p&gt;To bardzo ciekawa funkcja, która ma wiele zastosowań. Potrafi całkiem sporo, dlatego naprawdę warto zapoznać się z jej działaniem. Funkcja ta na podstawie podesłanej tablicy asocjacyjnej generuje odpowiednie zapytanie dodające lub aktualizujące rekord w zależności od kolejnego parametru. Przykładowe wywołania:&lt;/p&gt;
&lt;p&gt;{geshi lang=php} $arrData = array('user' =&amp;gt; 'Klaus Korner', 'ip' =&amp;gt; '127.0.0.1', 'rasa' =&amp;gt; 'Krasnolud'); $db -&amp;gt; AutoExecute('players', $arrData, 'INSERT'); //1 $db -&amp;gt; AutoExecute('players', $arrData, 'UPDATE', &quot;user='Klaus Korner'&quot;); //2 {/geshi}&lt;/p&gt;
&lt;p&gt;W pierwszym przykładzie dodajemy nowy rekord do tabeli &lt;em&gt;players&lt;/em&gt;, zaś w drugim aktualizujemy go. Jako pierwszy parametr funkcji przekazujemy nazwę tabeli którą modyfikujemy. Następnie tablicę z danymi, gdzie klucze są nazwami kolumn. Potem rodzaj zapytania i na końcu ewentualny warunek, jeżeli aktualizujemy rekord(y). Podobna do tej jest funkcja $db -&amp;gt; getUpdateSQL(), jednak ta zamiast wykonywać zapytanie, jedynie zwraca jego treść. Warto też zapamiętać, że aby dane wysyłane do bazy były poprawne, ADOdb sprawdza poprzednio czy klucze w tablicy z polami są prawidłowe i kasuje te złe. Niestety, trzeba za to zapłacić zapytaniem które musi zostać wykonane, dlatego należy z rozsądkiem używać tej funkcji.&lt;/p&gt;
&lt;h2&gt;Funkcja ADOConnection::Replace()&lt;/h2&gt;
&lt;p&gt;Jeszcze ciekawsza od poprzedniej funkcja służy do zastępowania/dodawania rekordów. Takie potwory są plagą skryptu na którym mam dość często nieprzyjemność pracować:&lt;/p&gt;
&lt;p&gt;{geshi lang=php} $test = $db-&amp;gt;Execute(&quot;SELECT `id` FROM `potions` WHERE `name`='&quot;.$strName.&quot;' AND `owner`=&quot;.$player -&amp;gt; id.&quot; AND `status`='K' AND `power`=&quot;.$intPower) or die(&quot;błąd&quot;); if (!$test-&amp;gt;fields['id']) { $db-&amp;gt;Execute(&quot;INSERT INTO potions (`owner`, `name`, `efect`, `power`, `amount`, `status`, `type`) VALUES(&quot;.$player-&amp;gt;id.&quot;, '&quot;.$strName.&quot;', '&quot;.$objItem-&amp;gt;fields['efect'].&quot;', &quot;.$intPower.&quot;, &quot;.$intTmpamount.&quot;, 'K', '&quot;.$objItem-&amp;gt;fields['type'].&quot;')&quot;); } else { $db-&amp;gt;Execute(&quot;UPDATE `potions` SET `amount`=`amount`+&quot;.$intTmpamount.&quot; WHERE `id`=&quot;.$test -&amp;gt; fields['id']); } {/geshi}&lt;/p&gt;
&lt;p&gt;Coś takiego możemy zastąpić jednym, prostym wywołaniem funkcji $db-&amp;gt;Replace(). Poniżej mały przykład:&lt;/p&gt;
&lt;p&gt;{geshi lang=php} $arrData = array( 'name' =&amp;gt; $strName, 'owner' =&amp;gt; $player -&amp;gt; id, 'status' =&amp;gt; 'K', 'power' =&amp;gt; $intPower, 'amount' =&amp;gt; 'amount + '.$intTmpamount ); $arrKeys = array('name', 'owner', 'status', 'power'); $db-&amp;gt;Replace('potions', $arrData, $arrKeys, true); {/geshi}&lt;/p&gt;
&lt;p&gt;W ten sposób zawiły i skomplikowany kod zamieniliśmy w zwięzłe wywołanie jednej funkcji. Jak widać, przydatność jest wysoka. Omówmy teraz dokładniej jej działanie. Funkcja ta na podstawie tablicy z drugiego parametru dodaje lub aktualizuje rekord z tabeli podanej jako pierwszy parametr. Sprawdzanie czy istnieje rekord do aktualizacji odbywa się za pomocą kluczy z trzeciego parametru (dane te trafiają do warunku WHERE, a pozostałe elementy tablicy z drugiego parametru służą do aktualizacji). Ostatni, czwarty parametr określa, czy funkcja ma dodawać apostrofy i domyślnie ustawiony jest na false. To już wszystko co dzisiaj chciałem wam pokazać. Mam nadzieję, że rozwiałem wszelkie wątpliwości, dlaczego uważam zastępowanie ADOdb jego biedniejszymi zamiennikami za niezbyt dobry pomysł. Jeżeli nie, to zapraszam na kolejny wpis z serii, który opisze wykorzystywanie cache w zapytaniach oraz kilka słów na temat modułu ADOdb napisanego w C. Powiem szczerze, że podczas pisania dwóch poprzednich wpisów zostałem mile zaskoczony ilością ciekawych funkcji w ADOdb. A może już ich używacie? Jakie są wasze doświadczenia z tą biblioteką i jak wiele dowiedzieliście się z tego wpisu? Czekam na komentarze.&lt;/p&gt;
</description><pubDate>Wed, 10 Sep 2008 16:53:32 +0200</pubDate><guid>http://blog.albitos.eu/2008/09/10/funkcje-adodb-i-wykonywanie-zapytan-cz-2/</guid><category>PHP/MySQL</category><category>Techblog</category><category>Wszystkie</category><category>php adodb dao</category></item></channel></rss>
