Praca nad nową aplikacją WWW wymaga wypełnienia bazy danych rekordami. Nie możemy przystąpić do testowania, dopóki nie dysponujemy bazą zawierającą hipotetyczne dane, które są zbliżone do danych rzeczywistych. W artykule przedstawię aplikację o nazwie Angaże, skupiając się na efektywnym wypełnieniu bazy danych przykładowymi rekordami.
Aplikacja Angaże
Aplikacja Angaże ułatwia rozdział zajęć dydaktycznych prowadzonych przez pracowników uniwersytetu.
Trzy zasadnicze zadania aplikacji to:
- Przygotowanie zestawienia wszystkich przedmiotów prowadzonych na wybranym kierunku. Zestawienie ma zawierać liczbę grup z każdego przedmiotu oraz obsadę.
- Ustalenie listy wszystkich prowadzonych zajęć dydaktycznych przez wybranego pracownika.
- Przygotowanie zestawienia wszystkich pracowników wraz z obciążeniem godzinowym.
Baza danych
Aplikacja wykorzystuje bazę danych o strukturze jak na rys. 2.
Baza danych zawiera dziesięć tabel. Pięć z nich nie ma kluczy obcych. Pozostałe tabele zawierają od jednego do trzech kluczy obcych.
Utworzenie pustej bazy danych
Pustą bazę danych możemy przygotować na trzy sposoby:
- pisząc skrypt SQL w edytorze tekstowym,
- wykorzystując aplikację phpMyAdmin,
- stosując eksport diagramu bazy danych w postaci skryptu SQL w aplikacji DBDesigner.
W załączonym pliku sql-tworzenie-pustej-bazy.zip zawarty jest skrypt SQL tworzący pustą bazę danych zgodną z diagramem z rys. 2. Po utworzeniu pustej bazy danych możemy przystąpić do wypełniania jej rekordami.
Komentarze w plikach tekstowych
Tekstowe pliki konfiguracyjne wielu programów zawierają komentarze. Przykładami takich plików są httpd.conf (konfiguracja serwera Apache) czy php.ini (konfiguracja PHP). Warto również pliki na podstawie których wypełniamy bazę danych wzbogacić o komentarze. Wszystkie pliki omówione w artykule stosują komentarze w stylu uniksowym: znak # komentuje wszystko aż do końca linii.
Przetwarzanie pliku baz komentarzy ma postać:
$p = file(\'dane.txt\');
$pc = count($p);
for ($i = 0; $i < $pc; $i++) {
$l = explode(\':\', trim($p[$i]));
...
}
Po zastosowaniu komentarzy schemat przetwarzania pliku przyjmuje postać:
$p = trim(file_get_contents(\'dane.txt\'));
$p = uncomment_and_trim($plk);
$p = explode(\"\r\n\", $plk);
$pc = count($plk);
for ($i = 0; $i < $pc; $i++) {
$l = explode(\':\', trim($p[$i]));
...
}
Za usunięcie komentarzy odpowiada funkcja {stala}uncomment_and_trim(){/stala} wykorzystująca wyrażenia regularne.
Wypełnianie tabel bez kluczy obcych rekordami
Najłatwiej wprowadzić do bazy danych rekordy z tabel, które nie mają kluczy obcych. Po odczytaniu informacji z pliku do bazy danych dodajemy odpowiedni rekord.
Tabela twydzial
Tabela twydzial zawiera trzy pola: identyfikator, nazwę i skrót.
W pliku tekstowym wydzialy.txt wprowadzamy w kolejnych liniach dane poszczególnych rekordów. Separatorem w pliku jest znak :. Pierwszym polem jest nazwa wydziału, a drugim - skrót. Identyfikator rekordu pomijamy. Ponieważ pole id ma atrybut {stala}auto_increment{/stala}, silnik bazy danych zajmie się ustalaniem wartości identyfikatorów.
Oto przykładowa zawartość pliku wydzialy.txt:
Wydział Szydełkowania:WS
Wydział Prac Ręcznych:WPR
Wydział Dowcipkowania:WD
Zapytanie SQL dodające do bazy danych nowy wydział ma postać:
INSERT INTO
twydzial (nazwa, skrot)
VALUES
(\'Wydział budownictwa\', \'WB\')
Zatem dodanie wszystkich wydziałów z pliku wydzialy.txt do bazy danych wykonamy pętlą {stala}for{/stala} - listing.
$p = file(\'wydzialy.txt\');
$pc = count($p);
for ($i = 0; $i < $pc; $i++) {
$l = explode(\':\', trim($p[$i]));
$nazwa = mysql_escape_string($l[0]);
$skrot = mysql_escape_string($l[1]);
$q = \"
INSERT INTO
twydzial (nazwa, skrot)
VALUES
(\'$nazwa\', \'$skrot\')
\";
$res = $bd->sendQuery($q);
}
Tabela tpokoj
Tabela tpokoj zawiera trzy pola: identyfikator, numer i telefon.
W pliku tekstowym pokoje.txt zapisujemy odpowiednie dane. Separatorem pól - podobnie jak poprzednio - jest znak :.
Każda linijka pliku opisuje jeden rekord tabeli tpokoje, przy czym pierwszym polem jest numer, a drugim telefon. Tak jak w przypadku tabeli twydzialy, pole id pomijamy.
Przykładowe linie pliku wydzialy.txt mają postać:
20:1220
21:1221
22:1222
Następujące zapytanie SQL doda do bazy danych nowy rekord opisujący pokój 21:
INSERT INTO
tpokoj (numer, telefon)
VALUES
(\'21\', \'1221\')
Wszystkie rekordy z pliku pokoje.txt dodamy wykonując kod z listingu 2.
$p = file(\'wydzialy.txt\');
$pc = count($p);
for ($i = 0; $i < $pc; $i++) {
$l = explode(\':\', trim($p[$i]));
$numer = mysql_escape_string($l[0]);
$tel = mysql_escape_string($l[1]);
$q = \"
INSERT INTO
tpokoj (numer, telefon)
VALUES
(\'$numer\', \'$tel\')
\";
$res = $bd->sendQuery($q);
}
Pozostałe tabele
Wszystkie pozostałe tabele, które nie zawierają kluczy obcych, a więc tstanowisko, trodzajzajec oraz trodzajstudiow, dodamy do bazy danych w identyczny sposób.
Wypełnianie tabel, które zawierają klucze obce
W przypadku tabel, które zawierają klucze obce, procedura wypełniania bazy danych jest nieco inna. Przed dodaniem każdego rekordu do bazy danych musimy ustalić wartości wszystkich kluczy obcych.
Oczywiście najpierw do bazy danych należy dodać wszystkie tabele, do których odwołują się klucze obce. Na przykład przed przystąpieniem do dodawania rekordów z tabeli tkatedra należy dodać do bazy danych zawartość tabeli twydzial (tabela tkatedra ma klucz obcy {stala}twydzial_id{/stala} odwołujący się do tabeli twydzial).
Tabela tkatedra
Tabela tkatedra zawiera jeden klucz obcy: {stala}twydzial_id{/stala}.
Plik tekstowy opisujący katedry nazywa się katedry.txt. Zawiera on trzy kolumny: nazwę katedry, skrót nazwy katedry oraz skrót nazwy wydziału. Pole \"skrót nazwy wydziału\" jest kluczem obcym.
Katedra Historii Szydełkowania:KHS:WS
Katedra Teorii Prac Ręcznych:KTPR:WPR
Katedra Zastosowań Dowcipkowania:KZD:WD
Oto zapytanie SQL, które umieści nowy rekord w tabeli tkatedra:
INSERT INTO
tkatedra (nazwa, skrot, twydzial_id)
VALUES
(\'Katedra Maszynoznastwa\', \'KM\', \'7\')
Problem polega na tym, że w pliku katedry.txt wpisane są skróty nazwy wydziałów (np. WS, WPR, WD), a nie ich identyfikatory. Zatem na podstawie nazwy wydziału musimy ustalić jego identyfikator. Zadanie to realizuje funkcja {stala}podajIdWydzialu(){/stala}:
function podajIdWydzialu($AWydzial)
{
$robq = \"
SELECT
id
FROM
twydzial
WHERE
skrot=\'$Awydzial\'
\";
return $this->getSingleResult($robq);
}
Wykorzystując funkcję {stala}podajIdWydzialu(){/stala} plik katedry.txt przetwarzamy w sposób widoczny na listingu 3.
$p = file(\'katedry.txt\');
$pc = count($p);
for ($i = 0; $i < $pc; $i++) {
$l = explode(\':\', trim($p[$i]));
$nazwa = mysql_escape_string($l[0]);
$skrot = mysql_escape_string($l[1]);
$wydzial = mysql_escape_string($l[2]);
$wydzial_id = $bd->podajIdWydzialu($wydzial);
if ($wydzial_id) {
$q = \"
INSERT INTO
tkatedra (nazwa, skrot, twydzial_id)
VALUES
(\'$nazwa\', \'$skrot\', \'$wydzial_id\')
\";
$res = $bd->sendQuery($q);
} else {
echo \'BŁĄD!\';
}
}
Tabela tkierunek
W tabeli tkierunek znajdziemy dwa klucze obce: {stala}trodzajstudiow_id{/stala} oraz {stala}twydzial_id{/stala}.
Plik kierunek jest bardziej skomplikowany, głównie z tego powodu, że tabela tkierunek zawiera więcej pól.
W kolejnych kolumnach znajdziemy dane: nazwę kierunku, liczbę semestrów, nazwę skróconą, wagę stosowaną do sortowania kierunków, nazwę wydziału (jest to klucz obcy) oraz rodzaj studiów (drugi klucz obcy).
Robótki ręczne:10:Robótki dm:40:WPR:dzienne magisterskie
Żarty i dowcipy:6:Żarty zz:90:WD:zaoczne zawodowe
Humor:4:Humor podypl.:110:WD:podyplomowe
W celu dodania kierunku \"Żartologia\" do bazy danych należy wykonać zapytanie:
INSERT INTO
tkierunek (
nazwa, skrot, lata,
sortowanie, twydzial_id,
trodzajstudiow_id
)
VALUES (
\'Żartologia\', \'Żartologia dm\', \'10\',
\'153\', \'123\', \'456\'
)
W zapytaniu tym występują dwa klucze obce: identyfikator wydziału (123) oraz identyfikator rodzaju studiów (456). Do ustalenia numeru identyfikacyjnego wydziału na podstawie nazwy stosujemy poznaną już funkcję {stala}podajIdWydzialu(){/stala}. Natomiast rodzaj studiów zidentyfikujemy stosując analogiczną funkcję {stala}podajIdRodzajuStudiow(){/stala}:
function podajIdRodzajuStudiow($ARodzajStudiow)
{
$robq = \"
SELECT
id
FROM
trodzajstudiow
WHERE
nazwa=\'$ArodzajStudiow\'
\";
return $this->getSingleResult($robq);
}
Stosując obie wymienione funkcje, dodajemy rekordy do tabeli tkierunek na podstawie pliku kierunki.txt - listing 4.
$p = file(\'kierunki.txt\');
$pc = count($p);
for ($i = 0; $i < $pc; $i++) {
$l = explode(\':\', trim($plk[$i]));
$nazwa = mysql_escape_string($l[0]);
$lata = mysql_escape_string($l[1]);
$skrot = mysql_escape_string($l[2]);
$sortowanie = mysql_escape_string($l[3]);
$wydzial = mysql_escape_string($l[4]);
$rodzajstudiow = mysql_escape_string($l[5]);
$wydzial_id = $bd->podajIdWydzialu($wydzial);
$rodzajstudiow_id = $bd->podajIdRodzajuStudiow($rodzajstudiow);
if ($wydzial_id && $rodzajstudiow_id) {
$q = \"
INSERT INTO
tkierunek (
nazwa, skrot, lata,
sortowanie, twydzial_id,
trodzajstudiow_id
)
VALUES (
\'$nazwa\', \'$skrot\', \'$lata\',
\'$sortowanie\', \'$wydzial_id\',
\'$rodzajstudiow_id\'
)
\";
$res = $bd->sendQuery($q);
} else {
echo \'BŁĄD!\';
}
}
Pozostałe tabele
Jeszcze dwie tabele zawierające klucze obce, tprzedmiot oraz tpracownik, wypełniamy w identyczny sposób.
Tabela tprzedmiot zawiera klucze obce {stala}tkierunek_id{/stala} oraz {stala}trodzajzajec_id{/stala}. Wymaga ona zatem przygotowania dwóch funkcji: {stala}podajIdKierunku(){/stala} i {stala}podajIdRodzajuZajec(){/stala}.
Natomiast tabela tpracownik zawiera trzy klucze obce: {stala}twydzial_id{/stala}, {stala}tpokoj_id{/stala} oraz {stala}tstanowisko_id{/stala}. Wymaga zatem przygotowania jeszcze dwóch funkcji: {stala}podajIdStanowiska(){/stala} oraz {stala}podajIdPokoju(){/stala}. Trzecia z funkcji, {stala}podajIdWydzialu(){/stala}, została już omówiona.
Wypełnianie przydziałów zajęć
Baza danych Angaże nakłada pewne wymagania. Wszystkie zajęcia występujące w tabeli tprzedmiot muszą występować w tabeli tprzydzial.
Przyjmijmy, że w tabeli tprzedmiot występuje przedmiot o nazwie \"ABC Szydełkowania\" w liczbie czterech grup ćwiczeniowych. W takiej sytuacji tabela tprzydzial musi zawierać cztery rekordy dotyczące przedmiotu \"ABC Szydełkowania\": po jednym rekordzie na daną grupę.
Oczywiście zanim przystąpimy do przydzielania zajęć pracownikom, wszystkie zajęcia są nieobsadzone.
Przygotowanie pliku tekstowego opisującego puste przydziały nie miałoby sensu. Podobnie jak nie ma sensu ręczne wprowadzanie pustych przydziałów (jest to ogromna ilość pracy).
Znacznie lepiej wykonać to zadanie w PHP, stosując prostą iterację po wszystkich przedmiotach w bazie danych. A zatem po umieszczeniu w bazie danych przedmiotów, ustalamy ich dane:
$robq = \"SELECT id, liczbagrup FROM tprzedmiot\";
$dane = $bd->sendVerticalQuery($robq);
$danec = count($dane[0]);
Otrzymane przedmioty przetwarzamy w pętli. Każdemu przedmiotowi dodajemy liczbę pustych przydziałów wynikającą z liczby grup - listing 5.
for ($i = 0; $i < $danec; $i++) {
$idprz = $dane[0][$i];
$ilegr = $dane[1][$i];
for ($j = 1; $j <= $ilegr; $j++) {
$robq = \"
INSERT INTO
tprzydzial (tprzedmiot_id, numergrupy)
VALUES
(\'$idprz\', \'$j\')
\";
$wyn = $bd->sendQuery($robq);
}
}
Gotowa baza danych
W ten sposób zakończyliśmy wstępny etap przygotowania angaży pracowników. Zadanie to przebiegło w trzech etapach:
- utworzyliśmy pustą bazę danych,
- dodaliśmy do tabel zawartość plików tekstowych,
- wypełniliśmy tabelę tprzydzial pustymi przydziałami.
Baza danych jest teraz gotowa do pracy. Do przydzielania zajęć poszczególnym pracownikom wykorzystujemy formularze zawarte w interfejsie aplikacji.