Seria artykułów poświęconych bazom danych pokazywała w jaki sposób korzystać z programu DBDesigner. Aplikacja Propel, przedstawiona poprzednio, generuje automatycznie klasy aktywnych rekordów. Teraz opiszę w jaki sposób Propelem generować kod PHP dla modelu bazy danych przygotowanego DBDesignerem.
Współpraca aplikacji
DBDesigner i Propel
Aplikacja DBDesigner służy do wizualnego projektowania
baz danych. Za pomocą kilku prostych
narzędzi tworzymy model ERD, definiując
tabele oraz relacje. Wynikiem pracy w programie
DBDesigner jest model bazy danych zapisany
w formacie XML.
Propel jest narzędziem, które na podstawie
modelu bazy danych opisanego w języku XML generuje
klasy PHP5 zapewniające dostęp do bazy
danych. Plik wejściowy Propela zawiera m.in. elementy
database, table, column.
Jeśli chcemy korzystać z DBDesignera w połączeniu
z Propelem, należy plik XML zapisany
przez DBDesignera przekształcić do formatu
wykorzystywanego przez aplikację Propel.
Zadanie to realizuje transformacja XSLT opracowana
przez Jonathana Grahama i dostępna
pod adresem: http://blog.tooleshed.com/?p=6.
Do wykonania konwersji w PHP niezbędne są
dwa pliki:
dbd2propel.xsl
transform.php
Dzięki wykorzystaniu transformacji dbd2propel.
xsl możemy dla bazy danych zaprojektowanej
w programie DBDesigner wygenerować Propelem
klasy aktywnych rekordów.
Przekształcenie formatu XML DBDesignera do formatu
Propela
Procedura konwersji modelu wykonanego programem
DBDesigner do formatu Propela:
- Przygotować model bazy danych programem
DBDesigner. Wynik pracy zapisać w pliku
{stala}model.xml{/stala}. - Umieścić w jednym folderze trzy pliki:
wykonany przed chwilą {stala}model.xml{/stala} oraz
{stala}dbd2propel.xsl{/stala} i {stala}transform.php{/stala}. - Odwiedzić przeglądarką skrypt {stala}transform.php{/stala}.
W folderze pojawi się plik {stala}schema.xml{/stala}, który
opisuje model bazy danych w formacie wymaganym
przez aplikację Propel.
Procedurę konwersji można uprościć przygotowując
plik {stala}transform.bat{/stala} o treści:
php -f transform.php
Plik ten należy umieścić w tym samym folderze
co plik {stala}transform.php{/stala}. Wykonanie przekształcenia
sprowadzi się do uruchomienia pliku
{stala}transform.bat{/stala}. Dodatkową korzyścią stosowania
plików wsadowych .bat jest to, że skrypty PHP
mogą być w ten sposób uruchamiane w dowolnym
folderze, a nie tylko w htdocs.
Przykład: piłkarze
Zadanie
Dany jest model bazy danych pilkarze.
Model ten jest zapisany w pliku {stala}pilkarze.xml{/stala}. Wykorzystując
aplikacje DBDesigner oraz Propel należy
przygotować skrypt SQL tworzący podaną
bazę danych oraz napisać skrypt PHP, który wstawi
do bazy danych rekordy:
Grzegorz Bronowicki, Legia Warszawa
Seria artykułów poświęconych bazom danych, które były
opublikowane na łamach MI w ubiegłym roku, pokazywała
w jaki sposób korzystać z programu DBDesigner. Aplikacja
Propel, którą przedstawiłem w ubiegłym miesiącu,
generuje automatycznie klasy aktywnych rekordów. Teraz
opiszę w jaki sposób Propelem generować kod PHP dla
modelu bazy danych przygotowanego DBDesignerem.
Krok 1. Transformacja DBDesigner -> Propel
Najpierw zmieniamy nazwę pliku {stala}pilkarze.xml{/stala}
na {stala}model.xml{/stala}.
Następnie wykonujemy transformację z formatu
DBDesignera do formatu Propela. Na podstawie
pliku {stala}model.xml{/stala} otrzymamy plik {stala}schema.xml{/stala}.
Krok 2. Generowanie kodu SQL i klas PHP
Teraz trzeba przygotować dane dla Propela.
Pierwszym plikiem jest {stala}schema.xml{/stala} otrzymany
w poprzednim kroku jako wynik konwersji pliku {stala}model.xml{/stala}. Ponadto należy przygotować plik
build.properties o zawartości:
propel.project = pilkarze
propel.database = mysql
propel.database.url = mysqli://pilkadm:
secretpass@localhost/pilkarze
propel.targetPackage = pilkarze
propel.addGenericAccessors = true
propel.addGenericMutators = true
oraz plik runtime-conf.xml o zawartości:
mysql
mysqli
localhost
pilkarze
pilkadm
secretpass
Trzy pliki {stala}schema.xml{/stala}, {stala}build.properties{/stala} oraz
{stala}runtime-conf.xml{/stala} umieszczamy w jednym folderze.
W folderze tym należy umieścić także plik
{stala}generuj.bat{/stala} o zawartości:
c:\php\propel\generator\bin\propel-gen.bat.
Teraz folder z danymi dla Propela zawiera
cztery pliki. Można przystąpić
do generowania aktywnych rekordów. Uruchamiamy
plik {stala}generuj.bat{/stala}.
Po wykonaniu pliku wsadowego {stala}generuj.bat{/stala},
w folderze bieżącym pojawi się folder build zawierający
pliki wygenerowane przez Propela.
W folderze build znajdą się trzy foldery:
- folder classes – aktywne rekordy, tj. klasy PHP
dostępu do bazy danych, m.in. klasę Pilkarz
zapisaną w pliku {stala}build\\classes\\pilkarze\\Pilkarz.php{/stala} oraz klasę Klub zapisaną w pliku {stala}build\\classes\\pilkarze\\{/stala} - folder conf – plik konfiguracyjny {stala}build\\conf\\pilkarze-conf.php{/stala},
- folder sql – skrypt SQL tworzący tabele bazy
danych {stala}build\\sql\\schema.sql{/stala}.
Krok 3. Ttworzenie bazy danych
Przygotujemy skrypt SQL o nazwie {stala}pilkarze.sql{/stala}
zawierający instrukcje:
SET NAMES utf8 COLLATE utf8 _ polish _ ci;
DROP DATABASE IF EXISTS pilkarze;
CREATE DATABASE pilkarze DEFAULT CHARACTER
SET utf8 COLLATE utf8 _ polish _ ci;
GRANT
INSERT, DELETE, UPDATE, SELECT
ON
pilkarze.*
TO
pilkadm@localhost
IDENTIFIED BY
\'secretpass\';
FLUSH PRIVILEGES;
USE pilkarze;
Na dole powyższego skryptu (czyli poniżej instrukcji
USE pilkarze;) wklejamy skrypt SQL wygenerowany
przez Propela. Skrypt ten znajdziemy
w folderze build powstałym w poprzednim
kroku: {stala}build\\sql\\schema.sql{/stala}.
Obok skryptu {stala}pilkarze.sql{/stala} umieszczamy skrypt
{stala}pilkarze.bat{/stala} o zawartości:
c:\mysql\bin\mysql -uroot -pAX1BY2CZ3 < pilkarze.sql
Napis AX1BY2CZ3 jest hasłem konta root serwera
MySQL.
Po wykonaniu skryptu {stala}pilkarze.bat{/stala} na serwerze
MySQL powstanie baza danych o nazwie
pilkarze. Sprawdzamy to wykorzystując program
phpMyAdmin. Oczywiście nowo utworzona
baza danych będzie pusta. Liczba rekordów
zawartych w poszczególnych tabelach bazy danych.
Krok 4. Wstawianie rekordów do bazy
Wykonujemy skrypt {stala}wstaw-rekordy.php{/stala} o zawartości:
require _ once \'propel/Propel.php\';
require _ once \'pilkarze/Klub.php\';
require _ once \'pilkarze/Pilkarz.php\';
Propel::init(\'pilkarze-conf.php\');
$klub = new Klub();
$klub->setNazwa(\'Legia Warszawa\');
$pilkarz = new Pilkarz();
$pilkarz->setImie(\'Grzegorz\');
$pilkarz->setNazwisko(\'Bronowicki\');
$pilkarz->setKlub($klub);
$pilkarz->save();
W folderze, w którym znajduje się skrypt
{stala}wstaw-rekordy.php{/stala} umieszczamy plik {stala}pilkarze-conf.php{/stala}wygenerowany przez Propela (kopiujemy
go z folderu {stala}build\\conf\\pilkarze-conf.php{/stala})
oraz folder zawierający klasy dostępu do bazy
danych (kopiujemy cały folder{stala}build\\classes\\pilkarze{/stala}).
Jeśli odwiedzimy przeglądarką skrypt {stala}wstaw-rekordy.php{/stala}, to w bazie danych zostaną zapisane
dwa rekordy: piłkarz Grzegorz Bronowicki
oraz klub Legia Warszawa.
Skrypt {stala}wstaw-rekordy.php{/stala} możemy wykonać
bez wykorzystania przeglądarki. Tworzymy plik
{stala}wstaw-rekordy.bat{/stala} o zawartości:
php -f wstaw-rekordy.php
Plik ten umieszczamy w tym samym folderze
co plik {stala}wstaw-rekordy.php{/stala}. Uruchomienie pliku
wsadowego {stala}wstaw-rekordy.bat{/stala} spowoduje wykonanie
skryptu {stala}wstaw-rekordy.php{/stala}.
Uwagi do pierwszego przykładu
Błąd PHP 5.1
Jeśli korzystamy z PHP w wersji 5.1, to Propel
nie będzie tworzył plików w folderze build\\conf.
W takiej sytuacji plik {stala}pilkarze-conf.php{/stala} należy
utworzyć ręcznie. Rozwiązaniem problemu jest
aktualizacja PHP do wersji 5.2.
Konto i hasło
W plikach:
{stala}build.properties{/stala}
{stala}runtime-conf.xml{/stala}
{stala}pilkarze.sql{/stala}
należy wprowadzić nazwę konta użytkownika
bazy danych oraz hasło. W przykładzie pilkarze
są nimi:
konto: pilkadm
hasło: secretpass
Hasło i konto występują w pliku {stala}pilkarze.sql{/stala}:
...
TO
pilkadm@localhost
IDENTIFIED BY
\'secretpass\';
...
w pliku {stala}build.properties{/stala}:
...
propel.database.url = mysqli://pilkadm:
secretpass@localhost/pilkarze
...
oraz w pliku {stala}runtime-conf.php{/stala}:
...
pilkadm
secretpass
...
Oczywiście we wszystkich trzech plikach należy
użyć identycznego konta.
Nazwa modelu
Podczas zapisywania bazy danych utworzonej
programem DBDesigner nadawana jest nazwa
modelu. Domyślnie nazwa ta jest identyczna jak nazwa pliku. Na przykład, jeśli model zapiszemy
w pliku {stala}studenci.xml{/stala}, to DBDesigner nazwie ten
model studenci.
Nazwę modelu można sprawdzić opcją Options . Model options.
Jeśli plik zapiszemy pod nazwą {stala}model.xml{/stala},
to należy pamiętać o tym, by przy użyciu opcji
Options . Model options zmienić nazwę modelu.
W przeciwnym razie trzeba nazwać bazę
danych model.
Nazewnictwo tabel
Zwróćmy uwagę na nazewnictwo tabel i kolumn
w bazie danych. Nazwy klas generowanych przez
Propela odpowiadają nazwom tabel w bazie danych.
Jeśli w bazie danych występuje tabela pilkarz,
to Propel wygeneruje klasę Pilkarz i zapisze
ją w pliku {stala}Pilkarz.php{/stala}. Podobnie, dla tabeli
klient wygenerowana zostanie klasa Klient zapisana
w pliku {stala}Klient.php{/stala}.
Jeśli tabele bazy danych będą nazwane w mianowniku
liczby pojedynczej, wówczas skrypty
PHP korzystające z klas generowanych przez
Propel będą najczytelniejsze:
Tabela o nazwie: samochod
Wygenerowana klasa: Samochod
Klasa zapisana w pliku: Samochod.php
Skrypt:
$s = new Samochod();
...
Tabela o nazwie: ksiazka
Wygenerowana klasa: Ksiazka
Klasa zapisana w pliku: Ksiazka.php
Skrypt:
$k = new Ksiazka();
...
Metody dostępu do pól
Dla każdej kolumny tabeli tworzone są metody
dostępu do pól. Tabela pilkarz zawiera kolumny:
imie i nazwisko. Propel generuje dla nich metody
{stala}setImie(){/stala} oraz {stala}setNazwisko(){/stala}:
$pilkarz = new Pilkarz();
$pilkarz->setImie(\'Grzegorz\');
$pilkarz->setNazwisko(\'Bronowicki\');
Tabela pilkarz zawiera klucz obcy klub_id. Dla
kluczy obcych Propel również generuje metody
dostępu, w tym przypadku {stala}setKlub(){/stala}. Nazwa metody
pochodzi od nazwy tabeli, z której pochodzi
klucz obcy. Parametrem metody {stala}setKlub(){/stala} jest
obiekt klasy Klub:
$klub = new Klub();
$klub->setNazwa(\'Legia Warszawa\');
...
$pilkarz->setKlub($klub);
Zapisanie w bazie danych piłkarza powoduje
automatyczne zapisanie klubu:
$pilkarz->save();
Podsumowanie
Dla każdej tabeli bazy danych
tworzona jest jedna klasa zawierająca odpowiedni
zestaw metod.
U2
Wykorzystując programy DBDesigner oraz Propel
napiszemy skrypty SQL oraz PHP. Skrypt SQL ma
tworzyć pustą bazę danych, zaś PHP wstawiać
do bazy danych rekordy opisujące piosenkę pt.
\"Sunday Bloody Sunday\" z płyty \"War\":
Płyta: War
Rok wydania: 1983
Utwór: Sunday Bloody Sunday
Czas trwania: 4:38
Numer na płycie: 1
Baza danych zawiera trzy tabele:
plyta (kolumny: rok, tytul, okladka, okladkamini)
utwor (kolumny: tytul, tekst)
plyta _ has _ utwor (kolumny: plyta _ id, utwor _ id, numer, czas)
Propel wygeneruje klasy:
Plyta
setRok()
setTytul()
setOkladka()
setOkladkamini)
Utwor
setTytul()
setTekst()
PlytaHasUtwor
setPlyta()
setUtwor()
setNumer()
setCzas()
Skrypt wstawiający do bazy piosenkę \"Sunday Bloody Sunday\" i płytę \"War\" przyjmie postać:
$plyta = new Plyta();
$plyta->setTytul(\'War\');
$plyta->setRok(1983);
$utwor = new Utwor();
$utwor->setTytul(\'Sunday Bloody Sunday\');
$phu = new PlytaHasUtwor();
$phu->setPlyta($plyta);
$phu->setUtwor($utwor);
$phu->setNumer(1);
$phu->setCzas(\'00:04:38\');
$phu->save();
Artykuły MI
Wykorzystując programy DBDesigner
oraz Propel napiszemy skrypty SQL oraz PHP.
Skrypt SQL ma tworzyć pustą bazę danych, zaś
PHP wstawiać do bazy danych jeden rekord: rubrykę
\"Warsztat\".
Baza danych zawiera m.in. tabelę trubryka
o kolumnach rubryka, liczbaartykulow, liczbastron.
Dla tabeli tej Propel wygeneruje klasę Rubryka
o metodach {stala}setRubryka(){/stala}, {stala}setLiczbaartykulow(){/stala},
{stala}setLiczbastron(){/stala}.
Kod wstawiający rubrykę Warsztat przyjmie postać:
$rubryka = new Trubryka();
$rubryka->setRubryka(\'Warsztat\');
$rubryka->save();
Angaże
Wykorzystując programy DBDesigner
oraz Propel napiszemy skrypty SQL oraz PHP.
Skrypt SQL ma tworzyć pustą bazę danych, zaś PHP wstawiać do bazy danych jeden rekord: wydział
o nazwie \"Lorem Ipsum\" i skrócie LI.
Baza danych zawiera między innymi tabelę
twydzial o polach nazwa i skrot. Dla tabeli tej
Propel wygeneruje klasę Twydzial o metodach
{stala}setNazwa(){/stala} oraz {stala}setSkrot(){/stala}.
Skrypt wstawiający rekord \"Lorem Ipsum\" przyjmie postać:
$wydzial = new Twydzial();
$wydzial->setNazwa(\'Lorem Ipsum\');
$wydzial->setSkrot(\'LI\');
$wydzial->save();
Rock
Wykorzystując programy DBDesigner oraz
Propel napiszemy skrypty SQL oraz PHP. Skrypt
SQL ma tworzyć pustą bazę danych, zaś PHP
wstawiać do bazy danych jeden rekord: osobę
o imieniu Gordon, nazwisku Sumner i pseudonimie
Sting.
Baza danych zawiera między innymi tabelę
tosoba o polach imie, nazwisko, pseudonim. Dla
tej tabeli Propel wygeneruje klasę Tosoba o metodach
{stala}setImie(){/stala}, {stala}setNazwisko(){/stala} oraz {stala}setPesudonim(){/stala}.
Kod wstawiający do bazy danych podany rekord będzie następujący:
$osoba = new Tosoba();
$osoba->setImie(\'Gordon\');
$osoba->setNazwisko(\'Sumner\');
$osoba->setPseudonim(\'Sting\');
$osoba->save();
Podsumowanie
Opisana technika pracy, oparta o programy
DBDesigner oraz Propel, powoduje duży wzrost
wydajności. Przygotowanie modelu bazy danych,
skryptu SQL tworzącego pustą bazę oraz
klas aktywnych rekordów jest niemal całkowicie
zautomatyzowane. Jako test opisanej metody
przetworzyłem bazy danych z kilku artykułów. Jedynymi problemami
jakie napotkałem było nazewnictwo.
Przykłady dalsze
Filmy
Wykorzystując programy DBDesigner oraz Propel
napiszemy skrypty SQL oraz PHP. Skrypt SQL
ma tworzyć pustą bazę danych, zaś PHP wstawiać
do bazy danych rekordy opisujące dwa filmy:
Film: Wielki Gatsby
Rok produkcji: 1974
Aktorzy: Robert Redford, Mia Farrow, Karen Black
oraz
Film: Dom dusz
Rok produkcji: 1993
Aktorzy: Meryl Streep, Jeremy Irons, Glenn Close, Winona Ryder, Antonio Banderas
Model bazy zawiera trzy tabele:
film
aktor
film _ has _ aktor
Zatem Propel wygeneruje klasy:
Film (plik: build\classes\filmy\Film.php)
Aktor (plik: build\classes\filmy\Aktor.php)
FilmHasAktor (plik: build\classes\filmy\FilmHasAktor.php)
Tabela film zawiera kolumny:
film _ id
tytul
rok
Zatem klasa Film będzie zawierała m.in. metody:
setTytul()
setRok()
Tabela aktor zawiera kolumny:
aktor _ id
imie
nazwisko
na ich bazie klasa Aktor otrzyma m.in. metody:
setImie()
setNazwisko()
Natomiast dla tabeli film_has_aktor zostanie
wygenerowana klasa {stala}FilmHasAktor{/stala}. Tabela film_ has_aktor zawiera dwa klucze obce:
film _ id
aktor _ id
Zatem klasa {stala}FilmHasAktor{/stala} będzie zawierała dwie metody:
setAktor()
setFilm()
których parametrami są obiekty klas Aktor i Film.
Skrypt wstawiający rekordy przyjmie postać:
$film = new Film();
$film->setTytul(\'Wielki Gatsby\');
$film->setRok(1974);
$aktor = new Aktor();
$aktor->setImie(\'Robert\');
$aktor->setNazwisko(\'Redford\');
$fha = new FilmHasAktor();
$fha->setFilm($film);
$fha->setAktor($aktor);
$fha->save();