Obsługa wielu systemów baz danych

0

Ten temat co jakiś czas powraca na forum, a dla mnie jest o tyle ważny, że na niczym innym niż PostgreSQL stawiać Coyota lokalnie ochoty nie mam. Problem zaczyna się, gdy w kodzie PHP pojawia się składnia SQL nie wspierana przez ten (czy też inne) serwery baz danych.

Więc proponuję następujące rozwiązanie: oddzielić logikę aplikacji czyli główną część PHP od samych funkcji SQL pobierających dane. Może łatwiej na przykładzie:

Załóżmy istnienie fragmentu w pliku coyote/index.php (fragment prawdziwy)

$sql = 'SELECT news_id,
    news_subject,
    news_time
    FROM ' . NEWS_TABLE . '
    ORDER BY news_id
    DESC LIMIT ' .$user->theme['cfg']['index_news_limit'];
$result = $db->sql_query($sql);

while ( $row = $db->sql_fetch($result) )
{
    $template->assign_block('NEWS', array(
        'U_NEWS'     => append_sid("news.$phpEx?id=$row[news_id]&go=1"),
        'DATE'       => date('d-m', $row['news_time']),
        'SUBJECT'    => trim_text($row['news_subject'], $user->theme['cfg']['index_news_length'])
        )
    );
}

Proponowałbym oddzielenie kodu SQL od działania PHP w taki sposób, jak przedstawiają pliki poniżej. Plik
coyote/index.php:

/* ZAŁĄCZANIE PLIKU Z FUNKCJAMI O NAZWIE TAKIEJ SAMEJ JAK TEN PLIK, Z KATALOGU OBSŁUGIWANEJ BAZY DANYCH */

if (file_exists('database/'.$Config['DB']['System'].'/'.basename($_SERVER['SCRIPT_NAME'])))
    include('database/'.$Config['DB']['System'].'/'.basename($_SERVER['SCRIPT_NAME']));

// ...

if ($db->Index->GetNews($user->theme['cfg']['index_news_limit']))
{
    foreach ( $db->result as $row )
    {
        $template->assign_block('NEWS', array(
            'U_NEWS'     => append_sid("news.$phpEx?id=$row[news_id]&go=1"),
            'DATE'       => date('d-m', $row['news_time']),
            'SUBJECT'    => trim_text($row['news_subject'], $user->theme['cfg']['index_news_length'])
            )
        );
    }
}

Plik coyote/database/PostgreSQL/index.php:

<?php
include_once(coyote/database/PostgreSQL/common_db_functions.php);
class Index
{
    function GetNews($limit)
    {
        global $db;
        return $db->Query('SELECT news_id,
            news_subject,
            news_time
            FROM ' . NEWS_TABLE . '
            ORDER BY news_id
            DESC LIMIT ' . $limit);
    }
}
$db->Index = new Index();
?>

Zaincludowany plik zawierałby definicję $db (właściwie to ten mechanizm akurat istnieje) oraz jej metody w stylu Query(), które zwraca również wynik do $db->result. Pracuję obecnie nad projektem, który wykorzystuje taki mechanizm, więc odpowiednik pliku coyote/database/PostgreSQL/common_db_functions.php dla PostgreSQL mam.

Sprawdza się to doskonale, a wystarczy dodać osobny katalog z plikami dla innej bazy i ustawić zmienną (tutaj: $Config['DB']['System']) na nazwę tej bazy danych i rozbudowa gotowa. Uniezależniamy kod PHP od systemu zarządzania bazą danych.

Co myślicie o użyciu tego mechanizmu w Coyote?

0

Ja jestem przeciwny. Czemu? Za duzo kombinowania. Nie chcialoby mi sie przepisywac zapytania pod wszystkie systemy baz danych jakie moze obslugiwac Coyote. Napisz moze o roznicach w skladni MySQL oraz PostgreSQL i czy bedzie to naprawde konieczne. Nav cos pisal o roznicy " oraz ' i z tego co wiem "bawi" sie juz Postgresem.

Proponuje wiec:

  • napisac klase obslugi Postgre
  • przygotowac plik schema.sql
  • sprawdzic kompatybilnosc zapytan w roznych systemach

W przypadkach gdy kompatybilnosc jest rzeczywiscie nie do przeskoczenia, proponuje rozwiazac to tak jak w session.php:

switch ( SQL_LAYER )
{
              case 'mysql4':
              
              // kod 
              break;
              //////////////////////////////////////////////////////////////////
              
              default:
              
              // kod 
}
0

Myślę, że nie będzie potrzeby "przepisywac zapytania pod wszystkie systemy baz danych jakie moze obslugiwac Coyote". Wystarczy napisać pod jedną, a potem skopiować i poprawić dla innej bazy niekompatybilne zapytania. Co do różnic - podstawowe będą wynikały z odmiennego podejścia do manipulacji datami oraz innych dostępnych funkcji (inaczej nazwanych albo inaczej obsługiwanych).

My tu mówimy na razie tylko o PostgreSQL, ale jak komuś się zachce przenieść to na jakiegoś Firebird, MSSQL, DB2 czy innego Oracle'a, to będzie już znaczny problem.

0

No wlasnie - to jest duplikowanie kodu :) W przypadku gdy w danym pliku znajdziemy blad - trzeba bedzie go poprawiac w pozostalych. Wezmy pierwszy przyklad z brzegu - phpBB. Obsluguje on wiele systemow baz danych i jakos wszystko chyba dziala. Trzeba bedzie jedynie napisac osobna klase do wyszukiwania danych, gdyz obecnie wykorzystywany jest mechanizm Fulltext-search, typowy dla MySQL.

0

Klasę przepisałem. Ale została mi struktura, z którą chyba sobie jeszcze nie poradzę oraz właśnie przepisanie tych zapytań.

Co do Fullltext-search pisałem już na ircu, że jest moduł do Postgresa który to umożliwia.

0

Mimo wszystko uważam, że warto oddzielić główny kod PHP, który odpowiada za działanie serwisu, a kod SQL i powiązany z nim PHP do komunikacji z bazą. Dlaczego? Z identycznych powodów, z których od PHP w Coyote został oddzielony HTML.

Może rozbijanie SQL na duplikujące się kody dla różnych baz nie jest najlepszym wyjściem, ale można na przykład oddzielić SQL powiedzmy do folderu /database/common/ i tylko przeciążać go różnicą dla danej bazy z folderu bazy, np.: /database/postgresql/.

Wydzielenie pobierania danych i ich obróbki znacznie ułatwia szukanie błędów w kodzie i ich poprawianie.

1 użytkowników online, w tym zalogowanych: 0, gości: 1