wtorek, 11 listopada 2008

Zepsuło się - naprawiamy obsługę SQLite w PHP

Wczoraj chciałem napisać niewielki skrypt w PHP. Skrypcik malutki, ale byłby stosunkowo często wykorzystywany (jakieś kilka tysięcy razy na dzień :P). Aby zanadto nie męczyć MySQL'a postanowiłem spróbować wreszcie wykorzystać SQLite - bazę prostą, ale wygodną, szybką i posiadającą wystarczające możliwości. W końcu chodzi tylko o najzwyklejsze składowanie danych.

Kolejną sprawą było PDO, z którego również nigdy wcześniej nie korzystałem. Natrafiła się więc idealna okazja do nadrobienia zaległości i bliższego poznania obu ciekawych rozwiązań. Jakież było w związku z tym moje zdziwienie, gdy zauważyłem, że SQLite i PDO u mnie nie współpracują. Po wielu próbach okazało się, że winnym zaistniałej sytuacji jest brak rozszerzenia sqlite.so w mojej instalacji PHP. Trochę mnie to zdziwiło biorąc pod uwagę fakt, że w czasie instalacji serwera dodałem do niego chyba wszystko co było możliwe. Jak widać, byłem w błędzie ;P Nadróbmy więc stracony czas.

Niestety gotowej do podrzucenia w systemie biblioteki sqlite.so raczej nie znajdziemy. Trzeba ją w takim razie przygotować sobie samemu. Poniższe rozwiązanie znalazłem na forum PHPBuilder. Aby jednak wdrożyć je w systemie Fedora 9 konieczne jest dokonanie kilku kosmetycznych zmian. Pełny tutorial znajdziecie poniżej.

Z serwera PHP pobieramy najpierw plik SQLite-1.0.3.tgz (mirror). Komendą

pecl download sqlite

zawsze możemy pobrać najnowszą wersję. Archiwum rozpakowujemy, odpalamy terminal i wchodzimy do nowopowstałego katalogu SQLite-1.0.3. Po upewnieniu, że wewnątrz znajduje się plik config.m4 wpisujemy kolejno

phpize
./configure

Następnie w ulubionym edytorze tekstu otwieramy plik sqlite.c i dokonujemy stosownych podmian. Linię

static unsigned char arg3_force_ref[] = {3, BYREF_NONE, BYREF_NONE, BYREF_FORCE };

zamieniamy na

/* static unsigned char arg3_force_ref[] = {3, BYREF_NONE, BYREF_NONE, BYREF_FORCE }; */

zaś blok

function_entry sqlite_functions[] = {
PHP_FE(sqlite_open, arg3_force_ref)
PHP_FE(sqlite_popen, arg3_force_ref)

na

function_entry sqlite_functions[] = {
PHP_FE(sqlite_open, third_arg_force_ref)
PHP_FE(sqlite_popen, third_arg_force_ref)

Plik zapisujemy i zamykamy. Wracamy do terminala, logujemy się na konto root i wydajemy kolejne polecenia

make
make install
ls /usr/lib/php/modules/

Naszym oczom powinna ukazać się lista rozszerzeń PHP. Jeśli widzimy tam sqlite.so to znaczy, że wszystko poszło idealnie.

Tip: Instalator powinien sam przenieść nowe rozszerzenie do odpowiedniego katalogu. Jeśli jednak tego nie zrobi, musimy dokonać tego samodzielnie. Plik sqlite.so znajdziemy w naszym folderze roboczym w podkatalogu modules.

Póki co jednak PHP nie widzi nowego rozszerzenia, musimy jeszcze dopisać je do konfiguracji i zrestartować serwer Apache.

cd /etc/php.d/
cp pdo_sqlite.ini sqlite.ini
vim sqlite.ini

Zawartość pliku sqlite.ini zmieniamy odpowiednio z

; Enable pdo_sqlite extension module
extension=pdo_sqlite.so

na

; Enable sqlite extension module
extension=sqlite.so

i zapisujemy. Teraz pozostaje tylko wspomniane ponowne uruchomienie usługi httpd i SQLite zaczyna nam śmigać.

/etc/init.d/httpd restart

Dostępne od tej pory są zarówno fukcje sqlite_* jak i możemy obsługiwać bazy przez interfejs PDO.

Na koniec warto jeszcze wspomnieć o pewnych utrudnieniach związanych z korzystaniem z baz SQLite w PHP. Aby uniknąć różnych problemów z zapisem do bazy należy pamiętać nie tylko o ustawieniu uprawnień do niej na 666, ale również do katalogu, w którym jest przechowywana na 777! Jeśli o tym zapomnimy metoda PDO::errorInfo() zwróci komunikat błędu attempt to write a readonly database lub unable to open database file (szczególnie ten drugi niewiele mówi).

Trochę odbiegłem od planu, ale wolałem napisać powyższy artykuł już teraz żeby nie zapomnieć :) Kolejny w związku z tym będzie już tak jak wspominałem ostatnio o serwerze XMPP we własnej domenie. Czekajcie cierpliwie! Kiedyś może jeszcze napiszę co nieco o pracy z SQLite.

Zauważyłeś błąd w artykule? Coś nie działa? Zostaw swoje uwagi w komentarzach.