
- Data wpisu: 2009-05-28
- Tagi: Bazy danych, databases.yml, Multidatabase, ORM, PHP, PostgreSQL, Propel, propel.ini, schema, SQL, sqldb.map, Symfony, yml
W aplikacjach internetowych czasami musimy wykorzystać w jednym serwisie wiele baz danych, nieraz nawet wiele różnych baz danych. Mój wpis będzie prezentował proste przykłady użycia wielu baz z wykorzystaniem frameworka Symfony. Dla przykładu użyje bazy danych PostgreSQL oraz ORM Propela 1.3.
W przykładzie wykorzystam 2 tabele: “users” z bazy “db1″ (załóżmy, że to główna bazy serwisu z użytkownikami) i “requests” z bazy “db2″ (baza w której zapisywane są statystyki z żądań do aplikacji). Modele wygenerowane będą dla bazy PostgreSQL. W kolejnym etapie zaprezentuje w jaki sposób można załadować przykładowe dane pochodzące z data/fixtures.
Definiowanie baz w pliku databases.yml
Edytujemy config/databases.yml
all:
propel:
class: sfPropelDatabase
param:
classname: PropelPDO
dsn: pgsql:dbname=db1;host=panic user=db1 password=db1
hostspec: pgsql
port: 5432
encoding: utf8
stat:
class: sfPropelDatabase
param:
classname: PropelPDO
dsn: pgsql:dbname=db2;host=panic user=db2 password=db2
hostspec: pgsql
port: 5432
encoding: utf8
Pierwszym krokiem jest zdefiniowanie połączeń do baz danych. Główną nazwę połączenia będzie “propel” a drugą “stat”
Ustawienie pliku propel.ini
propel.database = pgsql propel.database.driver = pgsql propel.database.url = pgsql:dbname=db1;host=panic user=db1 password=db1
W pliku propel.ini ustawiamy połączenie z główną bazę danych. “propel.database” odpowiada za generowanie kodu SQL dla danych baz, np.: MySQL, PostgreSQL, Oracle. Jeśli chcemy generować SQL dla wybranego typu bazy, to musimy zmienić na odpowiednią wartość. Można to uzyskać z linii koment ustawiajac –phing-arg
Przykład dla MySQLa:
./symfony propel:build-all --no-confirmation --connection=stat --phing-arg="Dpropel.database=mysql"
Przykład dla Oracle:
./symfony propel:build-all --no-confirmation --connection=stat --phing-arg="Dpropel.database=oracle"
Definiowanie tabel w config/schema.yml
Jak w przykładzie z optymalizacją Propela dobrym nawykiem jest rozdzielenie różnego typu struktur na osobne pliki schema.yml. Główną definicja tabel można zapisać w pliku schema.yml a dodatkową strukturę bazy w osobnym pliku, np w pliku stat_schema.yml.
Plik config/schema.yml
propel:
users:
id: { type: integer, required: true, primaryKey: true, autoincrement: true }
created_at: { type: timestamp }
name: { type: varchar, size: 255 }
surname: { type: varchar, size: 255 }
Plik config/stat_schema.yml
stat:
_attributes: { package: lib.stat_model }
requests:
id: { type: integer, required: true, primaryKey: true, autoincrement: true }
created_at: { type: timestamp }
module: { type: varchar, size: 255 }
action: { type: varchar, size: 255 }
W pliku stat_schema.yml, użyłem package: lib.stat_model – czyli miejsce, w którym zostaną wygenerowane modele wykorzystujące bazę “db2″, lib.stat_model = lib/stat_model.
Po zdefiniowaniu struktur i baz przechodzimy do generowania modeli i stworzenia struktur tabel w bazach danych.
Generowanie modeli i struktur baz danych dla “db1″ i “db2″
./symfony propel:build-all --no-confirmation
Modele dla baz danych zostały wygenerowane. Struktura tabel została stworzona tylko w pierwszej bazie “db1″ - ponieważ to połączenie jest domyślne. Aby stworzyć strukturę tabel w bazie “db2″ musimy wymusić połączenie z bazą “db2″ (czyli połączenie o nazwie “stat”).
./symfony propel:build-all --no-confirmation –connection=stat
Przykład wykorzystania modeli
Przykłady:
$obj1 = UsersPeer::retrieveByPK(1); $obj2 = RequestsPeer::retrieveByPK(1);
Wykorzystując model nie musimy podawać połączenia, chyba że chcemy aby dany model był wykorzystany jawnie do “innej” bazy, “innej” mam tutaj na myśli bazy danych o takiej samej strukturze tabeli jaka jest zdefiniowana w modelu.
Ładowanie przykładowych danych (data/fixtures)
Podobnie jak w przypadku definicji struktur bazy danych rozdzielamy ładowanie danych. Dla bazy “db1” będzie to katalog data/fixtures a dla bazy “db2” data/stat_fixtures
Wywołanie tasków - dla domyślnej bazy danych “db1″ :
./symfony propel:data-load
Ładowanie danych do bazy “db2″ wymaga podania odpowiedniego połączenie i ustawienia katalogu z którego dane będą wczytywane.
./symfony propel:data-load --connection=stat --dir="data/stat_fixtures"
Można definiować n takich baz. Jeśli np. chcielibyśmy operować na takich samych tabelach w różnych bazach danych to możemy w modelach wymuszać konkretne połączenia, wszystko zależy od projektu i jego wymagań.


