2 praca dyplomowa sklep internetowy fixed YQEBDWOZT53SOADIG5SCLTTSVRLYEOS6UCAWVZI

background image

WYŻSZA SZKOŁA

INFORMATYKI I ZARZĄDZANIA

Z SIEDZIBĄ W

R

ZESZOWIE

WYDZIAŁ ADMINISTRACYJNO-INFORMATYCZNY

Kierunek:

INFORMATYKA I EKONOMETRIA

Specjalność:

S

YSTEMY I SIECI KOMPUTEROWE

Autor:

B

ARTŁOMIEJ

S

IĘBAB

I

MPLEMENTACJA

S

YSTEMU

S

KLEPU

I

NTERNETOWEGO

N

A

B

AZIE

O

PROGRAMOWANIA

O

PEN

S

OURCE

PRACA DYPLOMOWA

P

ROMOTOR

DR INŻ

. J

ANUSZ

Ś

WIERZOWICZ

Rzeszów 2001

background image

2

Wstęp

Przedstawiony projekt systemu internetowej sprzedaży towarów jest fragmentem całości
serwisu internetowego firmy. Został on zbudowany przy wykorzystaniu narzędzi

i oprogramowania OpenSource. Korzysta z istniejących w aplikacjach finansowo księgowych

danych, gromadzonych w codziennej działalności przedsiębiorstwa. Za kryterium
podstawowe przyjęto ekonomiczne dostosowanie tworzonych rozwiązań pod kątem

zastosowania takiego modelu sklepu internetowego w firmach małej i średniej wielkości.
Kod aplikacji jest wysoce elastyczny i pozwala na swobodne modyfikowanie zarówno

formatu wejścia danych jak i interfejsu użytkownika oraz wkomponowanie w istniejący

serwis internetowy firmy. Aktualna działająca aplikacja sklepu internetowego znajduje się
pod adresem:

http://www.vt.pl/

gdzie jest użytkowana i stale rozwijana. W rozwój aplikacji

sklepu internetowego oraz całości serwisu firmy duży wkład pracy stale wnosi mój przyjaciel

Radosław Wierzbicki za co niniejszym składam mu podziękowanie.

background image

3

Cel i zakres pracy

Rozdział I omawia założenia wstępne, przedstawia charakter pracy oraz metody i narzędzia
zastosowane w budowie aplikacji. Omówiono tutaj uwarunkowania ekonomiczne

powstającego systemu oraz zaprezentowano bazę systemową oprogramowania.

Rozdział II przedstawia teorię i funkcjonowanie sklepu internetowego, ukazuje wymagania
użytkowników dotyczące działania serwisów internetowych firm. Przedstawia wpływ

marketingu i reklamy na popularność serwisu. Prezentuje zasady działania oraz model
logiczny i funkcjonalny tego typu aplikacji internetowych.

Rozdział III prezentuje przygotowanie danych na potrzeby sklepu internetowego.

Przedstawia sposoby konwersji, archiwizacji i przesyłania danych pomiędzy serwerami
i aplikacjami istniejącymi w przedsiębiorstwie. Pokazuje procedury konwersji i obróbki

danych oraz ich automatyczny załadunek do systemu bazodanowego.

Rozdział IV omawia strukturę i organizację bazy danych sklepu. Prezentuje skrypty
administracyjne i bazodanowe systemu oraz omawia ich budowę i działanie. Przedstawia

podział funkcjonalny konstruowanych podprocedur oraz strukturę bazy SQL.
Rozdział V prezentuje wyszukiwarkę towarów, koncepcję i zasadę działania oraz kod

źródłowy. Omawia napotykane problemy optymalizacji zapytań do bazy danych i sposoby

ich rozwiązywania.
Rozdział VI przedstawia dalsze cele i kierunki rozwoju projektu sklepu internetowego.

Omawia budowę interfejsu rejestracji informacji dodatkowych o towarach oraz model

i zasadę działania „koszyka” na towary. Prezentuje stosowane metody śledzenia
i utrzymywania sesji pomiędzy webserwerem a przeglądarką klienta.

Podsumowanie pracy omawia zebrane podczas budowy projektu wnioski i doświadczenia.

background image

4

Rozdział I – Z

AŁOŻEN IA WSTĘPNE

,

PRZEDSTAWIENIE METOD

I

NARZĘDZI

U

WARUNKOWANIA EKONOMICZNE

W czasach gwałtownego rozwoju Internetu, działalność gospodarcza wkracza w nowy etap

rozwoju. Nowe możliwości jakie stwarza zasięg działania, powszechność oraz dostępność

Internetu inspirują do zainteresowania się rozwojem biznesu na tej platformie. Szczególną
dziedziną, w której jest możliwy szybki rozwój i poszerzenie podstawowej i tradycyjnej

działalności jest handel, rozumiany zarówno jako wymiana pomiędzy partnerami jak
i dostawcami a ich klientami. Rozwój małej i średniej przedsiębiorczości wymaga rozwiązań

dostosowanych do potrzeb tego segmentu działalności komercyjnej. Rynek ten w krajach

Unii Europejskiej czy też w Stanach Zjednoczonych jest określany jako SOHO (Small Office
Home Office). Podstawowym kryterium jest tu wielkość firmy, różnie rozumiana, często

jako ilość zatrudnionych pracowników czy też wielkość generowanych przychodów,

obrotów itp. Jedyną różnicą pomiędzy Polską a innymi krajami Europy Zachodniej jest
właśnie skala według której następuje segmentacja. W Polsce przyjmuje się że średniej

wielkości przedsiębiorstwo zatrudnia ponad dwudziestu pięciu pracowników. Jest to o rząd
wielkości mniejsza liczba niż w innych krajach Unii Europejskiej. Analiza potrzeb takich firm

wykazała, że podstawowym kryterium wyboru rozwiązań informatycznych wspierających

i rozszerzających działalność podstawową są koszty zarówno zakupu, rozwoju jak
i

utrzymania systemów, oprogramowania i administracji. Społeczność internetowa

jednoznacznie wykazuje ogromne zainteresowanie rozwojem oprogramowania i systemów

OpenSource (

www.opensource.org

) zarówno opartych na licencji GNU GPL jak i BSD.

Teksty tych dokumentów umieszczone są pod adresem

www.opensource.org/licenses

Przykładem systemów OpenSource jest np. Linux czy wiele innego doskonałego
oprogramowania określanego wspólną nazwą GNU. Kolejnym elementem jest także cała

rodzina Unix’owych sieciowych systemów operacyjnych *BSD takich jak

FreeBSD (

www.freebsd.org

), NetBSD (

www.netbsd.org

), OpenBSD (

www.openbsd.org

), baz

danych takich jak PostgreSQL

(

www.postgresql.org

), języków programowania jak

PHP (

www.php.net

) i innych. Tendencje te ostatnio znalazły poparcie u „wielkich” rynku

informatycznego. Sun wykupił i udostępnił na licencji GNU pakiet biurowy StarOffice, IBM
przeniósł Linux'a na swoje platformy mainframe, Borland stworzył środowisko

Delphi/Kylix do budowy uniwersalnych aplikacji dla środowiska Windows/Linux oraz

background image

5

udostępnił bazę InterBase itp. Powstała organizacja Free Software Foundation
(

www.fsf.org

) wspierająca ten „ruch” w kierunku dalszego upowszechniania

i popularyzowania tego trendu. Bazując na osiągnięciach społeczności internetowej w tej
dziedzinie za podstawę realizacji systemu umożliwiającego małym i średnim firmom

wkroczenie w sferę e-biznesu przyjęto systemy bazujące na tego typu oprogramowaniu.

P

REZENTACJA BAZY SYSTEMOWEJ OPROGRAMOWANIA

Na podstawę do budowy systemu kompleksowo obsługującego całość działań

komunikacyjnych, sieciowych, aplikacyjnych a jednocześnie zapewniającego wysoki stopień
bezpieczeństwa całego systemu został wybrany system Unix z rodziny BSD. FreeBSD jest

systemem dedykowanym i optymalizowanym do pracy na platformie Intel (IA32) oraz
Alpha. Jest on z powodzeniem stosowany przez największych dostawców usług

internetowych i przeznaczony jest do pracy przy bardzo dużych obciążeniach. Przykładem

jego wykorzystania są serwisy web i email np.

Yahoo.com

lub

Hotmail.com

, największy serwis

ftp

ftp.cdrom.com

czy też rodzimy

Home.pl

. Na serwerze firmy gdzie wykonano wdrożenie

kompletnego środowiska obsługującego całość działalności internetowej zainstalowany

został Unix FreeBSD, serwer pocztowy Qmail (

www.qmail.org

) dedykowany do obsługi

poczty internetowej (nawet do kilku milionów przesyłek dziennie), webserwer

Apache (

www.apache.org

) do obsługi serwisów WWW oraz dostępu do poczty poprzez

przeglądarkę na bazie TWIG (

twig.screwdriver.net

) a także obsługi sklepu internetowego

działającego na bazie PostgreSQL (

www.postgresql.org

), do której dostęp i dynamicznie

budowane strony wykonano w PHP4 (

www.php.net

). Gwałtownie rosnącą popularność tego

języka przedstawia Rysunek 1.

Rysunek 1 – Popularność języka PHP.

background image

6

Serwer internetowy świadczy ponadto wiele innych usług i zabezpieczony został firewallem.
Analogicznie, po stronie wewnętrznego LAN firmy został uruchomiony drugi serwer na

bazie FreeBSD obsługujący kilka podsieci firmy oraz zapewniający dostęp do internetu
z wewnątrz firmy. Na serwerze w celu poprawienia wewnętrznego bezpieczeństwa sieci

również uruchomiono firewall oraz translację adresów. Sieć firmowa oparta jest na stacjach

roboczych z oprogramowaniem MS Windows natomiast na serwerze FreeBSD sieć
Windows jest obsługiwana przez oprogramowanie Samba

(

www.samba.org

).

Oprogramowanie finansowo księgowe stworzone przez firmę Comvar (

www.comvar.com.pl

)

na bazie CA Clipper rezyduje na dyskach sieciowych wewnętrznego serwera i tam
przechowywane są dane. Taka organizacja pozwoliła na wykorzystanie danych firmy do

automatycznego zasilania sklepu internetowego a ponadto udostępniła całej firmie
wymagane usługi internetowe przy minimalnych kosztach, bowiem całe oprogramowanie

serwerów bazuje na OpenSource. Schemat działania całości struktury sieciowej firmy

sprawdził się w ciągu kilku lat jego funkcjonowania i gwarantuje wysoką jakość
i niezawodność działania. Na serwerach dokonywana jest regularna archiwizacja wszystkich

danych firmy a samo środowisko FreeBSD jako wyjątkowo odporne na awarie wydaje się

być wręcz przeznaczone do takich celów. Początkowo wyjściowym systemem był Linux,
jednak problemy występujące z udostępnianiem i poprawną pracą sieci Windows oraz

podatność jego filesystemu (extfs2) na awarie wykluczyła go z dalszego stosowania, gdyż był
on tutaj najsłabszym ogniwem. Strategia ta znalazła późniejsze potwierdzenie w sytuacji, gdy

z przyczyn niezależnych od firmy cała serwerownia na skutek awarii wodociągów w budynku

została doszczętnie zalana wodą. Zniszczeniu uległy zasilacze UPS oraz router Cyclades
obsługujący łącze do internetu poprzez Polpak Frame Relay. Modemy Lucent DSLPipe

obsługujące łącza do zdalnych siedzib firmy na terenie miasta nie zostały uszkodzone.

W serwerach na skutek tej awarii zniszczeniu uległy karty sieciowe. Po wymianie kart
sieciowych w ciągu kilku godzin sieć firmowa przywrócona została do działania a żadne dane

zgromadzone na dyskach serwerów nie uległy uszkodzeniu. Poprzez zastosowanie struktury
skrzynek pocztowych natywnych dla Qmail’a określanej jako Maildir, pomimo awarii

zasilania w trakcie dostarczania poczty do skrzynek nie uległa ona uszkodzeniu. Bieżąca

działalność firmy, po krótkim czasie niezbędnym na wymianę uszkodzonych podzespołów,
mogła być kontynuowana i żadne dane nie uległy zniszczeniu, nie było nawet potrzeby

odzyskiwania ich z kopii zapasowych.

background image

7

Rysunek 2 przedstawia schematyczną strukturę topologiczną sieci firmy:

Internet

zdalne oddziały firmy

siedziba główna firmy

strefa zdemilitaryzowana (DMZ)

Rysunek 2 – Topologia sieci przedsiębiorstwa.

background image

8

Rozdział II – T

EORIA I FUNKCJONOWANIE

W

YMAGANIA UŻYTKOWNIKÓW

Podstawą działania sklepu internetowego są dane o towarach, na bazie których możliwe jest
dalsze jego konstruowanie. W praktyce działania sklepu dane te służą prezentacji

posiadanych produktów przeznaczonych do sprzedaży internetowym kanałem dystrybucji.
Z przeprowadzanych analiz zachowań internautów odwiedzających tego typu serwisy,

charakterystyczna jest zasada, że każda strona musi zostać załadowana w ciągu 7-10 sekund

od próby wejścia do serwisu internetowego. Dłuższy czas „odświetlania” strony zniechęca
internautów i powoduje rezygnację z dalszej eksploracji zasobów firmy. Szybkość transferów

osiągana przez najczęściej wykorzystywane do łączenia z Internetem popularne modemy

gwarantuje przepustowość w zakresie od 3KB/s do 6KB/s, stąd wynika iż ilość danych
wysyłanych przez serwer WWW do przeglądarki klienta nie powinna przekraczać 30KB do

60KB maksymalnie na podstawowe strony firmowe. Specyficzne jest natomiast podejście
internautów do stron specjalizowanych np. z prezentacjami multimedialnymi lub

szczegółowymi danymi technicznymi i użytkowymi produktów, które wzbudziły ich

zainteresowanie i o których chcą uzyskać szczegółowe informacje. Tutaj „cierpliwość”
użytkowników Internetu jest dużo większa, a ich gotowość do „czekania” na załadowanie

strony jest kilku a nawet kilkunastokrotnie większa. Takie strony mogą mieć rozmiary rzędu

100KB i więcej, o ile zbudowane są w taki sposób, że już w trakcie ich ładowania
przeglądarka wyświetla stopniowo ściągane dane. Przy największych stronach konieczne

wydaje się dzielenie prezentowanych informacji na wiele mniejszych fragmentów, po których
użytkownik może swobodnie nawigować za pomocą hyperlinków i różnego rodzaju

statycznych i dynamicznych odsyłaczy. W dobrym tonie jest konstruowanie stron „lekkich”

czyli nie przeładowanych zbędną grafiką ładującą się powoli, a przy odnośnikach do plików
z większymi obrazami czy też plikami multimedialnymi podawanie ich rozmiaru lub

przybliżonego czasu ładowania. Organizacja logiczna i wizualna strony musi być jasna

i przejrzysta dla potencjalnego klienta. Jezyk HTML opisu strony musi być zgodny ze
obowiązującymi standardami i zwyczajami stosowanymi w budowie stron. Występuje

tendencja do takiego budowania strony, aby była możliwa do poprawnej prezentacji nawet
przez najprostsze przeglądarki trybu tekstowego dostępne na platformach unixowych (jak

choćby Lynx, Links czy W3M). Oczywiście należy także wykorzystywać wszelkie nowości jak

skrypty Java czy DHTML jednak w taki sposób, aby zapewnić poprawne interpretowanie

background image

9

strony we wszystkich najpopularniejszych przeglądarkach różnych firm i ich kilku ostatnich
wersjach. Charakterystycznym wydaje się być celowa rezygnacja w wielu serwisach

internetowych ze stosowania ramek i zastąpienie ich tabelami. Sklep internetowy ze względu
na specyfikę swojego działania, musi zapewniać bezpieczeństwo zgromadzonych danych

klientów, szczególnie gdy realizowane są płatności kartami płatniczymi. Stosowanym

standardem jest szyfrowanie transmisji takich danych przy użyciu protokołu SSL. Obecną
tendencją jest także scedowanie obowiązku weryfikacji i autoryzacji kart płatniczych na

zaufaną stronę „trzecią” w osobie organizacji zajmującej się autoryzowaniem transakcji

elektronicznych. Nowością ostatnio wprowadzaną w Polsce przez
PolCard S.A. (

www.polcard.pl

), jako największego krajowego publicznego „operatora”

transakcji kartowych, jest autoryzowanie online takich transakcji, poprzez przekierowanie
transakcji autoryzacji przez sklep do serwera autoryzacji tej firmy. Analiza preferencji

użytkowników dokonujących zakupów online wykazuje jeszcze przeważającą wśród polskich

internautów strategię realizowania płatności „za zaliczeniem pocztowym”, jednak występują
pierwsze oznaki zwiększającego zainteresowania płatnościami kartą płatniczą. Związane jest

to z dużym naciskiem banków i organizowanymi promocjami zarówno przez Visa

International (

www.visa.com

) jak i same banki na promocję i sprzedaż usług

bezgotówkowych. Często karta płatnicza jest obecnie wydawana bez opłat do każdego

zakładanego rachunku konta osobistego a bankowe tabele opłat i prowizji tak konstruowane,
aby niejako „administracyjnie” motywować klientów do korzystania z bezgotówkowych

form płatności.

M

ARKETING I REKLAMA

Ogólna zasada funkcjonowania sklepu internetowego opiera się na kilku filarch. Z jednej

strony jest to baza danych o towarach, katalogach, cennikach itp. informacjach, z drugiej są
to dane gromadzone na podstawie informacji uzyskiwanych od klientów. Wszystko to

wsparte jest analizami i statystykami oglądalności i odwiedzin na firmowych stronach serwisu
webowego. Można analizować liczbę odwiedzin, specyfikę i rodzaje poszukiwanych towarów

i informacji o nich, adresy domen z których następują wejścia oraz charakterystykę czasową

na przestrzeni dnia, tygodnia czy miesiąca lub roku. Podstawą są logi serwera jak i dane
zapisywane w bazie SQL. Analizy te pozwalają przewidywać okresy wzmożonego

zainteresowania konkretnymi produktami jak i umożliwiają na precyzowanie oferty

kierowanej do potencjalnego klienta. To daje duże pole działania w porównaniu do

background image

10

tradycyjnych metod sprzedażowych, gdzie klient pozostaje anonimowy praktycznie aż do
momentu zawarcia konkretnej transakcji. Wsparciem dla strategii marketingowych może być

dobrze zaplanowana akcja reklamowa na bazie banerów reklamowych prezentowanych na
różnych stronach zarówno własnego serwisu jak i na zasadzie wymiany banerowej z innymi.

Wejścia poprzez kliknięcie w baner mogą być analizowane pod kątem charakterystyki

wiekowej klienta. Wiadomo bowiem gdzie dany baner był umieszczony, na jakim serwisie

i jaki jest profil internautów odwiedzających dany serwis. Nikt przecież nie będzie

reklamować drogiego sprzętu RTV na serwisach internetowych przeznaczonych dla
nastolatków. W takim przypadku właściwszym będzie zaprezentowanie sprzętu przenośnego

typu walkman czy discman. Całokształt działań promujących sklep internetowy musi być

wsparty podstawami zarówno psychologicznymi, ekonomicznymi jak i informatycznymi,
mającymi na celu osiągnięcie zamierzonego celu i sukcesu. Prezentowane rozwiązania

umożliwiają rozbudową całego serwisu o różnorakie narzędzia wpierające dział marketingu
firmy w cenne informacje, na których zebranie tradycyjnymi metodami należałoby

Rysunek 3 – Internetowa promocja towarów sklepu.

background image

11

wydatkować zarówno duże środki finansowe jak i poświęcić sporo czasu na badania
marketingowe. Oczywistym jest także fakt, że informacje zebrane tradycyjnymi metodami

przekładają się także na sam sklep internetowy i prezentowaną ofertę. W obecnych czasach
właściwym wydaje się model działalności dodatkowej i uzupełniającej „tradycyjną”

ekonomię handlu podczas prowadzenia tego typu serwisu internetowego. W przypadku

małych i średnich przedsiębiorstw taki model może prowadzić do poszerzenia kontaktu
z potencjalnymi klientami, wyrobienia sobie dobrej marki i pozytywnej opinii wśród klientów

jak i zwiększenia sprzedaży, udziałów w rynku czy też zadowolenia klientów co może mieć

przełożenie na wymierne odnoszone korzyści.

Z

ASADA DZIAŁANIA

Zasada działania sklep internetowego została oparta o model wirtualnego środowiska

pozyskiwania informacji o produktach i w przypadku ich atrakcyjności dla klienta ewentualną

sprzedaż. Zaobserwowane zachowania dowodzą często, że wizyty na stronach służą
uzyskaniu konkretnych informacji o produkcie. Nie zawsze kończą się one zrealizowaniem

transakcji, jednak często klienci przychodzący do „tradycyjnego” sklepu firmowego

powołują się na informacje uzyskane z serwisu webowego firmy. Świadczy to o tym, iż
potencjalny klient chce być dobrze poinformowany zanim skontaktuje się już

z rzeczywistym sprzedawcą a nie jego wirtualnym odpowiednikiem. Jednak transakcje na
droższy sprzęt zawierane są w normalnym sklepie. Tutaj uwidacznia się cel działania takiego

sklepu jako bardziej informujący i promujący konkretny produkt niż nastawiony ściśle na

sprzedaż. Chcąc sprostać temu zadaniu zbudowany od podstaw sklep internetowy
udostępnia klientom wygodną wyszukiwarkę towarów, przeglądanie informacji o towarach,

nowościach i specjalnych ofertach czy promocjach. Często klienci mają już wyrobione zdanie

o konkretnych producentach i starają się dokonywać zakupów sprzętu tylko konkretnie
wybranej serii, modelu czy producenta. W tym celu przeglądarka sklepu została wzbogacona

w możliwość przeglądania tematycznego jak i w oparciu o konkretnego producenta. Chcąc
sprostać tym zadaniom, wymagana była rozbudowa modułu aktualizowania i wprowadzania

informacji dodatkowych o towarach. Oprogramowanie finansowo księgowe firmy nie było

przeznaczone do tego celu i nie udostępniało wymaganych narzędzi. Dane zgromadzone
i przetwarzane w bieżącej działalności firmy doskonale nadawały się do wykorzystania jako

wsad informacyjny o posiadanych towarach, producentach i cenach. Także informacje

o odbiorcach oraz dostawcach pozwalają na uzupełnienie sklepu o moduł kontaktów

background image

12

ze stałymi partnerami handlowymi i rozszerzenie działalności modelu B2C (business-to-
consumer) także o model B2B (business-to-business). Jednocześnie wykorzystanie

posiadanych danych znacząco ułatwia funkcjonowanie sklepu, gdyż są one automatycznie
ładowane do bazy danych sklepu i prezentowane w serwisie webowym firmy bez

konieczności udziału pracowników. Nie jest tu wymagana specjalistyczna wiedza na temat

konstruowania zaawansowanych systemów webowych, gdyż sposób w jaki zostało to
zrealizowane jest uniwersalny i łatwo dostosowywany praktycznie do każdej aplikacji

finansowo księgowej obsługującej podstawową działalność firmy. Zwrotnie informacje ze

sklepu internetowego mogą być w łatwy sposób ładowane do modułu zamówień lub
rezerwacji w firmie, tym samym udostępniając niezbędne informacje do bieżącej działalności

firmy. Chcąc zapewnić wymagane bezpieczeństwo operacji zdecydowano się na model
wsadowego ładowania danych do sklepu oraz jego fizyczne umiejscowienie na odrębnym

serwerze. LAN-serwer lokalny ładuje dane do serwera Internetowego, gdzie są one dalej

odpowiednio obrabiane i przetwarzane a następnie prezentowane w tam zlokalizowanym
serwisie internetowym firmy. Taki logiczny podział zadań pozwolił także na oddzielenie

i rozłożenie obciążeń pomiędzy obydwa serwery uniezależniając wewnętrzną pracę firmy od

obciążenia generowanego przez internautów a także na podniesienie bezpieczeństwa
w przypadku ataków na serwer internetowy. Konieczność zapewnienia ciągłej i bezawaryjnej

pracy wewnętrznego serwera firmy była tutaj zadaniem priorytetowym.

M

ODEL LOGICZNY I FUNKCJONALNY

Opierając się na założeniach wstępnych, stworzony został model działania sklepu
internetowego jak i całokształtu „obecności” firmy w Internecie. Roboczo na wewnętrzne

potrzeby całość oprogramowania obsługującego serwis internetowy firmy otrzymała nazwę

„eMarket”. Działanie całego systemu sprowadza się do przetwarzania różnego rodzaju
danych i komunikacji sieciowej co schematycznie obrazuje Rysunek

4. Założenia

początkowe dotyczące całości systemu doprowadziły do jego logicznej budowy w sensie
topologii sieciowej oraz przepływu danych. Zasoby informacyjne firmy chronione są przed

nieuprawnionym dostępem poprzez system uprawnień zarówno do systemów finansowo

księgowych oraz na niższym poziomie dostępu do plików, katalogów i udostępnionych
drukarek sieciowych. Korzystanie z zasobów Internetu także wymaga odpowiednich

uprawnień. Ostatnia plaga wirusów pocztowych wymusiła rezygnację z mało bezpiecznych

programów pocztowych typu Microsoft Outlook oraz uruchomienie systemu pocztowego

background image

13

w oparciu o webserwer i przeglądarki na bazie oprogramowania TWIG, które zostało
zmodyfikowane i odpowiednio dostosowane do potrzeb firmy. Spowodowało to drastyczne

zakończenie problemów z zawirusowanymi załącznikami aktywującymi się automatycznie na
skutek różnego rodzaju błędów w oprogramowaniu pocztowym firmy Microsoft. Większość

systemów, działających na serwerach firmy korzysta i współpracuje z bazą danych

PostgreSQL. Baza ta została wybrana do zastosowań wymagających dużych obciążeń jako

jedyna obsługująca standardy SQL takie jak: zaawansowane transakcje i złączenia tabel,

sekwencje, triggery, wbudowany język konstruowania funkcji i procedur uruchamianych po
stronie samej bazy danych i wiele innych nowoczesnych metod. Z bazą współpracuje

webserwer Apache, na którym wykonują się skrypty PHP generujące dynamicznie strony

korzystając ze zgromadzonych danych. Na serwerze wewnętrznym firmy cyklicznie
uruchamiają się procesy pobierające dane z baz systemu finansowo księgowego. Dane są

wstępnie konwertowane i

przygotowywane do załadowania do bazy PostgreSQL.

Wykonywana jest konwersja strony kodowej ze standardu cp852 na iso-8859-2 a gotowe do

załadunku zbiory są przesyłane na serwer internetowy firmy. Więcej informacji na temat

standardów kodowania polskich znaków można znaleźć na Polskiej Stronie
Ogonkowej (

www.agh.edu.pl/ogonki

). Tu następuje załadunek poszczególnych zbiorów do

tabel w bazie danych. Wykonywane jest indeksowanie poszczególnych pól i w tym

momencie kończy się faza dostarczenia danych dla potrzeb sklepu. Schematycznie całość
tych procesów przedstawia Rysunek 5.

Taka logiczna organizacja przepływu danych jest jakby naturalna dla topologicznej
organizacji sieci firmy jak i specyfiki działania samego oprogramowania finansowo

Zasoby sprzętowe systemów

Zbiory danych i dokumentów

Przetwarzanie

danych

Rysunek 4 – Schemat przetwarzania danych.

background image

14

księgowego. Rozdzielenie funkcji wstepnego przygotowania danych od ich prezentowania
pozwoliło na zachowanie bezpieczeństwa zasobów zgromadzonych na wewnętrzym

serwerze firmy poprzez ich fizyczne oddzielenie od warstwy aplikacji internetowych. Dalsza
ich prezentacja obciąża serwer internetowy i nie zakłóca działania sieci wewnętrznej. Nawet

w przypadku ewentualnej awarii czy ingerencji w zasoby serwera internetowego, maszyna

“produkcyjna” kontynuuje normalne działanie bez wpływu na bieżącą pracę firmy.

Pliki DBF systemu F/K

Konwersja danych

Załadowanie do bazy SQL

Wewnętrzny serwer firmy

Internetowy serwer firmy

Rysunek 5 – Schemat procesu obiegu informacji.

background image

15

Rozdział III – P

RZYGOT OWANIE DANYCH

KONWERSJA DANYCH

Aplikacja finansowo księgowa firmy napisana w Clipperze 5.3 przechowuje dane w postaci
plików DBF. Struktura katalogów samej aplikacji zorganizowana jest w postaci katalogu

systemu podstawowego oraz podkatalogów poszczególnych magazynów. Na podstawie

analizy przechowywanych w poszczególnych plikach danych

określono że wstępnie na potrzeby sklepu internetowego

potrzebnych będzie kilka tabel z systemu podstawowego oraz ze
wszystkich poszczególnych magazynów. Rysunek 6 przedstawia

fizyczną organizację aplikacji na dysku sieciowym widzianą od

strony użytkowników sieci Windows a z drugiej strony od
wewnątrz serwera. Z poziomu użytkownika widziana jest struktura

katalogów począwszy od wnętrza katalogu „sklep” bowiem tak
udostępniony zasób Samby jest mapowany jako dysk logiczny.

Położenie całości aplikacji magazynowej na dyskach serwera umożliwiło dostęp do tych

danych pod kątem ich konwersji dla sklepu internetowego, bez zbędnego obciążania sieci
wewnętrznej transferami a jedynie obróbką samych danych na poziomie serwera. W celu

zapewnienia integralności danych konwersja wykonuje się automatycznie w godzinach

nocnych, tak aby to nie kolidowało z działalnością firmy a jednocześnie zapewniało
aktualność danych. Charakter działania aplikacji magazynowej wymusił takie przystosowanie

modułu konwersji do struktury katalogów, aby dodanie kolejnych magazynów automatycznie
zapewniało pobieranie danych także z nich.

W celu konwersji z formatu DBF do formatu tekstowego rozpatrywano dwa warianty.

Pierwszy opierał się na konwersji skryptem napisanym w języku Perl natomiast drugi
zakładał wykorzystanie gotowego i wielokrotnie szybszego programu w języku C którego

autorem jest Brad Eacker a kod był opublikowany w 1994r w grupach USENET.

Ostatecznie przeważyła szybkość konwersji nad elastycznością rozwiązania w Perlu. Chcąc
jednak zachować możliwość dostosowywania „wyciąganych” danych z tabel DBF, wyjściowe

pliki po kompletnej konwersji DBF na TXT obrabiane są już skryptem shellowym
napisanym z wykorzystaniem natywnych unixowi narzędzi takich jak awk czy tr. Poniższy

listing prezentuje ten skrypt opatrzony komentarzami wyjaśniającymi wykonywane działania:

Rysunek 6 - Katalogi.

background image

16

#!/bin/sh

echo Subject: Konwersja baz eMarket
echo
echo Przygotowanie baz z MGZ do zasilenia bazy SQL eMarket....

# maska tworzenia plików z prawami odczyt/zapis dla wlasciciela i odczyt dla grupy
umask 027

# parametry poczatkowe, sciezki oraz zmienne:
KAT_MGZ='/work/sklep/MGZ2'
KAT_TMP='/bofh/bazy/emarket/tmp'

# sciezka do programu AnsiC konwersji dbf2lst
DBFLST='/bofh/bazy/emarket/bin/dbflst'

#echo Kasowanie starych zbiorow po poprzedniej konwersji
rm -f /bofh/bazy/emarket/tmp/*.LST
rm -f /bofh/bazy/emarket/tmp/*.IN

echo -n Start wstepnej konwersji zbiorkow zasilajacych glownych
$DBFLST $KAT_MGZ/CENNIK.DBF >$KAT_TMP/CENNIK.LST && echo -n .
$DBFLST $KAT_MGZ/CENY_DEW.DBF >$KAT_TMP/CENY_DEW.LST && echo -n .
$DBFLST $KAT_MGZ/ODBIORCY.DBF >$KAT_TMP/ODBIORCY.LST && echo -n .
$DBFLST $KAT_MGZ/DOSTAWCY.DBF >$KAT_TMP/DOSTAWCY.LST && echo .

echo -n Start konwersji zbiorkow stanow magazynowych
if [ -f $KAT_TMP/MAGAZYN.LST ] ; then
rm $KAT_TMP/MAGAZYN.LST
fi

# wykonujemy w petli przebieg po wszystkich katalogach magazynow
for MAGAZYN in `ls -d $KAT_MGZ/MAG_??` ; do
$DBFLST $MAGAZYN/MAGAZYN.DBF >>$KAT_TMP/MAGAZYN.LST && echo -n .
done

echo -n Wycinamy wymagane pola z rekordow
# i jak poszlo dobrze to kasujemy niepotrzebne *.LST

# konwersja pliku nazw towarow
cat $KAT_TMP/CENNIK.LST | awk -F\| 'ORS=""{}

{printf "%i", $2}
{gsub(" ", "", $3)} {print "|"toupper($3)}
{gsub(" ", "", $6)} {print "|"toupper($6)"|"}
{printf "%i", $7} {print "|"}
{printf "%G", $15} {print "\n"}' >$KAT_TMP/CENNIK.IN && \

rm $KAT_TMP/CENNIK.LST && echo -n .

# konwersja pliku cen towarow
cat $KAT_TMP/CENY_DEW.LST | awk -F\| 'ORS=""{}

{printf "%i",$2}{print "|"}
{printf "%G",$6}{print "|"}
{print $7"\n"}' >$KAT_TMP/CENY_DEW.IN && \

rm $KAT_TMP/CENY_DEW.LST && echo -n .

# konwersja pliku danych o dostawcach
cat $KAT_TMP/DOSTAWCY.LST | awk -F\| 'ORS=""{}

{printf "%i",$2}{print "|"}
{gsub(" ", "", $5)}{print toupper($5)"|"}
{gsub(" ", "", $6)}{print toupper($6)"|"}
{gsub(" ", "", $7)}{print toupper($7)"|"}
{gsub(" ", "", $8)}{print toupper($8)"|"}
{gsub(" ", "", $9)}{print toupper($9)"|"}
{gsub(" ", "", $10)}{print toupper($10)"|"}
{gsub(" ", "", $11)}{print toupper($11)"|"}
{gsub(" ", "", $12)}{print toupper($12)"|"}
{gsub(" ", "", $14)}{print $14"\n"}' >$KAT_TMP/DOSTAWCY.IN && \

rm $KAT_TMP/DOSTAWCY.LST && echo -n .

# konwersja pliku danych o odbiorcach
cat $KAT_TMP/ODBIORCY.LST | awk -F\| 'ORS=""{}

{printf "%i",$2}{print "|"}
{gsub(" ", "", $5)}{print toupper($5)"|"}
{gsub(" ", "", $6)}{print toupper($6)"|"}
{gsub(" ", "", $7)}{print toupper($7)"|"}
{gsub(" ", "", $8)}{print toupper($8)"|"}
{gsub(" ", "", $9)}{print toupper($9)"|"}

background image

17

{gsub(" ", "", $14)}{print $14"\n"}' >$KAT_TMP/ODBIORCY.IN && \

rm $KAT_TMP/ODBIORCY.LST && echo -n .
# konwersja pliku cen towarow
cat $KAT_TMP/MAGAZYN.LST | awk -F\| 'ORS=""{}

{printf "%i",$2}{print "|"}
{gsub(" ", "", $6)}{print $6"|"}
{printf "%G",$14}{print "|"}
{printf "%G",$18}{print "\n"}' >$KAT_TMP/MAGAZYN.IN && \

rm $KAT_TMP/MAGAZYN.LST && echo -n .

# ustalamy prawa do plikow po konwersji
chmod u+rw-x,g+rw-x,o-rwx $KAT_TMP/CENNIK.IN
chmod u+rw-x,g+rw-x,o-rwx $KAT_TMP/CENY_DEW.IN
chmod u+rw-x,g+rw-x,o-rwx $KAT_TMP/MAGAZYN.IN
chmod u+rw-x,g+rw-x,o-rwx $KAT_TMP/DOSTAWCY.IN
chmod u+rw-x,g+rw-x,o-rwx $KAT_TMP/ODBIORCY.IN

echo
echo Zbiorki po konwersji zajmuja\:
echo
echo "KB: Nazwa:"
du -k $KAT_TMP/*.IN
echo

echo Upload plikow dla bazy emarket
cd /bofh/bazy/emarket/tmp
echo Zaczynamy transfer...

# wywolujemy skrypt ftp transfer na podstawie listy polecen
ftp -p < /bofh/bazy/emarket/tmp/transfer

echo Zaladowane.

ARCHIWIZACJA I PRZESYŁANIE DANYCH

Skrypty są wywoływane cyklicznie co noc wykonując wstępne przygotowanie danych oraz
ich przesłanie przy pomocy ftp na serwer internetowy, gdzie następuje dalsza faza obróbki

danych i ich ładowanie do PostgreSQL. Oprócz skasowania starych zbiorów i wkopiowania
na ich miejsce nowych wykonywana jest także archiwizacja. Przy pomocy poniższej listy

poleceń skryptu „transfer” dane przekazywane są protokołem ftp na serwer internetowy:

open inet-serwer
bin
cd /home/bazy/emarket/tmp

del /home/bazy/emarket/tmp/CENNIK.IN
del /home/bazy/emarket/tmp/CENY_DEW.IN
del /home/bazy/emarket/tmp/DOSTAWCY.IN
del /home/bazy/emarket/tmp/MAGAZYN.IN
del /home/bazy/emarket/tmp/ODBIORCY.IN

put /bofh/bazy/emarket/tmp/CENNIK.IN /home/bazy/emarket/tmp/CENNIK.IN
put /bofh/bazy/emarket/tmp/CENY_DEW.IN /home/bazy/emarket/tmp/CENY_DEW.IN
put /bofh/bazy/emarket/tmp/DOSTAWCY.IN /home/bazy/emarket/tmp/DOSTAWCY.IN
put /bofh/bazy/emarket/tmp/MAGAZYN.IN /home/bazy/emarket/tmp/MAGAZYN.IN
put /bofh/bazy/emarket/tmp/ODBIORCY.IN /home/bazy/emarket/tmp/ODBIORCY.IN
ls
bye

Wyniki wykonania całej operacji są „wyświetlane” na standardowe wyjście (stdout)

a następnie wysyłane pocztą email do administratora. Pozwala to na kontrolę poprawności
działania całej operacji, gdyż odbywa się ona bezobsługowo. Cykliczność wykonania tych

działań realizowana jest dwoma wpisami w pliku konfiguracyjnym crontab. Zapewniają one

background image

18

oprócz konwersji i przekazania danych na serwer internetowy także archiwizację całości
systemów finansowo księgowych firmy i umieszczenie ich w katalogu udostępnionym

obsłudze w celu przegrania na wymienne nośniki:

# zrob archiwizacje codziennie po dniu roboczym o 3:00 w nocy
#minute hour mday month wday what
0 3 * * 1,2,3,4,5,6 /bofh/bin/archiwizacja 2>&1 | /usr/sbin/sendmail operator
# zrob konwersje i przekazanie danych o 20:00
0 20 * * 1,2,3,4,5,6 /bofh/bazy/emarket/konwersja 2>&1 | /usr/sbin/sendmail operator

Archiwizacja wykonywana jest poniższym skryptem przygotowującym paczkę do
przekopiowania na nośniki wymienne:

#!/bin/sh
# odpalane z crona codziennie w nocy
echo "Subject: Status archiwizacji"
echo
echo Archiwizacja...

dladaty=`date "+20%y%m%d"`
echo $dladaty

# przygotowanie ksiegowosci
echo KSH
cd /work/ksieg
tar -czf /home/archiwa/ksz$dladaty.tgz ./KSH2/*
echo OK.

# przygotowanie magazynow
echo MGZ
cd /work/sklep
tar -czf /home/archiwa/mzz$dladaty.tgz ./MGZ2/*
echo MGZ OK.

echo Archiwa zajmuja obecnie\:
echo KBytes Nazwa pliku
du -k /home/archiwa/
echo Zajetosc dyskow\:
df -ki
echo KONIEC

S

TRUKTURA KONWERTOWANYCH PLIKÓW

W celu wykonania operacji konwersji danych na potrzeby sklepu internetowego poddano

analizie zawartość poszczególnych plików DBF systemów magazynowych. Wyodrębniono
przydatne tabele i na ich podstawie określone pola niezbędne dla działania sklepu. Poniższy

fragment każdego z plików przekazywanych do zaimportowania do bazy SQL obrazuje jakie
dane są wykorzystane z systemów finansowo księgowych firmy:

# Fragment pliku CENNIK.IN
# struktura pliku:
# ind | nazwa towaru cp852 | ozn. producenta | stan | VAT

167636|UCHWYT ZEZ+OBEJMA FI 40|UCHWYT ZEZ+OBEJMA |16|22
982027|YAMAHA RX-V 520 AMPLITUNER AV TI.|YAMAHA RX-V520 TI.|17|22
300405|KAMERA PANASONIC NV-DS27 EG|PANASONIC NV-DS27 |57|22
300052|TELEWIZOR PANASONIC TX 29 AS10P|PANASONIC TX 29 AS|78|22
300051|MAGNETOWID PANASONIC NV-FJ 762 EE|PANASONIC NV-FJ762|78|22
300050|MAGNETOWID PANASONIC NV-FJ 622 EE|PANASONIC NV-FJ622|78|22
51102|PANASONIC RT-60MC MIKROKASETA|PANASONIC RT-60MC |5|22

background image

19

# Fragment pliku CENY_DEW.IN
# struktura pliku:
# ind | cena netto | symbol waluty

330055|1146.72|ZLP
110003|548.36|ZLP
140021|1638.52|ZLP
167636|14.75|ZLP
500018|10.66|ZLP
51102|6.56|ZLP

# Fragment pliku DOSTAWCY.IN oraz ODBIORCY.IN
# struktura pliku:
# ind | nazwa krotka | nazwa dluga | adres1 ... adres6 | nip

1|WIZJA TV |WIZJA TV|UL.PAWINSKIEGO 5A/BLOK D|02-106 WARSZAWA |||||113-15-59-441
28|PHILIPS AGD|PHILIPS POLSKA SP Z.O.O.|02-222 WARSZAWA |AL. JEROZOLIMSKIE 195 B |||||526-021-09-55
43|THOMSON|THOMSON CONSUMER ELECTRONIC POLAND|UL OKULICKIEGO 7/9|05 - 500 PIASECZNO|||||123-00-05-409

# Fragment pliku MAGAZYN.IN
# struktura pliku:
# ind | data | stan dyspozycyjny | stan ksiegowy

240029|20010528|2|2
270018|20010703|28|28
270015|20010628|19|19

K

ONWERSJA STRONY KODOWEJ

Dane rejestrowane w systemie finansowo księgowym firmy są danymi „brudnymi” pod
względem historycznie stosowanych kodowań, poczynając od standardu polskich znaków

Mazovia poprzez Latin i inne a kończąc na cp852. Koniecznym było dokonanie konwersji
tych danych do jednolitego formatu jednak różnorodność stacji roboczych oraz ich

wykorzystanie do różnych celów wykluczała wykonanie tego na głównych danych firmy oraz

na zastosowanie jednakowego kodowania na wszystkich końcówkach. Konwersją polskich
znaków został „obarczony” serwer internetowy, gdzie wykonywana jest ona przed

wczytaniem danych do bazy SQL. Skrypt konwertujący jest uniwersalnym narzędziem

napisanym przez tragicznie zmarłego w 1996r dziennikarza Krakowskiej Gazety Wyborczej
Andrzeja Górbiela (

http://studweb.euv-frankfurt-o.de/twardoch/f/pl/comp/gorbiel/

).

Poniższy listing przedstawia tego skryptu:

#!/bin/sh
#
# plconv - filtr do konwersji polskich znakow diakrytycznych
#
# (c) 1994 Andrzej Gorbiel <A.Gorbiel@Ga-Wyb.Krakow.PL>
#
# a, c' e, l\ n' o' s' z' z. A, C' E, L\ N' O' S' Z' Z~
MAZ="\206\215\221\222\244\242\236\246\247\217\225\220\234\245\243\230\240\241"
LAT="\245\206\251\210\344\242\230\253\276\244\217\250\235\343\340\227\215\275"
WIN="\271\346\352\263\361\363\234\237\277\245\306\312\243\321\323\214\217\257"
ISO="\261\346\352\263\361\363\266\274\277\241\306\312\243\321\323\246\254\257"
TXT="acelnoszzACELNOSZZ"
MAZTAB="\206\215\221\222\244\242\236\246\247\217\225\220\234\245\243\230\240\241\277\263\
300\301\302\303\304\305\331\332\264"
ISOTAB="\261\346\352\263\361\363\266\274\277\241\306\312\243\321\323\246\254\257\53\174\53\
53\55\174\55\53\53\53\174"

ShowHelp ()
{
echo "Uzycie: $0 standard_we standard_wy [ < plik wejsciowy > plik wyjsciowy]"

background image

20

echo " dopuszczalne standardy:"
echo " MAZ - Mazovia"
echo " LAT - Latin-2 (MS-DOS CP 852)"
echo " WIN - Windows ANSI (CP 1250)"
echo " ISO - ISO Latin-2 (CP 8859/2)"
echo " TXT - ASCII (7-bit)"
exit
}

SetStd ()
{
case $1 in

MAZ) std=$MAZ;;
LAT) std=$LAT;;
WIN) std=$WIN;;
ISO) std=$ISO;;
TXT) std=$TXT;;
MAZTAB) std=$MAZTAB;;
ISOTAB) std=$ISOTAB;;
*) ShowHelp; exit;;

esac
}

if [ $# != 2 ]; then ShowHelp; fi

SetStd $1
std1=$std
SetStd $2

tr "$std1" "$std"

Z

AŁADOWANIE DANYCH DO BAZY

P

OSTGRE

SQL

Pliki w formacie tekstowym wczytywane są po ich otrzymaniu z serwera wewnętrznego
firmy. W tym momencie wykonywana jest konwersja kodowania na stronę kodową iso88592

(obowiązujący standard kodowania polskich znaków na stronach www tzw. iso-latin2).
Proces ten wywoływany jest również jako cykliczne zadanie w crontab’ie następującym

wpisem w plik konfiguracyjny:

# zasilenie dla emarket codziennie o 20:30
30 20 * * 1,2,3,4,5,6,7 /home/bazy/emarket/zaladunek 2>&1 | /var/qmail/bin/qmail-inject

Skrypt „załadunek” zbudowany jest podobnie jak skrypt konwersji danych na maszynie

wewnętrznej i wykonywane działania wyświetla na standardowe wyjście (stdout) co jest
poprzez sposób wywołania w corntab wysyłane jako raport do operatora. Jedyną różnicą

w wywołaniu skryptu jest to, iż działa on na tej samej maszynie na której zainstalowany
został system pocztowy Qmail i dlatego można było wykorzystać jeden z pocztowych

programów usługowych do dostarczenia poczty bezpośrednio do adresata. Działania takie

maja na celu informowanie obsługi lub administratorów o wszelkich występujących
problemach a także o powodzeniu każdego z etapów działania sklepu internetowego.

Poniższy skrypt prezentuje działania wykonywane w czasie importowania danych do bazy

PostgreSQL:

background image

21

#!/bin/sh

echo "From: zaladunek <operator@localhost>"
echo "To: operator"
echo "Subject: Zaladowanie danych do bazy eMarket."
echo

# zdefiniowanie polozenia katalogow roboczych
KAT_TMP='/home/bazy/emarket/tmp'
PATH=$PATH:/usr/local/pgsql/bin ; export PATH
BINARIA='/home/bazy/emarket'
cd $BINARIA

#echo Sprawdzenie czy sa sciagniete pliki zasilajace...

pliki=`ls $KAT_TMP/*.IN | wc -l`

if [ $pliki != 5 ] ; then
echo Brak pliku zasilajacego.
echo Sa tylko te...
echo
ls -l $KAT_TMP/*.IN
echo
echo STOP.
exit 1
fi

echo Jest wszystkie $pliki plikow...
echo
ls -l $KAT_TMP/*.IN
echo

# konwersja strony kodowej
echo Konwersja pl znakow na ISO
($BINARIA/bin/plznaki LAT ISO < $KAT_TMP/CENNIK.IN > $KAT_TMP/CENNIK.PL) && \
mv $KAT_TMP/CENNIK.PL $KAT_TMP/CENNIK.IN && chmod a+r $KAT_TMP/CENNIK.IN

# data i czas rozpoczecia zaladunku
echo Zaczynamy o `date`

# ustawienie znacznika zaladunku do bazy
# skrypty php sklepu blokuja dostep do bazy w przypadku
# wykrycia obecnosci tego pliku na czas zaladunku danych
echo Tymczasowe zablokowanie dostepu do bazy...
touch $KAT_TMP/emarket.tmp

# 90-usuntabele
$BINARIA/90-usuntabele

# 20-zaloztabele
$BINARIA/20-zaloztabele

# 30-zaladujtabele
$BINARIA/30-zaladujtabele

# 40-zalozindeksy
$BINARIA/40-zalozindeksy

# 40-zaladujkatalog
$BINARIA/40-zaladujkatalog

# 45-optymalizuj
$BINARIA/45-optymalizuj

# 50-statystyka
$BINARIA/50-statystyka

echo Konczymy o `date`
echo Odblokowanie dostepu do bazy...

rm $KAT_TMP/emarket.tmp

echo
echo Koniec ladowania.

background image

22

Etapy załadunku danych do bazy zostały podzielone na osobne funkcjonalne części,
co ułatwia ewentualne diagnozowanie nieprawidłowości oraz dalszy rozwój tego

oprogramowania. Każdy ze skryptów wykonujących działania na bazie PostgreSQL otrzymał
nazwę zbudowaną z początkowych dwóch cyfr oznaczających jego logiczną kolejność

w wykonaniu, analogicznie jak to ma miejsce w przypadku skryptów startowych w systemach

UNIX typu SysV 4.2 gdzie takie uporządkowanie występuje oraz w systemach BSD
w skryptach administracyjnych (daily, weekly, monthly itp.). Omówienie poszczególnych

skryptów SQL zostało umieszczone w kolejnych rozdziałach traktujących o samej strukturze

bazy danych. Wspomnieć należy, iż aby wykorzystywać bazę danych PostgreSQL,
administrator bazy założył odpowiednich użytkowników bazy z hasłami dostępu

i uprawnieniami pozwalającymi na czynności administracyjne. Głównym plikiem
konfiguracyjnym PostgreSQL regulującym dostęp określonych użytkowników z określonych

hostów jest plik konfiguracyjny „pg_hba.conf”. Dokładnie omawia to dokumentacja

PostgreSQL (

www.postgresql.org/idocs/index.php?client-authentication.html

). Sposób

autoryzacji (czy system wymaga hasła czy też nie) jest definiowany w tym pliku. Na jego

końcu przy domyślnej konfiguracji znajdują się wpisy:

local all trust
host all 127.0.0.1 255.255.255.255 trust

Oznaczają one, że dla połączeń lokalnych (local) - czyli takich, gdzie łączymy się nie

korzystając z socket’ów tcpip i dla dowolnej bazy (all), system ma przyjąć regułę nie pytania

o hasło (trust) natomiast dla połączeń zdalnych, ale tylko z maszyny o adresie 127.0.0.1 (czyli
z tego samego hosta, ale przez sockety tcpip), będzie obowiązywać ta sama reguła. Aby to

zmienić należy zastąpić ostatnie słowo (trust) na "password" lub "crypt" (różnią się one
metodą przesyłania hasła). Przykładowo zapis:

host all 192.168.1.10 255.255.255.0 password

Oznacza, że osoby łączące się z serwera o adresie 192.168.1.10 oraz z całej klasy C (czyli
w rzeczywistości adres ip może być typu 192.168.1.*) muszą podać hasło aby dostać się do

dowolnej bazy. Chcąc wymusić aby wzorcowy szablon bazy PostgreSQL był także

chroniony można dokonać zapisu:

host template1 192.168.1.10 255.255.255.0 password

co oznacza, że te same osoby będą mogły teraz dostać się tylko do bazy template1 i będą
musiały podać hasło. Metod autoryzacji użytkowników jest wiele, między innymi także na

podstawie protokołu ident. Przy pisaniu reguł dostępu należy pamiętać o kolejności. Zawsze

użyta zostanie ta reguła która jest pierwsza w pliku i pasuje do sytuacji (regułki
przeszukiwane są w kolejności od początku do końca pliku aż do znalezienia pierwszej

background image

23

pasującej i na tym się kończy przeszukiwanie). Poniższy zapis byłby błędny, pozbawiony
sensu poprzez swoją błędną hierarchię:

local all trust
host all 127.0.0.1 255.255.255.255 trust
local template1 password
host template1 127.0.0.1 255.255.255.255 password

Poprawnej konfigurację tej access listy przedstawia przykładowy zapis:

local template1 password
host template1 127.0.0.1 255.255.255.255 password
local all trust
host all 127.0.0.1 255.255.255.255 trust

W przypadku konfiguracji rzeczywistej sklepu wpisy dopuszczające ustalają dostęp do bazy
sklepu nazwanej jako „emarket” tylko i wyłącznie z serwera na którym działa sklep oraz dla

określonego użytkownika z hasłem. Zapewnia to już zwiększony poziom bezpieczeństwa

poprzez odrzucenie przez silnik bazy danych połączeń pochodzących zarówno od
użytkowników lokalnych serwera jak i zdalne próby nawiązania połączeń (choć to także

zabezpiecza zastosowany firewall). PostgreSQL zapewnia ponadto zabezpieczenia dostępu

do tabel zgodnie ze standardem SQL92 (

www.postgresql.org/idocs/index.php?sql.html

).

Na zasadzie przywilejów na konkretne działania i operacje na krotkach, tabelach, indeksach,

procedurach czy funkcjach. Można tu bardzo precyzyjnie określać co, kto jak i kiedy może
uczynić ze zgromadzonymi danymi, czy może tylko czytać nasze dane czy też usuwać,

poprawiać, dodawać nowe itp.

background image

24

Rozdział IV – S

TRUKTU RA I ORGANIZACJA BAZY EMARKET

S

KRYPTY ADMINISTRACYJNE

Chcąc zautomatyzować czynności tworzenia i uruchomienia samej bazy, a także jej zasilania
danymi na potrzeby sklepu napisano skrypty powłoki wywołujące określone działania

w bazie danych. Proces zasilania danymi sterowany jest głównym skryptem wywołującym
poszczególne pod-skrypty odpowiedzialne za pewne fragmenty działania poszczególnych

zadań zasilania w dane całej bazy. Niektóre z nich uruchamiane są jednorazowo w momencie

tworzenia bazy lub też jej kasowania. Inne pozwalają na wykonanie pewnych analiz
(na obecnym etapie rozwoju aplikacji jedynie w minimalnym zakresie). Większość danych

ładowana jest bez natychmiastowego indeksowania co znacząco przyśpiesza całą operację.

Dopiero po załadowaniu danych do tabel następuje zaindeksowanie wszystkich wymaganych
pól w konkretnych tabelach. Na samym końcu wykonywana jest „odkurzenie” bazy

pozwalająca PostgreSQL’owi na empiryczną i statystyczną optymalizację wyszukiwania
danych. Poniższe zestawienie prezentuje i omawia wywołania wszystkich skryptów.

#!/bin/sh
# skrypt 20-zaloztabele
#
echo Zalozenie tabel bazy emarket SQL...
#

KAT_SQL='/home/bazy/emarket/sql'
SQL='/usr/local/pgsql/bin/psql -d emarket -q -f'

echo

echo cennik...
$SQL $KAT_SQL/create/create_table_cennik.sql

echo cenydew...
$SQL $KAT_SQL/create/create_table_cenydew.sql

echo dostawcy...
$SQL $KAT_SQL/create/create_table_dostawcy.sql

echo magazyn...
$SQL $KAT_SQL/create/create_table_magazyn.sql

echo odbiorcy...
$SQL $KAT_SQL/create/create_table_odbiorcy.sql

#echo informacje...
$SQL $KAT_SQL/create/create_table_informacje.sql

echo
echo Koniec.

Powyższy pod-skrypt „20-zaloztabele” odpowiedzialny jest za początkowe założenie

niezbędnych tabel w bazie SQL. Wywołuje już bezpośrednio, napisane w dialekcie języka

SQL92 polecenia zakładające poszczególne tabele z polami określonego typu.

background image

25

#!/bin/sh
# skrypt 20-zaladujtabele
#
echo Zaladowanie danych do tabel bazy emarket SQL...
#

KAT_SQL='/home/bazy/emarket/sql'
SQL='/usr/local/pgsql/bin/psql -d emarket -q -f'

echo

echo cennik...
$SQL $KAT_SQL/load/load_table_cennik.sql

echo cenydew...
$SQL $KAT_SQL/load/load_table_cenydew.sql

#echo dostawcy...
#$SQL $KAT_SQL/load/load_table_dostawcy.sql

#echo odbiorcy...
#$SQL $KAT_SQL/load/load_table_odbiorcy.sql

echo magazyn...
$SQL $KAT_SQL/load/load_table_magazyn.sql

echo
echo Przy okazji skorygujemy bledne dane...

# pewne dane w zasilajacych zbiorach sa zduplikowane lub nie maja
# wypelnionych wymaganych pol (zaszlosc historyczna) poprawiamy to tutaj
SQL='/usr/local/pgsql/bin/psql -d emarket -q -c'
$SQL "UPDATE magazyn SET data='19940505' where data=' ';"
#$SQL "DELETE FROM cenydew where indeks='984001' and cenat='1036.07';"

SQL='/usr/local/pgsql/bin/psql -d emarket -q -f'
echo uniqmagazyn...
$SQL $KAT_SQL/load/load_table_uniqmagazyn.sql

echo Koniec.

Powyższy pod-skrypt „20-zaladujtabele” wywołuje skrypty SQL92 wczytujące i korygujące

dane bezpośrednio do tabel w bazie. Niektóre dane (np. odbiorcy i dostawcy) nie są
wczytywane na obecnym etapie rozwoju sklepu internetowego aż do momentu gdy aplikacja

zostanie rozbudowana o moduły współpracy z partnerami handlowymi (B2B), realizację
wymiany partnerskiej, dynamicznie konstruowane cenniki w zależności od podpisanych

umów na upusty globalne itp.

#!/bin/sh
# Skrypt 40-zaladujkatalog
#
echo Zaladowanie danych do tabel bazy emarket SQL...
#

KAT_SQL='/home/bazy/emarket/sql'
SQL='/usr/local/pgsql/bin/psql -d emarket -q -f'

echo

echo ladujemy dane do tabeli katalog...
$SQL $KAT_SQL/load/load_table_katalog.sql

echo indeksujemy tabele katalog...
$SQL $KAT_SQL/create/create_index_katalog.sql

echo
echo Koniec.

background image

26

Powyższy pod-skrypt generuje dane do dodatkowo tworzonej tabeli zawierającej
wyfiltrowane dane z tabeli zawierającej dane ze wszystkich magazynów. W aplikacji

finansowo księgowej firmy, każdy magazyn zawiera towary współistniejące w innych
magazynach. Każdy z magazynów posiada ten sam indeks dla towaru, zgodny z innymi

indeksami w pozostałych magazynach. Każdy z nich ma swój własny stan magazynowy

(dyspozycyjny i księgowy) oraz cenę. Istnieje także globalna tabela cen dewizowych
przechowująca wspólną cenę dla wszystkich magazynów. Idea działania aplikacji

magazynowej w firmie jest taka, iż gdy istnieje dla danego towaru cena w centralnym cenniku

to właśnie ona ma przewagę nad ceną lokalną w danym magazynie, dlatego tutaj właśnie
zdecydowano się na zagregowanie tych danych w jeden wspólny rekord będący podstawą do

dalszego działania sklepu.

#!/bin/sh
# skrypt 40-zalozindeksy
echo Zalozenie indeksow bazy emarket SQL...
#

KAT_SQL='/home/bazy/emarket/sql'
SQL='/usr/local/pgsql/bin/psql -d emarket -q -f'

echo

echo cennik...
$SQL $KAT_SQL/create/create_index_cennik.sql

echo cenydew...
$SQL $KAT_SQL/create/create_index_cenydew.sql

#echo dostawcy...
#$SQL $KAT_SQL/create/create_index_dostawcy.sql

#echo magazyn...
#$SQL $KAT_SQL/create/create_index_magazyn.sql

#echo odbiorcy...
#$SQL $KAT_SQL/create/create_index_odbiorcy.sql

echo uniqmagazyn...
$SQL $KAT_SQL/create/create_index_uniqmagazyn.sql

echo informacje...
$SQL $KAT_SQL/create/create_index_informacje.sql

echo
echo Koniec.

Powyższy pod-skrypt indeksuje wszystkie potrzebne pola w tabelach. Wykonywane jest to
dopiero po wczytaniu całości danych gdyż w ten sposób uniknięto przebudowywania

indeksów przy wczytywaniu danych do tabel i uzyskano znaczny wzrost szybkości całej

operacji importu danych. Silnik bazy danych w takim przypadku nie wykonuje blokad przy
dodawaniu rekordów a i same dane są fizycznie na dysku nie pofragmentowane, co miało by

miejsce, gdyby równocześnie trwało przeplatanie wczytania rekordu i zaktualizowanie

indeksu. Co prawda leżący u podstaw systemu plików mechanizm dba o takie

background image

27

rozmieszczenie plików, aby ulegały jak najmniejszej fragmentacji, jednak odbywa się to
kosztem zwiększonego zapotrzebowania na zasoby systemu. Pamiętajmy że PostgreSQL

przechowuje wszystkie obiekty bazy w osobnych plikach.

#!/bin/sh
# skrypt 45-optymalizuj
echo Optymalizacja bazy emarket SQL...
#

echo

/usr/local/pgsql/bin/vacuumdb --analyze emarket

echo
echo Koniec.

Powyższy pod-skrypt uruchamia mechanizmy analizy i optymalizacji wbudowane w silnik
bazy danych. W przypadku bazy, w której nie są kasowane tabele z danymi ten mechanizm

wpływa na „uczenie” się rozkładu danych i wykorzystywanie metod stochastycznych dla

przyspieszenia dostępu do danych i powinien być uruchamiany okresowo. W przypadku
bazy eMarket nie ma on aż tak znaczącego wpływu, gdyż dane są stale „młode”.

#!/bin/sh
# skrypt 50-statystyka
echo Statystyka tabel bazy emarket SQL...
#

KAT_SQL='/home/bazy/emarket/sql'
SQL='/usr/local/pgsql/bin/psql -d emarket -q -c'

echo
echo Zaladowane rekordy w tabelach:

echo cennik...... `$SQL "SELECT count(*) FROM cennik;"`
echo ceny_dew.... `$SQL "SELECT count(*) FROM cenydew;"`
echo dostawcy.... `$SQL "SELECT count(*) FROM dostawcy;"`
echo uniqmagazyn. `$SQL "SELECT count(*) FROM uniqmagazyn;"`
echo odbiorcy.... `$SQL "SELECT count(*) FROM odbiorcy;"`
echo katalog..... `$SQL "SELECT count(*) FROM katalog;"`
echo informacje.. `$SQL "SELECT count(*) FROM informacje;"`

echo
echo Koniec.

Powyższy pod-skrypt zlicza ilości krotek w poszczególnych tabelach po załadowaniu danych

oraz je prezentuje co zostaje dołączone przy wczytywaniu danych do raportu kontrolnego
przesyłanego administratorom.

#!/bin/sh
# skrypt 80-usunindeksy
echo Skasowanie indeksow bazy emarket SQL...
#

KAT_SQL='/home/bazy/emarket/sql'
SQL='/usr/local/pgsql/bin/psql -d emarket -q -f'

$SQL $KAT_SQL/delete/drop_all_index.sql

echo
echo Koniec.

background image

28

#!/bin/sh
# skrypt 90-usuntabele
echo Skasowanie tabel bazy emarket SQL...
#

KAT_SQL='/home/bazy/emarket/sql'
SQL='/usr/local/pgsql/bin/psql -d emarket -q -f'

$SQL $KAT_SQL/delete/drop_all_table.sql

echo
echo Koniec.

Powyższe dwa pod-skrypty usuwają wszystkie tabele i indeksy z bazy eMarket. Wykonywane
są przed załadowaniem nowych danych do tabel. Operacja skasowania całych tabel wraz

z indeksami jest nieporównywalnie szybsza niż kasowanie zawartości tabel a ponadto
fizycznie usuwane są niepotrzebne już pliki z dysku serwera.

#!/bin/sh
# 95-czysctmp
echo Usuwanie plikow zasilenia bazy SQL eMarket....
#

# parametry poczatkowe:

KAT_TMP='/home/bazy/emarket/tmp'

rm $KAT_TMP/CENNIK.IN
rm $KAT_TMP/CENY_DEW.IN
rm $KAT_TMP/ODBIORCY.IN
rm $KAT_TMP/DOSTAWCY.IN
rm $KAT_TMP/MAGAZYN.IN

echo Zbiorki zasilajace usuniete!
echo Koniec.

Powyższy pod-skrypt ma na celu fizyczne usunięcie niepotrzebnych zbiorów zasilających.

Jest uruchamiany w tylko specyficznych przypadkach, bowiem zbiory te są kasowane przy

przesyłaniu danych z serwera wewnętrznego firmy.

#!/bin/sh
# 99-struktura
echo Struktura bazy emarket SQL...
#

echo "\d cennik"

| /usr/local/pgsql/bin/psql -d emarket 2>&1

echo "\d cenydew"

| /usr/local/pgsql/bin/psql -d emarket 2>&1

echo "\d uniqmagazyn" | /usr/local/pgsql/bin/psql -d emarket 2>&1
echo "\d dostawcy"

| /usr/local/pgsql/bin/psql -d emarket 2>&1

echo "\d odbiorcy"

| /usr/local/pgsql/bin/psql -d emarket 2>&1

echo "\d katalog"

| /usr/local/pgsql/bin/psql -d emarket 2>&1

echo "\d informacje"

| /usr/local/pgsql/bin/psql -d emarket 2>&1

echo Koniec.

Powyższy pod-skrypt ma za zadanie wyświetlenie struktury bazy danych eMarket. Służy

wyłącznie celom administracyjnym np. przy rozbudowywaniu i modyfikowaniu tabel, pól czy

background image

29

indeksów. Wyniki jego wykonania posłużą do dalszej prezentacji struktur tabel bazy
w dalszej części pracy.

S

KRYPTY

SQL

Procedury operujące bezpośrednio w bazie danych zostały zapisane w postaci plików

skryptowych SQL92 wywoływanych „na żądanie”. Wykonują one czynności tworzenia,
usuwania, indeksowania danych przez silnik bazy danych. Automatyzują działania codziennej

obsługi bazy. Podzielone zostały tematycznie na kilka kategorii takich jak:

„create” – tworzenie tabel czy indeksów,
„delete” – kasowanie danych, tabel oraz indeksów,

„check” – kontrola i sprawdzanie bazy,
„load” – importowanie danych do tabel,

„analyse” – różnego rodzaju analizy danych i zestawienia.

K

ATEGORIA SKRYPTÓW

CREATE

Do tej kategorii zaliczają się skrypty tworzące tabele oraz indeksy:

create_table_odbiorcy.sql

create_index_odbiorcy.sql

create_table_dostawcy.sql

create_index_dostawcy.sql

create_table_magazyn.sql

create_index_magazyn.sql

create_table_informacje.sql

create_index_informacje.sql

create_table_cenydew.sql

create_index_cenydew.sql

create_table_cennik.sql

create_index_cennik.sql

dla tabel generowanych dynamicznie na podstawie danych:

create_index_uniqmagazyn.sql
create_index_katalog.sql

-- create_table_odbiorcy.sql
--
-- utworzenie tabeli [odbiorcy] zawierajacej kody i nazwy odbiorcow
--
CREATE TABLE odbiorcy (

kod

int4 NOT NULL,

nazwa

varchar(16),

nazwa1

varchar(41),

nazwa2

varchar(41),

nazwa3

varchar(41),

nazwa4

varchar(41),

nip

char(13)

);
-- COMMIT;

-- create_index_odbiorcy.sql
--
-- utworzenie wymaganych indeksow dla tabeli [odbiorcy]
--

CREATE INDEX odbiorcy_kod_idx ON odbiorcy (kod);
CREATE INDEX odbiorcy_nazwa_idx ON odbiorcy (nazwa);
CREATE INDEX odbiorcy_nazwa1_idx ON odbiorcy (nazwa1);
CREATE INDEX odbiorcy_nazwa2_idx ON odbiorcy (nazwa2);

-- COMMIT;

background image

30

-- create_table_dostawcy.sql
--
-- utworzenie tabeli [dostawcy] zawierajacej kod, nazwy i rach. banku dostawcow
--
CREATE TABLE dostawcy (

kod

int4 NOT NULL,

nazwa

varchar(16),

nazwa1

varchar(41),

nazwa2

varchar(41),

nazwa3

varchar(41),

nazwa4

varchar(41),

bank1

varchar(41),

bank2

varchar(41),

bank3

varchar(41),

nip

char(13)

);
-- COMMIT;

-- create_index_dostawcy.sql
--
-- utworzenie wymaganych indeksow dla tabeli [dostawcy]
--

CREATE UNIQUE INDEX dostawcy_kod_idx ON dostawcy (kod);
CREATE INDEX dostawcy_nazwa_idx ON dostawcy (nazwa);
CREATE INDEX dostawcy_nazwa1_idx ON dostawcy (nazwa1);
CREATE INDEX dostawcy_nazwa2_idx ON dostawcy (nazwa2);
CREATE INDEX dostawcy_nip_idx ON dostawcy (nip);
-- COMMIT;

-- create_table_magazyn.sql
--
-- utworzenie tabeli [magazyn] zawierajacej indeksy, ceny i stany towarow
--
CREATE TABLE magazyn (

indeks

int4 not null,

data

char(8),

stan

decimal(9,2) DEFAULT '0.00',

standp

decimal(9,2) DEFAULT '0.00'

);
-- COMMIT;

-- create_index_magazyn.sql
--
-- utworzenie wymaganych indeksow dla tabeli [magazyn]
--

CREATE INDEX magazyn_indeks_idx ON magazyn (indeks);

-- COMMIT;

-- create_table_informacje.sql
--
-- utworzenie tabeli [informacje] zawierajacej indeksy i info o towarach
--

CREATE TABLE informacje (

indeks

int4 NOT NULL,

podtyp

int4 NOT NULL DEFAULT '0',

idpromocja

int4 NOT NULL DEFAULT '0',

pokaz

char(1) DEFAULT 'N',

skrot

varchar(200) DEFAULT '',

tytul

varchar(80) DEFAULT '',

opis

varchar(4000) DEFAULT '',

link1

varchar(80) DEFAULT '',

link2

varchar(80) DEFAULT '',

flagi

varchar(80) DEFAULT ''

);

-- COMMIT;

background image

31

-- create_index_informacje.sql
--
-- utworzenie wymaganych indeksow dla tabeli [informacje]
--

CREATE INDEX informacje_indeks_idx ON informacje (indeks);
CREATE INDEX informacje_podtyp_idx ON informacje (podtyp);
CREATE INDEX informacje_idpromocja_idx ON informacje (idpromocja);
CREATE INDEX informacje_pokaz_idx ON informacje (pokaz);

-- COMMIT;

-- create_table_cenydew.sql
--
-- utworzenie tabeli [ceny_dew] zawierajacej indeksy i ceny(dewizowe) towarow
--

CREATE TABLE cenydew (

indeks

int4 NOT NULL,

cenar

decimal(9,2) DEFAULT '0.00',

wal

char(3) DEFAULT 'ZLP'

);
-- COMMIT;

-- create_index_cenydew.sql
--
-- utworzenie wymaganych indeksow dla tabeli [ceny_dew]
--

CREATE UNIQUE INDEX cenydew_indeks_idx ON cenydew (indeks);

-- COMMIT;

-- create_table_cennik.sql
--
-- utworzenie tabeli [cennik] zawierajacej indeksy i nazwy towarow
--

CREATE TABLE cennik (

indeks

int4 NOT NULL,

nazwa

varchar(34),

kod_prod

varchar(19),

dost

int4 NOT NULL,

vat

float4 DEFAULT '22'

);
-- COMMIT;

-- create_index_cennik.sql
--
-- utworzenie wymaganych indeksow dla tabeli [cennik]
--

CREATE UNIQUE INDEX cennik_indeks_idx on cennik (indeks);
CREATE INDEX cennik_nazwa_idx on cennik (nazwa);
CREATE INDEX cennik_kod_prod_idx on cennik (kod_prod);
CREATE INDEX cennik_dost_idx on cennik (dost);
-- COMMIT;

-- create_index_uniqmagazyn.sql
--
-- utworzenie wymaganych indeksow dla tabeli [uniqmagazyn]
--

CREATE UNIQUE INDEX uniqmagazyn_indeks_idx ON uniqmagazyn (indeks);
-- COMMIT;
-- create_index_katalog.sql
--
-- utworzenie wymaganych indeksow dla tabeli [katalog]
--

CREATE UNIQUE INDEX katalog_indeks_idx ON katalog (indeks);
CREATE INDEX katalog_nazwa_idx ON katalog (nazwa);

background image

32

CREATE INDEX katalog_kodprod_idx ON katalog (kod_prod);
CREATE INDEX katalog_data_idx ON katalog (data);
-- COMMIT;

K

ATEGORIA SKRYPTÓW

DELETE

Do tej kategorii zaliczają się skrypty kasujące tabele oraz indeksy:

drop_all_table.sql
drop_all_index.sql

-- drop_all_table.sql
--
-- usuniecie wszystkich tabel
--

DROP TABLE cennik;
DROP TABLE cenydew;
DROP TABLE dostawcy;
DROP TABLE odbiorcy;
DROP TABLE magazyn;
DROP TABLE uniqmagazyn;

-- tabela informacje zostaje bo jest uzupelniana z zewnatrz
-- DROP TABLE informacje;

DROP TABLE katalog;

-- COMMIT;

-- drop_all_index.sql
--
-- usuniecie wszystkich indexow
--

DROP INDEX cennik_indeks_idx;
DROP INDEX cennik_nazwa_idx;
DROP INDEX cennik_kod_prod_idx;
DROP INDEX cennik_dost_idx;

DROP INDEX cenydew_indeks_idx;

DROP INDEX dostawcy_kod_idx;
DROP INDEX dostawcy_nazwa_idx;
DROP INDEX dostawcy_nazwa1_idx;
DROP INDEX dostawcy_nazwa2_idx;
DROP INDEX dostawcy_nip_idx;

DROP INDEX uniqmagazyn_indeks_idx;

DROP INDEX odbiorcy_kod_idx;
DROP INDEX odbiorcy_nazwa_idx;
DROP INDEX odbiorcy_nazwa1_idx;
DROP INDEX odbiorcy_nazwa2_idx;

-- DROP INDEX informacje_indeks_idx;
-- DROP INDEX informacje_podtyp_idx;
-- DROP INDEX informacje_idpromocja_idx;
-- DROP INDEX informacje_pokaz_idx;

DROP INDEX katalog_indeks_idx;
DROP INDEX katalog_nazwa_idx;
DROP INDEX katalog_kodprod_idx;
DROP INDEX katalog_data_idx;

-- COMMIT;

background image

33

K

ATEGORIA SKRYPTÓW

LOAD

Do tej kategorii zaliczają się skrypty importujące dane do tabel oraz generujące dane na bazie

już istniejących poprzez agregację czy filtrowanie. Wczytywanie bazuje na specjalnej
metodzie importu danych bezpośrednio do tabeli w jednym przebiegu jaką udostępnia

backend PostgreSQL’a. Taki sposób importu definitywnie góruje nad metodami

tradycyjnymi, wykorzystującymi składnię „INSERT INTO”. Przewaga w szybkości jest
szczególnie widoczna przy „dużych” importach rzędu kilkadziesiąt tysięcy rekordów i więcej.

load_table_dostawcy.sql
load_table_odbiorcy.sql
load_table_cenydew.sql
load_table_uniqmagazyn.sql
load_table_cennik.sql
load_table_katalog.sql
load_table_magazyn.sql

-- load_table_dostawcy.sql
--
-- ladowanie danych do tabeli [dostawcy]
--

COPY dostawcy
FROM '/home/bazy/emarket/tmp/DOSTAWCY.IN'
USING DELIMITERS '|';

-- COMMIT;

-- load_table_odbiorcy.sql
--
-- ladowanie danych do tabeli [odbiorcy]
--

COPY odbiorcy
FROM '/home/bazy/emarket/tmp/ODBIORCY.IN'
USING DELIMITERS '|';

-- COMMIT;

-- load_table_cenydew.sql
--
-- ladowanie danych do tabeli [cenydew]
--

COPY cenydew
FROM '/home/bazy/emarket/tmp/CENY_DEW.IN'
USING DELIMITERS '|';

-- COMMIT;

-- load_table_uniqmagazyn.sql
--
-- Agregacja z tabeli magazyn do tabeli [uniqmagazyn] bazy emarket SQL...
--
SELECT

indeks AS agr_indeks,
max(data) AS ost_data,
sum(stan) AS suma_stan,
sum(standp) AS suma_standp

INTO TEMP agrmagazyn FROM magazyn GROUP BY indeks;
--

background image

34

--

SELECT DISTINCT

agr_indeks,
ost_data,
suma_stan,
suma_standp

INTO TEMP tmpmagazyn FROM magazyn, agrmagazyn
WHERE agr_indeks=magazyn.indeks and ost_data=magazyn.data
ORDER BY agr_indeks;
--
--
--DROP TABLE uniqmagazyn;
SELECT

agr_indeks::int4 AS

indeks,

date(ost_data) AS

data,

suma_stan::float4

AS stan,

suma_standp::float4

AS standp

INTO uniqmagazyn FROM tmpmagazyn ORDER BY 1;
--
--
DROP TABLE magazyn;

-- load_table_cennik.sql
--
-- ladowanie danych do tabeli [cennik]
--

COPY cennik
FROM '/home/bazy/emarket/tmp/CENNIK.IN'
USING DELIMITERS '|';

-- COMMIT;

-- load_table_katalog.sql
--
-- zlozenie danych z tabel i zaladowanie do ostatecznej prezentacyjnej tabeli [katalog]
--

DROP TABLE katalog;

SELECT cennik.indeks, cennik.nazwa, cennik.kod_prod,

uniqmagazyn.data, cenydew.wal, cenydew.cenar AS netto,

--

numeric_round(cenydew.cenar::float8 * (cennik.vat /100+1),2) AS brutto,
round(cenydew.cenar::float8 * (cennik.vat /100+1),2) AS brutto,
standp AS nastanie

INTO

katalog

FROM cennik,uniqmagazyn,

cenydew

WHERE (cennik.indeks=uniqmagazyn.indeks)

AND

(cennik.indeks=cenydew.indeks)

--

AND standp>=0 AND

--

date_ge(uniqmagazyn.data,'1998-12-31') AND

--

(cennik.nazwa like '%%%%')

ORDER BY 3,2;

-- load_table_magazyn.sql
--
-- ladowanie danych do tabeli [cennik]
--

COPY magazyn
FROM '/home/bazy/emarket/tmp/MAGAZYN.IN'
USING DELIMITERS '|';

-- COMMIT;

background image

35

K

ATEGORIA SKRYPTÓW

CHECK

Skrypty te wykonują kontrolę danych w tabelach ładowanych do bazy na obecność

zduplikowanych identycznych rekordów. W wyniku zawieszenia się komputera na którym
działa aplikacja finansowo księgowa indeksy NTX bazy danych DBF mogą zostać

uszkodzone, a wtedy może dojść do takiej sytuacji, że aplikacja „nieświadoma” dopisanej

pozycji do bazy na innej końcówce sieciowej może zarejestrować identyczną krotkę. Skrypty
te powstały gdy wynikła taka właśnie sytuacja. Następstwem tego była konieczność

„ręcznego”, usuwania błędnych rekordów z tabeli DBF oraz reindeksacja.

duplicated_cenydew.sql
duplicated_cennik.sql
duplicated_dostawcy.sql
duplicated_odbiorcy.sql

-- duplicated_cenydew.sql
--
-- Wyszukanie podwojnych indeksow w tabeli cenydew...
--
SELECT indeks, count(indeks) AS ile FROM cenydew
GROUP BY indeks HAVING count(indeks)>1;

-- duplicated_cennik.sql
--
-- Wyszukanie podwojnych indeksow w tabeli cennik...
--
SELECT indeks, count(indeks) AS ile FROM cennik
GROUP BY indeks HAVING count(indeks)>1;

-- duplicated_dostawcy.sql
--
-- Wyszukanie podwojnych identyfikatorow dostawcow...
--
SELECT kod, count(kod) AS ile FROM dostawcy

GROUP BY kod HAVING count(kod)>1;

-- duplicated_odbiorcy.sql
--
-- Wyszukanie podwojnych identyfikatorow odbiorcow...
--
SELECT kod, count(kod) AS ile FROM odbiorcy
GROUP BY kod HAVING count(kod)>1;

K

ATEGORIA SKRYPTÓW

ANALYSIS

W tej kategorii w pierwotnym zamierzeniu miały powstać skrypty wykonujące różne analizy
danych zebranych w tabelach, zarejestrowanych transakcjach i innych operacjach. Na

obecnym stadium rozwoju sklepu internetowego został opracowany jeden skrypt wybierający

towar „niechodliwy” z bazy danych. Skrypt występuje w dwóch wersjach a ich zadaniem jest
bardziej przetestowanie możliwości składania danych z wielu tabel niż użytkowe

wykorzystanie. W momencie gdy powstawał, dostępna wersja bazy PostgreSQL nie miała

background image

36

jeszcze zaimplementowanej obsługi złączeń klauzulami „JOIN” i należy go traktować jako
„wprawkę” programistyczną, gdyż obecna wersja PostgreSQL zapewnia pełną obsługę

złączeń, lewo i prawostronnych a także zawężających itp.

-- niechodliwy.sql
--
-- Towar na stanie niechodliwy
--

SELECT *, float4(stan+standp)*float4(cenaz) AS wartosc
FROM uniqmagazyn,

cennik

WHERE uniqmagazyn.indeks=cennik.indeks

and

(stan + standp)>0 and
data<'1999-01-01'

ORDER BY data;

-- niechodliwy.sql
--
-- Towar na stanie niechodliwy zlaczenie bez klauzuli JOIN
--

SELECT uniqmagazyn.*, cennik.*
FROM uniqmagazyn,

cennik

WHERE uniqmagazyn.indeks=cennik.indeks

UNION ALL

SELECT uniqmagazyn.*, null, null, null, null, null
FROM uniqmagazyn
WHERE NOT EXISTS (
SELECT * FROM cennik
WHERE uniqmagazyn.indeks=cennik.indeks

);

S

TRUKTURA BAZY

Poniższe zestawienie jest wynikiem działania skryptu „99-struktura” generującego
schematyczną i poglądową prezentację struktury tabel i przynależnych im indeksów w bazie

danych eMarket. Listing ten prezentuje stan bazy po wykonaniu pełnego załadunku

wszystkich tabel oraz wykonaniu skryptów aktualizujących i czyszczących.

Table "cennik"
Attribute | Type | Modifier
-----------+-------------+--------------
indeks | integer | not null
nazwa | varchar(34) |
kod_prod | varchar(19) |
dost | integer | not null
vat | float4 | default '22'
Indices: cennik_dost_idx,
cennik_indeks_idx,
cennik_kod_prod_idx,
cennik_nazwa_idx

Table "cenydew"
Attribute | Type | Modifier
-----------+--------------+----------------
indeks | integer | not null
cenar | numeric(9,2) | default '0.00'
wal | char(3) | default 'ZLP'
Index: cenydew_indeks_idx

background image

37

Table "uniqmagazyn"
Attribute | Type | Modifier
-----------+---------+----------
indeks | integer |
data | date |
stan | float4 |
standp | float4 |
Index: uniqmagazyn_indeks_idx

Table "dostawcy"
Attribute | Type | Modifier
-----------+-------------+----------
kod | integer | not null
nazwa | varchar(16) |
nazwa1 | varchar(41) |
nazwa2 | varchar(41) |
nazwa3 | varchar(41) |
nazwa4 | varchar(41) |
bank1 | varchar(41) |
bank2 | varchar(41) |
bank3 | varchar(41) |
nip | char(13) |
Indices: dostawcy_kod_idx,
dostawcy_nazwa1_idx,
dostawcy_nazwa2_idx,
dostawcy_nazwa_idx,
dostawcy_nip_idx

Table "odbiorcy"
Attribute | Type | Modifier
-----------+-------------+----------
kod | integer | not null
nazwa | varchar(16) |
nazwa1 | varchar(41) |
nazwa2 | varchar(41) |
nazwa3 | varchar(41) |
nazwa4 | varchar(41) |
nip | char(13) |
Indices: odbiorcy_kod_idx,
odbiorcy_nazwa1_idx,
odbiorcy_nazwa2_idx,
odbiorcy_nazwa_idx

Table "katalog"
Attribute | Type | Modifier
-----------+----------------------+----------
indeks | integer |
nazwa | varchar(34) |
kod_prod | varchar(19) |
data | date |
wal | char(3) |
netto | numeric(9,2) |
brutto | numeric(65535,65531) |
nastanie | float4 |
Indices: katalog_data_idx,
katalog_indeks_idx,
katalog_kodprod_idx,
katalog_nazwa_idx

Table "informacje"
Attribute | Type | Modifier
------------+---------------+----------------------
indeks | integer | not null
podtyp | integer | not null default '0'
idpromocja | integer | not null default '0'
pokaz | char(1) | default 'N'
skrot | varchar(200) | default ''
tytul | varchar(80) | default ''
opis | varchar(4000) | default ''
link1 | varchar(80) | default ''
link2 | varchar(80) | default ''
flagi | varchar(80) | default ''
Indices: informacje_idpromocja_idx,
informacje_indeks_idx,
informacje_podtyp_idx,
informacje_pokaz_idx

background image

38

Rozdział V – W

YSZUKI WARKA TOWARÓW

K

ONCEPCJA DZIAŁANIA

Chcąc udostępnić potencjalnym klientom efektywny mechanizm wyszukiwania w bazie
towarów, koniecznym stało się skonstruowanie odpowiednich mechanizmów

umożliwiających pobranie od internauty interesującej go frazy, przeszukanie bazy danych
oraz zaprezentowanie znalezionych pozycji. Pewnym problemem wydaje się być tutaj

konieczność połączenia efektywności mechanizmu wyszukującego z możliwościami silnika

bazy danych. Większość obecnie istniejących baz danych nie pozwala na wyszukiwanie pełno

tekstowe przy wykorzystaniu indeksu, gdy szukana fraza zaczyna się znakiem wieloznacznym

w zapytaniu typu „LIKE”. Najnowsze komercyjne bazy danych takie jak ORACLE
wspierają ten mechanizm poprzez statyczne utworzenie specjalnych struktur indeksujących

pełnotekstowo całe pola tabeli, jednakże jedynie statycznie. Każdorazowe dopisanie krotki
do tabeli wymusza ponowne pełne zaindeksowanie całości tabeli, co praktycznie wyklucza to

zastosowanie w przypadku bazy, gdzie są modyfikowane lub dodawane kolejne rekordy.

Rysunek 7 – Główna strona wyszukiwarki towarów.

background image

39

PostgreSQL posiada bardzo zaawansowane metody i typy indeksów, jednak nie ma
możliwości ich użycia w przypadku pełno tekstowego wyszukiwania. Silnik bazy danych jest

wtedy zmuszony do wykonania pełnego przejścia po wszystkich krotkach tabeli (tzw. full
scan), co drastycznie obniża efektywność tego rozwiązania.

W obecnej fazie rozwoju aplikacji sklepu internetowego zdecydowano się na pewne

rozwiązania skutecznie eliminujące wykonywanie pełnych przejść w tabelach. W głównym
oknie wyszukiwawczym jednak taki mechanizm musiał tymczasowo pozostać ze względu na

konieczność zapewnienia pełnego wyszukiwania nawet kosztem zwiększonego obciążenia

systemu i spowolnienia samego procesu. W module ofert przy przeglądaniu gotowych
zestawień towarów zastosowano zmodyfikowany mechanizm głównej wyszukiwarki w taki

sposób aby nie używać zapytań zaczynających się znakiem wieloznacznym „%” w klauzuli
„LIKE”, co spowodowało możliwość użycia przez motor bazy danych indeksów na

przeglądanych polach a tym samym wykonywanie całości zapytania w sposób błyskawiczny.

Chcąc rozwiązać tzw. problem „full text search” czyli pełnotekstowego wyszukiwania

korzystającego z indeksów (

http://www.postgresql.org/idocs/index.php?indices.html

)

w przygotowaniu jest pewien model przechowywania nazw towarów w dodatkowej tabeli,

ale w taki sposób, aby możliwym stało się zaindeksowanie każdego wyrazu z nazwy towaru.

Rysunek 8 – Prezentacja wyników wyszukania towaru.

background image

40

Opracowana koncepcja polega na podziale nazwy towarów na odrębne wyrazy a następnie
na zapisanie ich do odrębnych pól w krotce.

background image

41

Każde pole będzie polem indeksowanym tak więc przy konstruowaniu zapytania możliwym
stanie się wykorzystanie w mechanizmie wyszukiwarki odwołania klauzulami „LIKE” bez

podawania na początku znaku wieloznacznego „%” a zamianę szukanej frazy na kilka klauzul
typu „LIKE ‘towar%’” co pozwoli na użycie indeksów jak w przypadku przeszukania w

module ofert. Pole z nazwą towaru i oznaczeniem producenta sumarycznie ma długość

34+19=53 znaki. Zakładając że w skrajnym pesymistycznym przypadku nazwa towaru
złożona będzie z pojedynczych liter rozdzielanych spacjami to otrzymujemy około 27 pól

potrzebnych do rozbicia na wyrazy (53/2=26+1). Tak więc przyjmujemy, że 30 pól jest
liczbą wystarczająca w zupełności do przechowania całej nazwy towaru w rozbiciu na

wyrazy. Spacje nie są przechowywane bowiem służą jako znak, według którego dokonujemy

rozbicia na części składowe. Do kolejnych pól rekordu wpisujemy kolejne wyrazy z nazwy
towaru a sama treść zapytania wykonującego wyszukanie z wykorzystaniem indeksów

przyjmie wtedy przykładową postać:

SELECT * FROM subtowary WHERE pole1 LIKE ‘szukana_fraza%’ OR pole2 LIKE ‘szukana_fraza%’ OR .....;

Rysunek 9 – Prezentacja wyszukiwania predefiniowanego rodzaju towarów.

background image

42

Zakładamy oczywiście że szukana fraza jest pojedynczym wyrazem, a w przypadku, gdy jest
to kilka wyrazów wykonujemy kilka takich zapytań dla każdego z wyrazów, składanych

następnie w jeden zestaw wyników. Powyższy projekt rozwiązania problemu pełnych przejść
po tabeli wydaje się być optymalnym do tego celu rozwiązaniem i będzie testowo

zastosowany w aplikacji sklepu internetowego w najbliższym czasie.

K

OD ŹRÓDŁOWY WYSZUKIWARKI

Mechanizm wyszukiwarki został wbudowany w różne strony serwisu internetowego firmy.

W momencie gdy powstawał, język PHP nie posiadał uniwersalnej klasy obiektów służących
do odwołania do bazy danych. Każdy typ bazy danych wymagał użycia innego zestawu

poleceń. Chcąc maksymalnie uniezależnić się od samej bazy zastosowano uniwersalne
definicje funkcji odwołujących się do baz. Wykorzystano do tego celu bibliotekę phpDB

której autorami są J. Thong i C. Fonk (

phpdb.linuxbox.com

) pozwalającą na zamaskowanie

metod odwołań do baz MySQL, MSQL, PostgreSQL, Microsoft SQL Server, Sybase na
jednakowe funkcje, co pozwala na łatwą wymianę silnika bazy na inny bez konieczności

zmian w kodzie źródłowym. Obecnie rozwijana jest przez autorów języka PHP, klasa

uniwersalnych funkcji, metod i obiektów pozwalająca na uniknięcie problemów związanych
z koniecznością przeróbek kodu w takich przypadkach. Projekt jest obecnie w bardzo

wczesnej fazie rozwoju jednakże fakt tworzenia go przez ekipę tworzącą PHP gwarantuje, że
wkrótce możliwym będzie zastosowanie go w systemach produkcyjnych. Nosi on nazwę

„PEAR: the PHP Extension and Application Repository”. Poniższy listing prezentuje i

omawia kod php wyszukiwarki. Niektóre linie zostały sztucznie podzielone na krótsze ze
względu na ich długość, co oznaczono znakiem „\” (jednakże on sam w kodzie oryginalnym

nie może występować). Listing zawiera komentarze świadczące o zespołowej pracy nad

powstającym kodem oraz podział zadań na kod dostępu i obsługi bazy danych oraz kod
dynamicznego generowania strony na podstawie pobieranych z bazy danych rekordów.

<?php
// obsluga bazy wyszukiwarki, plik: db.php3

// parametry glowne: uzytkownik, haslo, nazwa bazy itp.
include "inc/db.inc";

// zaimportowanie meta tagow
include "inc/meta.inc";

// phpDB wrapper do baz danych, wkoncu to ma chodzic na wszystkim :)
include "lib/phpDB.inc";

// data aktualizacji do ewentualnego wyswietlenia
// okreslana dynamicznie jako data i czas modyfikacji pliku index.php3

$datam = filemtime('index.php3');
$filemodtime = date("j m Y h:i:s A", $datam);

background image

43

$aktual = strftime ('%d.%m.%Y godzina %H:%M:%S', $datam);

?>
<title>-x(AGD)x- .::EuroMarket - Video Tomex::. -x(RTV)x-</title>

<script language="JavaScript">
function WinOpen(file) {
window.open(file,'_blank','toolbar=no,location=no,directories=no,status=no,menubar=no,scrollbars=yes, \
resizable=no,width=600,height=400');}
</script>

</HEAD>
<body>

<? include "inc/menu.inc"; ?>
<br>
<div align="center">
<table width="760" cellpadding="0" cellspacing="0" border="0">
<tr><td width="200" align="center" valign="baseline">
<form action="db.php3" method="post">

<strong>Potrzebujesz czegoś?</strong><BR>
<input style="color: #1c36b3; background-color: #CCAC0C; font-size: 8pt; font-weight: 800;"

type="Text" size="14" name="towar" style="width: 140px">

<br><br><input style="background-color: #1c36b3; color: #CCAC0C; font-size: 8pt;

font-weight: 800;" type="Submit" value="Szukaj">
</form>
</td>
<td valign="top">
<strong><u>Możesz szukać korzystaj±c z symboli wieloznacznych:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</u></strong><br>
<table cellpadding="0" cellspacing="0" border="0">
<tr><td width="250" valign="bottom"><B>*</B> -zastępuje dowolny ciąg znaków<BR>
<B>?</B> -zastępuje jeden znak</td>
<td valign="bottom">Na przykład:<B>telewizor*philips</B>
<br> Bez względu na wielkość znaków.</td></tr></table>
<br> &nbsp;&nbsp;&nbsp;&nbsp;
Jeżeli chcesz zamówić wybrany produkt kliknij na ikonce <img src="gfx/wozek0.gif" alt="Zamow" border="0">
</td>
</tr>
</table>
</div>
<br>

<?php

// sprawdzamy czy akurat trwa ladowanie danych do bazy
// nie jest to najlepszy sposób, trzeba potem zmienic na lepszy

if ( ! file_exists("/home/bazy/tmp/emarket.tmp"))
{

//$towar z brany jest z tresci zapytania przegladarki trzeba go dobrze wyfiltrowac potem !!!
//trzeba oprogramowac wybor *? jak w dosie
//zastosowac regexpy do odfiltrowania niebezpiecznych znakow (sanity check)

/* tymczasowo wylaczam ten komunikat msg-box

if ($towar=="" or $towar==" "){

echo "<SCRIPT LANGUAGE=\"JavaScript\">\n";
echo "<!--\n";
echo "alert('Nie podales czego szukasz!')\n";
echo "history.back()\n";
echo "//-->\n";
echo "</SCRIPT>\n";
echo "<B>Nie podales czego szukasz!</B><BR>";
echo "<A HREF=\"$powrot\">Powrót</A>\n";

*/

}
//trzeba dorobic full_text_search do PostgreSQL bo inaczej nie posluguje sie tu indexami
//gdy w zapytaniu jest: like %costam% to jet robiony full table scan

// zduplikowanie zmiennej towar
$nazwa_tow = $towar;

//konwersja * i ? na % i _ dla SQL

$towar=strtr($towar,"*?","%_");

background image

44

$towar="'%" . strtoupper($towar) ."%'";

// link powrotu

echo "<table width=\"760\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\">";
echo "<tr><td align=\"left\" valign=\"baseline\">";
echo "<div align=\"left\">";
echo "Wyniki wyszukiwania słowa &quot;<b>" . $nazwa_tow . "</b>&quot; :<br>";
echo "<B>Ceny detaliczne w zł, dla klientów indywidualnych.</B></div><br><br>";
echo "</td></tr></table>";
//echo "<FORM><INPUT TYPE=\"button\" VALUE=\"POWRÓT\"

onClick=\"parent.location.href='http://www.vt.pl'\"></FORM>";
?>

<!-- Tabela wynikow wyszukiwania-->

<?php
// jednorazowe stale i trwale polaczenie z baza
// presistent connections pozwalaja na urzymywanie przez Apache stalego polaczenia
// z PostgreSQL co wyjatkowo przyspiesza dzialanie calosci

$db=new phpDB();
$db->pconnect($db_host,$db_user,$db_pass,$db_name) or die("Wystapił błąd przy łączeniu!<BR>\n ");

// wersja zapytania po optymalizacji
$sqlquery="SELECT * FROM katalog WHERE nastanie>=0 AND date_ge(data, '$datapoczatkowa') ";

if ($towar=="'%%%'") { $selekcja="";}

else {$selekcja="AND ((nazwa like $towar) OR (kod_prod like $towar))";};

$sqlquery= $sqlquery .

$selekcja .

"LIMIT $ilosc OFFSET $start";

//echo $sqlquery . ";<BR><BR>\n";

$result = $db->execute($sqlquery) or die("Wystąpił błąd przy zapytaniu. <BR>\n");

$numrows=$result->getNumOfRows();
$numfields=$result->getNumOfFields();

?>

<TABLE WIDTH=760 BORDER=0 BGCOLOR="#b32f1c" cellpadding="0" cellspacing="0">
<TR>
<TD HEIGHT="14"><B style="color: #FFF200;">lp</B></TD>
<TD HEIGHT="14"><B style="color: #FFF200;">
zam.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nazwa towaru</B></TD>
<TD HEIGHT="14"><B style="color: #FFF200;">data ceny</B></TD>
<TD HEIGHT="14"><B style="color: #FFF200;">cena netto</B></TD>
<TD HEIGHT="14"><B style="color: #FFF200;">cena brutto</B></TD>
<TD HEIGHT="14"><B style="color: #FFF200;">dostępny</B></TD>
<TD HEIGHT="14"><B style="color: #FFF200;">info</B></TD>
</TR>

<?php
$row=0;
$img=0;

/*
Sprawdzamy czy przegladara ma jave czyli ze sie zglasza sie jako Mozilla
to jest naprawde proste i dobre i pewnie dodamy to do jakiego inc'luda na stale
fakt ze jak Mozilla to nie zawsze jest java ale to na razie wystarczy, a i links dziala :)
*/

if (strpos($HTTP_USER_AGENT, "ozilla") >0) {$jestjava=TRUE;} else {$jestjava=FALSE;};

/*
Poprawilem skladnie html'a bo sie rozlatywala zwlaszcza przy
generowaniu tabeli, teraz powinno byc ok w kazdej przegladarce.
Zmienilem troche wyglad stron, tak juz zostanie i pod ten styl bede wszystko zmienial
*/

// petla czytania kolejnych rekordow z bazy
while(!$result->EOF) {

// naprzemienne kolory wierszy
$bgcolor= ($row % 2) ;
if ($bgcolor<>0) { $bg=$bg1;} else { $bg=$bg2;};

$ind=$result->fields["indeks"];

background image

45

// jesli przegladara zgodna z Mozilla to zakladamy ze ma jave
if ($jestjava){$wywolanie="JavaScript:WinOpen('towar.php?indeks=$ind')";} else
{$wywolanie="towar.php?indeks=$ind";}
if ($result->fields["nastanie"]==0) {$stan="-";} else {$stan="tak";};

if ($ind!=""){

// wyswieltamy naglowek i numer wiersza
echo "<TR BGCOLOR=$bg><TD ALIGN=\"center\">";
echo ($row + $start + 1);
echo "</TD>";

// podmiana obrazka do zamawiania - nie udalo mi sie zrobic ladnego przezroczystego gifa wiec PHP RuLeZ
if ($img == 0 ) {
echo "<TD>&nbsp;<a href=\"zakup.php3?towar=" . $result->fields["nazwa"] . "&netto=" . \
$result->fields["netto"] . "&brutto=" . $result->fields["brutto"] . "\"> \
<img name=\"wozek$row\" src=\"gfx/wozek00.gif\" alt=\"Zamawiam!\" border=\"0\"></a> \
<B>&nbsp;" . $result->fields["nazwa"]. "&nbsp;</b> </TD>";
$img = $img + 1;
}
else {
echo "<TD valign=\"middle\">&nbsp;<a href=\"zakup.php3?towar=" . $result->fields["nazwa"] . \
"&netto=" . $result->fields["netto"] . "&brutto=" . $result->fields["brutto"] . "\"> \
<img name=\"wozek$row\" src=\"gfx/wozek0.gif\" alt=\"Zamawiam!\" border=\"0\"></a> \
<B>&nbsp;" . $result->fields["nazwa"]. "&nbsp;</b> </TD>";
$img = $img - 1;
}
echo "<TD><B>&nbsp;" .

$result->fields["data"]

. "&nbsp;</b></TD>";

echo "<TD ALIGN=\"right\">&nbsp;" .

$result->fields["netto"]

. "&nbsp;</TD>";

echo "<TD ALIGN=\"right\"><B>&nbsp;". $result->fields["brutto"]

. "&nbsp;</b></TD>";

echo "<TD ALIGN=\"center\">&nbsp;".

$stan

. "&nbsp;</TD>";

if ($stan == "tak") {
echo "<TD ALIGN=\"center\">&nbsp;<a href=\"$wywolanie\">info</a>&nbsp;</TD>";}
else { echo "<TD ALIGN=\"center\">&nbsp;$stan&nbsp;</TD>";};

echo "</TR>";
};

// pobieramy nastepna krotke
$result->nextRow();
$row++;
} // koniec petli czytania rekordow

//koniec tabeli
echo "</TABLE>\n";
/*
Te zagniezdzenia if trzeba poprzerabiac bo za duzo czasu tracimy na te warunki
narazie zostawie tak ale pozniej to pozmieniam, za to nie wyswietla pustego
wiersza tabeli z nr 1 oraz wyswietla info. Poprawnie zamyka tag tabeli.
Pewnie jeszcze zawine w to naglowek tabeli, pozniej...
*/

if ($ind=="") {
//nic nie znaleziono w bazie
echo "<b style=\"color:#DB2614\">";
echo "Przepraszamy!<BR>Nie znaleziono tego towaru w bazie.<BR>";
echo "Proszę spróbować ponownie oraz zmienić nazwę szukanego towaru...<BR><BR></b>";
};

// zwalniamy pamiec i zamykamy polaczenie z baza
// (teoretycznie bo przeciez uzywamy presistent connection ale na wszelki wypadek
// trzeba po sobie posprzatac
$result->close();
$db->close();

} //koniec warunku aktualizacji bazy
else { // wlasnie trwa aktualizacja sql'a
echo "<b style=\"color:#DB2614\">";
echo "Przepraszamy! <BR> Właśnie trwa aktualizacja bazy danych.<BR>";
echo "Proszę spróbować ponownie za chwilę...<BR><BR></b>";
};

onClick=\"parent.location.href='http://www.vt.pl'\"></FORM>";
echo "<br>";

include "inc/stopka.inc";

?>
</body></html>

background image

46

Struktura powyższego skryptu wskazuje na wzajemne przeplatanie kodu PHP, JavaScript

oraz czystego HTML'u. Możliwe jest także wykonywanie wstawek w innych językach
skryptowych jak np. Visual Basic Script. Najczęściej powtarzające się fragmenty kodu zostały

wyodrębnione do zewnętrznych plików a następnie dołączane klauzulą „include” w różnych

podprogramach w celu predefiniowania i ujednolicenia wyglądu generowanych stron czy też
identycznego tworzenia meta-tagów itp. W całości generowanych stron kod opisu strony

napisany jest zgodnie z obowiązującym standardem HTML przy zastosowaniu stylów.

Ułatwia to zachowanie jednakowego wyglądu wszystkich generowanych stron. Poniższy
listing przedstawia główny plik definicji stylów.

body {

background-color : #DEBE09;
margin-top : 0px;
margin-right : 0px;
margin-left : 0px;
font-family : Verdana, Geneva, Arial, Helvetica, sans-serif;
font-size : 8pt;
color : #1e1164;
text-align: center;

}

.tab {

border-style: solid;
border-width: 1px;
border-top-width: 0px;
border-bottom-width: 0px;

}

a {

font-size: 8pt;
color : #0a0eb6;
font-family : Verdana, Geneva, Arial, Helvetica, sans-serif;
text-decoration : none;

}

a:hover {

font-size: 8pt;
color : red;
font-family : Verdana, Geneva, Arial, Helvetica, sans-serif;
text-decoration : none;

}

td. {

font-family : Arial, Helvetica, sans-serif;
font-size : 8pt;
color : #1e1164;
font-family : Verdana, Geneva, Arial, Helvetica, sans-serif;

}

.m7 {

font-size: 7px;
color : #eac137;
font-weight : 800;
font-family : Verdana, Geneva, Arial, Helvetica, sans-serif;
text-decoration : none;

}

.m {

font-size: 10px;
color : SlateGray;
font-weight : 800;
font-family : Verdana, Geneva, Arial, Helvetica, sans-serif;

}

background image

47

.cena {

border-style: solid;
border-width: 1px;
border-color: black;
border-left-widht: 1px;
border-right-widht: 1px;
border-top-widht: 1px;
border-bottom-widht: 1px;
text-align: center;
font-size: 15px;
color : Yellow;
background-color: #b32f1c;
font-weight : 900;
font-family : Verdana, Geneva, Arial, Helvetica, sans-serif;

}

.cena2 {

border-style: solid;
border-width: 1px;
border-color: black;
border-left-widht: 1px;
border-right-widht: 0px;
border-top-widht: 1px;
border-bottom-widht: 1px;
text-align: center;
font-size: 15px;
color : black;
background-color: #DEBE09;
font-weight : 100;
font-family : Verdana, Geneva, Arial, Helvetica, sans-serif;

}

.cena3 {

border-style: solid;
border-width: 1px;
border-color: black;
border-left-widht: 0px;
border-right-widht: 1px;
border-top-widht: 1px;
border-bottom-widht: 1px;
text-align: center;
font-size: 15px;
color : Yellow;
background-color: navy;
font-weight : 900;
font-family : Verdana, Geneva, Arial, Helvetica, sans-serif;

}

.red {

color: #ac0f0f;

}

Zastosowanie stylów pozwala na szybkie zmiany wyglądu prezentowanych stron

w przypadku „odświeżania” serwisu internetowego za pomocą zmiany projektu graficznego.
Plik z opisem styli jest przez przeglądarkę wczytywany po napotkaniu odwołania w treści

strony do dokumentu z definicjami używanych styli. Poniższy listing prezentuje główny plik
generujący większość stron serwisu.

<? include "inc/meta.inc"; ?>
<title>-x(AGD)x- .::EuroMarket - Video Tomex::. -x(RTV)x-</title>

<script language="JavaScript">
function WinOpen(file) {
window.open(file,'_blank','toolbar=no,location=no,directories=no,status=no,menubar=no, \
scrollbars=no,resizable=no,width=300,height=240');}
</script>
<script language="JavaScript"><!--
function chBr(br, ver) {

if (!(chBr.arguments.length > 0)) return (navigator.appName + ', ' + navigator.appVersion);
var Browser = br;
var Version = (chBr.arguments.length > 1) ? ver : null;
var BrowserFlag = (navigator.appName.toLowerCase() == Browser.toLowerCase()) ? true : false;

background image

48

if (Version != null) {
var VersionFlag = (navigator.appVersion.substring(0,1) == Version.substring(0,1)) ? true : false;
}
return (BrowserFlag || VersionFlag);

}
function openr(dokument)
{
window.open(dokument,'parent[oferta]');
}
// --></script>
</head>

<body bgcolor="#DEBE09">
<br>

<?

# jezeli brak zapytania startuj tutaj
if ($ID == '') {
?>

<div align="center">
<table cellpadding="0" cellspacing="0" border="0">
<tr><td width="150" valign="top">
<? include "inc/targi.inc" ?>
</TD><td valign="top">

<!— Generowanie przyciskow metoda rollover -->

<!-- <div align="right"><a class="fade" href="javascript:WinOpen('inc/s_help.html')">pomoc</a></div> -->
</div>
<table cellpadding="0" cellspacing="0" border="0">

<tr><td valign="top">
<div align="center">
<a href="?ID=05"><img src="gfx/logo_vt.gif" width="361" height="107" alt="" border="0"></a><br>
</div>

<a href="?ID=01" onmouseover="if ( (chBr('Netscape', '3') == true) || (chBr('Explorer', '4') == true) )
menu1.src='gfx/onas_1.gif'"
onmouseout="if ( (chBr('Netscape', '3') == true) || (chBr('Explorer', '4') == true) )
menu1.src='gfx/onas_0.gif'">
<img name="menu1" src="gfx/onas_0.gif" alt="" border="0"></a></td></tr>
<tr><td width="94" align="right">
<a href="?ID=02" onmouseover="if ( (chBr('Netscape', '3') == true) || (chBr('Explorer', '4') == true) )
menu2.src='gfx/szukaj_1.gif'"
onmouseout="if ( (chBr('Netscape', '3') == true) || (chBr('Explorer', '4') == true) )
menu2.src='gfx/szukaj_0.gif'">
<img name="menu2" src="gfx/szukaj_0.gif" alt="" border="0"></a></td></tr>
<tr><td width="108" align="right">
<a href="http://poczta.vt.pl" onmouseover="if ( (chBr('Netscape', '3') == true) || (chBr('Explorer', '4')
== true) ) menu3.src='gfx/internet_1.gif'"
onmouseout="if ( (chBr('Netscape', '3') == true) || (chBr('Explorer', '4') == true) )
menu3.src='gfx/internet_0.gif'">
<img name="menu3" src="gfx/internet_0.gif" alt="" border="0"></a></td></tr>
<tr><td width="129" align="right">
<a href="?ID=04" onmouseover="if ( (chBr('Netscape', '3') == true) || (chBr('Explorer', '4') == true) )
menu4.src='gfx/partnerzy_1.gif'"
onmouseout="if ( (chBr('Netscape', '3') == true) || (chBr('Explorer', '4') == true) )
menu4.src='gfx/partnerzy_0.gif'">
<img name="menu4" src="gfx/partnerzy_0.gif" alt="" border="0"></a></td></tr>
<tr><td width="161" align="right">
<a href="?ID=05" onmouseover="if ( (chBr('Netscape', '3') == true) || (chBr('Explorer', '4') == true) )
menu5.src='gfx/promocje_1.gif'"
onmouseout="if ( (chBr('Netscape', '3') == true) || (chBr('Explorer', '4') == true) )
menu5.src='gfx/promocje_0.gif'">
<img name="menu5" src="gfx/promocje_0.gif" alt="" border="0"></a></td></tr>
<tr><td width="221" align="right">
<a href="oferta.php3" onmouseover="if ( (chBr('Netscape', '3') == true) || (chBr('Explorer', '4') ==
true) ) menu6.src='gfx/oferta_1.gif'"
onmouseout="if ( (chBr('Netscape', '3') == true) || (chBr('Explorer', '4') == true) )
menu6.src='gfx/oferta_0.gif'">
<img name="menu6" src="gfx/oferta_0.gif" alt="" border="0"></a></td></tr>
<tr><td width="290" align="right">
<a href="index.php3?ID=07" onmouseover="if ( (chBr('Netscape', '3') == true) || (chBr('Explorer', '4') ==
true) ) menu7.src='gfx/pkth_1.gif'"
onmouseout="if ( (chBr('Netscape', '3') == true) || (chBr('Explorer', '4') == true) )
menu7.src='gfx/pkth_0.gif'">
<img name="menu7" src="gfx/pkth_0.gif" alt="" border="0"></a></td></tr>
</table>

background image

49

<div align="center">

<!— wywolanie wyszukiwania -->

<form action="db.php3" method="post">
<b>Szukasz czegoś???</b><br>
<input style="color: #1c36b3; background-color: #CCAC0C; font-size: 8pt; font-weight: 800;"
type="Text" size="14" name="towar" style="width: 140px">
<input style="background-color: #1c36b3; color: #CCAC0C; font-size: 8pt; font-weight: 800;"
type="Submit" value="Szukaj">
</form>
</div>
</td>

<td valign="top">

<!— Dodatkowe elementy promocyjne -->

<? include "inc/targi2.inc"; ?>
</td>
</tr>
</table>
</div>
<br>

<?
}

# tutaj jezeli wyslane jest zapytanie inne niz null
else {

include "inc/menu.inc";
?>

<br>

<table cellpadding="0" cellspacing="0" border="0" width="750">
<tr>
<td align="center">

<?
include "inc/$ID.inc";

?>

</td></tr>
</table>
<? include "inc/stopka.inc"; ?>

<?
}

?>
</td></tr>
</table>

<br>
</body>
</html>

Skrypt ten jest wywoływany jako strona główna i od niego zaczyna działanie całość

wyszukiwania oraz nawigowania po stronach serwisu. Przy konstruowaniu serwisu
zbudowano moduł „oferta” generujący w predefiniowany sposób konkretne pozycje

tematyczne posiadanych towarów. Poniższy kod jest odpowiedzialny za obsługę
i wyświetlanie tych informacji.

background image

50

<?php
// obsluga bazy wyszukiwarki

// parametry glowne
include "inc/db.inc";

// licznik :>
include "inc/counter.inc";

// meta
include "inc/meta.inc";

// phpDB wrapper do baz danych, wkoncu to ma chodzic na wszystkim :)
include "lib/phpDB.inc";

// aktualizacja

$datam = filemtime('index.php3');
$filemodtime = date("j m Y h:i:s A", $datam);
$aktual = strftime ('%d.%m.%Y godzina %H:%M:%S', $datam);

?>
<script language="JavaScript"><!--
function chBr(br, ver) {

if (!(chBr.arguments.length > 0)) return (navigator.appName + ', ' + navigator.appVersion);
var Browser = br;
var Version = (chBr.arguments.length > 1) ? ver : null;
var BrowserFlag = (navigator.appName.toLowerCase() == Browser.toLowerCase()) ? true : false;
if (Version != null) {
var VersionFlag = (navigator.appVersion.substring(0,1) == Version.substring(0,1)) ? true : false;
}
return (BrowserFlag || VersionFlag);

}
function openr(dokument)
{
window.open(dokument,'parent[oferta]');
}
// --></script>
<title>-x(AGD)x- .::EuroMarket - Video Tomex::. -x(RTV)x-</title>

<script language="JavaScript">
function WinOpen(file) {

window.open(file,'_blank','toolbar=no,location=no,directories=no,status=no,menubar=no,scrollbars=yes,resi
zable=no,width=600,height=400');}
</script>

</HEAD>
<body>

<? include "inc/menu.inc"; ?>
<br>
<div align="center">

<table width="760" cellpadding="0" cellspacing="0" border="0">
<tr>

<td align="center" width="150" valign="top">
<table border="0" width="150" cellpadding="0" cellspacing="0">
<tr>
<tr><td align="center" height="16" style="background-color: #b32f1c; color: yellow"><strong>Nasza
Oferta</strong></td></tr>
</tr>
</table>

<br>
<table border="0">
<tr>

<td align="center">
<a style="font-size: 7pt" href="oferta.php3?show=telewizory">
<img src="gfx/tv.gif" alt="" border="0"><br>
telewizory
</a>
</td>

</tr>
<tr>

<td align="center">
<a style="font-size: 7pt" href="oferta.php3?show=magnetofony">

background image

51

<img src="gfx/mag.gif" alt="" border="0"><br>
magnetofony, radiomagnetofony
</a>
</td>

</tr>

<tr>

<td align="center">
<a style="font-size: 7pt" href="oferta.php3?show=pralki">
<img src="gfx/pralka.gif" alt="" border="0"><br>
pralki, zmywarki
</a>
</td>

</tr>

<tr>

<td align="center">
<a style="font-size: 7pt" href="oferta.php3?show=lodowki">
<img src="gfx/lodowka.gif" alt="" border="0"><br>
lodówki, zamrażarki
</a>
</td>

</tr>
<tr>

<td align="center">
<a style="font-size: 7pt" href="oferta.php3?show=vhsdvd">
<img src="gfx/magnetowid.gif" alt="" border="0"><br>
magnetowidy, odtwarzacze CD/DVD
</a>
</td>

</tr>
<tr>

<td align="center">
<a style="font-size: 7pt" href="oferta.php3?show=kuchnie">
<img src="gfx/kuchnia.gif" alt="" border="0"><br>
kuchnie
</a>
</td>

</tr>
<tr>

<td align="center">
<a style="font-size: 7pt" href="oferta.php3?show=odkurzacze">
<br>
odkurzacze
</a>
</td>

</tr>

</table>
<br>
<br>

</td>

<td width="610" valign="top" align="center">

<div align="center">
<table width="600" bgcolor="#e2b412" cellpadding="0" cellspacing="0" border="0">
<tr><td width="200" align="center" valign="baseline">
<form action="db.php3" method="post">

<strong>Potrzebujesz czego¶?</strong><BR>
<input style="color: #1c36b3; background-color: #CCAC0C; font-size: 8pt; font-weight: 800;"

type="Text" size="14" name="towar" style="width: 140px">

<br><br><input style="background-color: #1c36b3; color: #CCAC0C; font-size: 8pt;

font-weight: 800;" type="Submit" value="Szukaj">
</form>
</td>
<td valign="top">
Możesz szukać korzystając z symboli wieloznacznych:<br><br>
<table cellpadding="0" cellspacing="0" border="0">
<tr><td width="250" valign="bottom">
<B>*</B> -zastępuje dowolny ciąg znaków<BR>
<B>?</B> -zastępuje jeden znak</td>
<td valign="bottom">Na przykład:<B>telewizor*philips</B>
<br> Bez względu na wielkość znaków.</td></tr></table>
</td>
</tr>
</table>
</div>

background image

52

<br>

<?
// wyswietlamy konkretna _jedno_ lub _dwuwyrazowa_ kategorie
// np. $pokaz='pralka ariston'

if ($show == '') {

include "inc/oferta.inc";

}
else {
if ($show == 'pralki' ) {
include "inc/pralki.inc";
}
if ($show == 'telewizory' ) {
include "inc/tv.inc";
}
if ($show == 'lodowki' ) {
include "inc/lodowki.inc";
}
if ($show == 'magnetofony' ) {
include "inc/magnetofon.inc";
}
if ($show == 'vhsdvd' ) {
include "inc/vhsdvd.inc";
}
if ($show == 'kuchnie' ) {
include "inc/kuchnie.inc";
}
if ($show == 'odkurzacze' ) {
include "inc/odkurzacze.inc";
}

}
?>

<br>
<br>

<?
include "inc/stopka.inc";
?>
</td></tr></table>
</body></html>

Podsumowaniem całości kodu jest fragment obsługujący przyjęcie i zrealizowanie

zamówienia. W obecnym stadium rozwoju sklepu jest to realizowane poprzez wysłanie
przyjętych informacji pocztą email do obsługującego pracownika. Trwają prace nad

skonstruowaniem wygodnego i sprawnego w działaniu „koszyka” obsługującego komplet
czynności związanych z realizacją zamówień. Obecnie wykorzystywany formularz także jest

generowany dynamicznie przez skrypt napisany w PHP. Dane wprowadzane do formularza

są sprawdzane. Testowane jest wypełnienie wymaganych pól, niezbędnych do podjęcia
dalszych działań związanych z realizacja zamówienia.

background image

53

background image

54

Poniższy rysunek przedstawia proces wprowadzania danych na stronie formularza, tuż po
wybraniu odnośnika ukrytego pod postacią ikony koszyka sklepowego.

Całość realizowanych działań związanych ze złożeniem zamówienia wykonuje poniższy kod.

<? include "inc/meta.inc"; ?>
<title>-x(AGD)x- .::EuroMarket - Video Tomex::. -x(RTV)x-</title>

<script language="JavaScript">
function WinOpen(file) {

window.open(file,'_blank','toolbar=no,location=no,directories=no,status=no,menubar=no,scrollbars=no,resiz
able=no,width=300,height=240');
}
</script>
<script language="JavaScript"><!--
function chBr(br, ver) {

if (!(chBr.arguments.length > 0)) return (navigator.appName + ', ' + navigator.appVersion);
var Browser = br;
var Version = (chBr.arguments.length > 1) ? ver : null;
var BrowserFlag = (navigator.appName.toLowerCase() == Browser.toLowerCase()) ? true : false;
if (Version != null) {
var VersionFlag = (navigator.appVersion.substring(0,1) == Version.substring(0,1)) ? true : false;
}
return (BrowserFlag || VersionFlag);

}
function openr(dokument)
{

Rysunek 10 – Formularz realizacji zamówienia.

background image

55

window.open(dokument,'parent[oferta]');
}
// --></script>
</head>

<body>

<? include "inc/menu.inc"; ?>
<br>
<div align="center">
<?
if ( $wysylaj == 'tak' ) {

$zamowienie = $towar + "\n" + $imie;
$czas = date(H) . ":" . date(i) . ":" . date(s);

mail("sklep@vt.pl", "Zamowienie - $towar", "Zamówienia dokonano z adresu:
$REMOTE_ADDR -- godzina $czas\n\n
Nowe zamowienie internetowe!\n\n
Nazwa towaru: $towar\n
Ilość: $ilosc\n
Cena brutto: $brutto\n
Imię: $imie\n
Nazwisko: $nazwisko\n
Telefon: $telefon\n
Ulica: $ulica\n
Miejscowość: $miejscowosc\n
Województwo: $wojewodztwo\n
Dochody: $dochody zł\n\n
Dane firmy/instytucji:\n\n
Nazwa firmy/instytucji: $nazwa_firmy\n
NIP: $nip\n
Regon: $regon\n\n
Zamówienie należy zrealizować w przeci±gu 24 godzin! :>" , "From: emarket@localhost");
?>
<br><br><br>
<strong style="font-size: 15pt; font-weight: 900; color: ">Dziękujemy!!!</strong><br><br><br>
<strong>Zamówienie zostało wysłane, w ciągu 24 godzin skontaktujemy się w celu potwierdzenia
zakupu.</strong>
<br><br><br>
<strong><a style="font-size:11pt" class="fade"
href="http://vt.pl/index.php3?ID=05">Powrót do oferty</a></strong>
<?

}

else {

if ( $check == '' ) {
?>
<table width="550" cellpadding="0" cellspacing="0" border="0">
<tr>

<td align="center">

<strong style="font-size:14pt">Zamówienie: <strong style="color:#b32f1c">
<? echo $towar ?></strong></strong><br>
<strong style="font-size:11pt">Cena netto: <strong style="color:#b32f1c">
<? echo $netto ?></strong></strong>&nbsp;&nbsp;&nbsp;<strong style="font-size:11pt">
Cena brutto: <strong style="color:#b32f1c"><? echo $brutto ?></strong></strong>
<br><br>

Przed wysłaniem zamówienia należy wypełnić poniższy formularz. Po wysłaniu zamówienia w ci±gu 24 godzin
skontaktujemy się z Państwem w celu potwierdzenia zamówienia.
Pola, przy których znajduje się <strong style="color:#b32f1c">*</strong>
są niezbędne i należy je wypełnić.<br>
<br>
<form action="zakup.php3?check=confirm" method="post">
<table cellpadding="4" cellspacing="4" border="0">
<tr>

<td align="right"><strong>Towar<strong style="color:#b32f1c">*</strong></strong></td>
<td align="left"><input disabled maxlength="40" type="Text" style="width:160"

name="towar" value="<? echo $towar ?>"> </td>
</tr>
<tr>

<td align="right"><strong>Ilo¶ć (szt)<strong style="color:#b32f1c">*</strong></strong></td>
<td align="left"><input maxlength="3" value="1" type="Text" style="width:30" name="ilosc"> </td>

</tr>
<tr>

<td align="right"><strong>Imię<strong style="color:#b32f1c">*</strong></strong></td>
<td align="left"><input maxlength="40" type="Text" style="width:160" name="imie"> </td>

</tr>

background image

56

<tr>

<td align="right"><strong>Nazwisko<strong style="color:#b32f1c">*</strong></strong></td>
<td align="left"><input maxlength="40" type="Text" style="width:160" name="nazwisko"> </td>

</tr>
<tr>

<td align="right"><strong>Ulica/nr domu<strong style="color:#b32f1c">*</strong></strong></td>
<td align="left"><input maxlength="40" type="Text" style="width:160" name="ulica"> </td>

</tr>
<tr>

<td align="right"><strong>Miejscowo¶ć<strong style="color:#b32f1c">*</strong></strong></td>
<td align="left"><input maxlength="40" type="Text" style="width:160" name="miejscowosc"> </td>

</tr>
<tr>

<td align="right"><strong>Województwo</strong><strong style="color:#b32f1c">*</strong></td>
<td align="left">
<select name="wojewodztwo" id="wojewodztwo" style="width: 150">

<option value="none">wybierz</option>
<option value="zagranica">- zagranica -</option>
<option value="doloslaskie">dolnośląskie</option>
<option value="kujawsko-pomorskie">kujawsko-pomorskie</option>
<option value="lubelskie">lubelskie</option>
<option value="lubuskie">lubuskie</option>
<option value="lodzkie">łódzkie</option>
<option value="malopolskie">małopolskie</option>
<option value="mazowieckie">mazowieckie</option>
<option value="opolskie">opolskie</option>
<option value="podkarpackie">podkarpackie</option>
<option value="podlaskie">podlaskie</option>
<option value="pomorskie">pomorskie</option>
<option value="slaskie">śląskie</option>
<option value="swietokrzyskie">świętokrzyskie</option>
<option value="warmińsko-mazurskie">warmińsko-mazurskie</option>
<option value="wielkopolskie">wielkopolskie</option>
<option value="zachodniopomorskie">zachodniopomorskie</option>

</select>
</td>

</tr>
<tr>

<td align="right"><strong>Telefon<strong style="color:#b32f1c">*</strong></strong></td>
<td align="left"><input maxlength="40" type="Text" style="width:160" name="telefon"> </td>

</tr>

<tr>

<td align="right"><strong>Dochody (zł)</strong></td>
<td align="left">
<select name="dochody" id="dochody" style="width: 150">

<option value="none">wybierz</option>
<option value="-700">&lt;&lt; 700</option>
<option value="700-1400">700 - 1400</option>
<option value="1400-2000">1400 - 2000</option>
<option value="2000-3000">2000 - 3000</option>
<option value="3000-">3000 &gt;&gt;</option>

</select>
</td>

</tr>
</table>

</td></tr>
</table>
<br>
Poniższe dane należy wypełnić, jeżeli produkt jest zamawiany przez firmę lub instytucję.
<table cellpadding="4" cellspacing="4" border="0">
<tr>

<td align="right"><strong>Nazwa firmy<br>/instytucji</strong></td>
<td align="left"><input maxlength="40" type="Text" style="width:160" name="nazwa_firmy"> </td>

</tr>
<tr>

<td align="right"><strong>NIP</strong></td>
<td align="left"><input maxlength="40" type="Text" style="width:160" name="nip"> </td>

</tr>
<tr>

<td align="right"><strong>Regon</strong></td>
<td align="left"><input maxlength="40" type="Text" style="width:160" name="regon"> </td>

</tr>
</table>

<input type="Hidden" name="towar" value="<? echo $towar ?>"> </td>

background image

57

<input type="Hidden" name="netto" value="<? echo $netto ?>"> </td>
<input type="Hidden" name="brutto" value="<? echo $brutto ?>"> </td>
<input type="Submit" value="Wy¶lij">
</form>

<br><br>

<?
}
if ( $check == 'confirm' ) {
// Werykikacja; jezeli dane pole jest nie wypelnione zmienna $Zn przyjmuje
// wartosc $Z(n-1) + 1 jezeli na koncu zmienna $Z =/= 0 wraca do formularza
?>

<table cellpadding="2" cellspacing="2" border="0">
<tr>

<td align="right"><strong>Towar</strong></td>
<td align="left"><? echo $towar ?></td>

</tr>
<tr>

<td align="right"><strong>Ilość</strong></td>
<td align="left"><?

if ( $ilosc == '' ) {

echo "<strong style=\"color:#b32f1c\">Nie wypełniłeś tego pola!</strong>";
$z1 = 1;
}
else {
echo $ilosc;
$z1 = 0;
}
?>

</td>

</tr>
<tr>

<td align="right"><strong>Cena brutto</strong></td>
<td align="left"><?

echo $brutto;?> </td>

</tr>
<tr>

<td align="right"><strong>Imię</strong></td>
<td align="left"><?

if ( $imie == '' ) {

echo "<strong style=\"color:#b32f1c\">Nie wypełniłeś tego pola!</strong>";
$z2 = $z1 + 1;
}
else {
echo $imie;
$z2 = 0;
}
?>
</td>

</tr>
<tr>

<td align="right"><strong>Nazwisko</strong></td>
<td align="left"><?

if ( $nazwisko == '' ) {

echo "<strong style=\"color:#b32f1c\">Nie wypełniłeś tego pola!</strong>";
$z3 = $z2 + 1;
}
else {
echo $nazwisko;
$z3 = 0;
}
?>
</td>

</tr>
<tr>

<td align="right"><strong>Ulica/nr domu</strong></td>
<td align="left"><?

if ( $ulica == '' ) {

echo "<strong style=\"color:#b32f1c\">Nie wypełniłeś tego pola!</strong>";
$z4 = $z3 + 1;
}
else {
echo $ulica;
$z4 = 0;
}
?>
</td>

</tr>
<tr>

<td align="right"><strong>Miejscowość</strong></td>
<td align="left"><?

if ( $miejscowosc == '' ) {

echo "<strong style=\"color:#b32f1c\">Nie wypełniłeś tego pola!</strong>";

background image

58

$z5 = $z4 + 1;
}
else {
echo $miejscowosc;
$z5 = 0;
}
?>
</td>

</tr>
<tr>

<td align="right"><strong>Województwo</strong></td>
<td align="left"><?

if ( $wojewodztwo == '' ) {

echo "<strong style=\"color:#b32f1c\">Nie wypełniłeś tego pola!</strong>";
$z6 = $z5 + 1;
}
else {
echo $wojewodztwo;
$z6 = 0;
}
?>
</td>

</tr>
<tr>

<td align="right"><strong>Telefon</strong></td>
<td align="left"><?

if ( $telefon == '' ) {

echo "<strong style=\"color:#b32f1c\">Nie wypełniłeś tego pola!</strong>";
$z7 = $z6 + 1;
}
else {
echo $telefon;
$z7 = 0;
}
?>
</td>

</tr>

<tr>

<td align="right"><strong>Dochody (zł)</strong></td>
<td align="left"><?

if ( $dochody == '' ) {

echo "<strong style=\"color:#b32f1c\">Nie wypełniłeś tego pola!</strong>";
$z8 = $z7 + 1;
}
else {
echo $dochody . " zł";
$z8 = 0;
}
?>
</td>

</tr>
<tr>

<td align="right"><strong>Nazwa firmy<br>/instytucji</strong></td>
<td align="left"><?
if ( $nazwa_firmy == '' ) {
echo "brak";
}
else {
echo $nazwa_firmy;
$z9 = 0;
}
?></td>

</tr>
<tr>

<td align="right"><strong>NIP</strong></td>
<td align="left"><?
if ( $nip == '' ) {
echo "brak";
}
else {
echo $nip;
$z10 = 0;
}
?></td>

</tr>
<tr>

<td align="right"><strong>Regon</strong></td>
<td align="left"><?

if ( $regon == '' ) {

echo "brak";
}
else {

background image

59

echo $regon;
$z10 = 0;
}
?>
</td>

</tr>
</table>
<?
// sprawdzam formularz
$z = $z1 + $z2 + $z3 + $z4 + $z5 + $z6 + $z7 + $z8 + $z9 + $z10;
// jezeli jest ok
if ( $z == '0' ) {
?>
<form action="zakup.php3?wysylaj=tak" method="post">
<input type="Hidden" name="towar" value="<? echo $towar ?>">
<input type="Hidden" name="ilosc" value="<? echo $ilosc ?>">
<input type="Hidden" name="brutto" value="<? echo $brutto ?>">
<input type="Hidden" name="imie" value="<? echo $imie ?>">
<input type="Hidden" name="nazwisko" value="<? echo $nazwisko ?>">
<input type="Hidden" name="ulica" value="<? echo $ulica ?>">
<input type="Hidden" name="miejscowosc" value="<? echo $miejscowosc ?>">
<input type="Hidden" name="wojewodztwo" value="<? echo $wojewodztwo ?>">
<input type="Hidden" name="telefon" value="<? echo $telefon ?>">
<input type="Hidden" name="dochody" value="<? echo $dochody ?>">
<input type="Hidden" name="nazwa_firmy" value="<? echo $nazwa_firmy ?>">
<input type="Hidden" name="nip" value="<? echo $nip ?>">
<input type="Hidden" name="regon" value="<? echo $regon ?>">
<input type="Submit" value="Zamawiam!">
</form>
<?
}

else {
?>
Wymagane pola nie zostały wypełnione. Kliknij "Wstecz" aby to poprawić."
<form action="javascript:history.back();">
<input type="Submit" value="&lt;&lt; Wstecz">
</form>
<?
}

}

else {
exit;
}

}
?>
<br>
</div>
</body>
</html>

background image

60

Rozdział VI – K

IERUNK I DALSZEJ ROZBUDOWY SKLEPU

INTERNETOWEGO

M

ODUŁ INFORMACJI DODATKOWYCH

W trakcie realizacji projektu, w celu uatrakcyjnienia prezentowanych informacji,

skonstruowano mechanizm przechowywania dodatkowych danych o towarach. Ma to na

celu dostarczanie aktualnych danych technicznych oraz funkcjonalnych przeglądającym
ofertę internautom. Prezentowane wyniki wyszukiwania towarów uzupełniono o odnośniki

wywołujące dodatkowe okno z prezentowanymi informacjami. Obecnie trwają prace nad
budową i udostępnieniem formularzy do rejestrowania tych informacji. Z założenia będą one

wykorzystywane przez określone działy firmy do aktualizowania tych informacji oraz

dostępne jedynie z wewnątrz firmy. Informacje te obejmować będą swoim zakresem dane
szczegółowe o towarze, odnośniki do dodatkowych informacji na stronach producentów

sprzętu a także miniaturowe zdjęcia towaru. Po kliknięciu na miniaturowej fotografii

produktu, system załaduje w osobnym oknie normalnej wielkości fotografię, rysunek,
schemat a nawet film z przygotowaną prezentacją. Poniższy listing prezentuje kod

realizujący wygenerowanie okienka i wyświetlenie tych informacji.

<?php
// obsluga info o towarze

// parametry glowne
include "inc/db.inc";

// meta
include "inc/meta.inc";

// phpDB wrapper do baz danych, wkoncu to ma chodzic na wszystkim :)
include "lib/phpDB.inc";
?>
<title>Opis towaru</title>
</HEAD>
<body>
<br>
<?php

// czy mamy jave
if (strpos($HTTP_USER_AGENT, "ozilla") >0) {$jestjava=TRUE;} else {$jestjava=FALSE;};

// sprawdzamy czy akurat trwa ladowanie danych do bazy
// lamerskie, trzeba potem strugnac na lepsze
if ( ! file_exists("/tmp/emarket.tmp"))
{

//$towar z brany jest z tresci zapytania przegladarki trzeba go dobrze wyfiltrowac potem !!!
//trzeba oprogramowac wybor *? jak w dosie

if ($indeks=="" or $indeks==" "){

echo "<SCRIPT LANGUAGE=\"JavaScript\">\n";
echo "<!--\n";
echo "alert('Nie poda¦e czego szukasz!')\n";
echo "history.back()\n";
echo "//-->\n";
echo "</SCRIPT>\n";
echo "<B>Nie poda¦e czego szukasz!</B><BR>";
echo "<A HREF=\"$powrot\">Powrˇt</A>\n";
exit;}

background image

61

//jednorazowe stale i trwale polaczenie z baza

$db=new phpDB();
$db->pconnect($db_host,$db_user,$db_pass,$db_name) or die("Wystapił błąd przy łączeniu! <BR>\n ");

// wersja zapytania po optymalizacji
$sqlquery="SELECT * FROM informacje WHERE indeks=$indeks";

//echo $sqlquery . ";<BR><BR>\n";

$result = $db->execute($sqlquery) or die("Wystąpił błąd przy zapytaniu. <BR>\n");

$numrows=$result->getNumOfRows();
$numfields=$result->getNumOfFields();

/*
Wstepna struktura tabeli z informacjami – może ulec zmianie w trakcie rozwoju modulu
Table = informacje
+----------------------------------+----------------------------------+-------+
| Field | Type | Length|
+----------------------------------+----------------------------------+-------+
| indeks | int4 not null | 4 |
| podtyp | int4 not null default '0' | 4 |
| idpromocja | int4 not null default '0' | 4 |
| pokaz | char() default 'N' | 1 |
| skrot | varchar() default '' | 200 |
| tytul | varchar() default '' | 80 |
| opis | varchar() default '' | 4000 |
| link1 | varchar() default '' | 80 |
| link2 | varchar() default '' | 80 |
| flagi | varchar() default '' | 80 |
+----------------------------------+----------------------------------+-------+
*/

if (strtoupper($result->fields["pokaz"])!="T") {
echo "<div align=center><strong>Brak informacji dodatkowych o tym towarze.</strong></div>";
} else {
echo "<div style=\"margin-left: 20px;\" align=left>";
echo "<div align=left><B>Informacje dodatkowe:</B></div><BR>\n";

echo "<TABLE cellpadding=0 cellspacing=0 border=0 width=550>\n";
echo "<TR>";

echo "<TD align=left valign=top height=1 width=100><B class=\"cena\">Nazwa:&nbsp;</B></TD>";
echo "<TD>" . $nazwa

. "&nbsp;</TD>";

echo "</TR>\n";
echo "<TR>";

echo "<TD align=left valign=top height=1 width=100><B class=\"cena\">Tytul:&nbsp;</B></TD>";
echo "<TD valign=middle>" . $result->fields["tytul"]

."&nbsp;</TD>";

echo "</TR>\n";
echo "<TR>";

echo "<TD align=left valign=top height=1 width=100><B class=\"cena\">Skrˇt:&nbsp;</B></TD>";
echo "<TD valign=middle>" . $result->fields["skrot"]

."&nbsp;</TD>";

echo "</TR>\n";
echo "<TR>";

echo "<TD align=left valign=top height=1 width=100><B class=\"cena\">Opis:&nbsp;</B></TD>";
echo "<TD valign=middle>" . $result->fields["opis"] . "&nbsp;</TD>";

echo "</TR>\n";
echo "<TR>";

echo "<TD align=left valign=top height=1 width=100><B class=\"cena\">Link1:&nbsp;</B></TD>";
echo "<TD valign=middle>" . $result->fields["link1"]

."&nbsp;</TD>";

echo "</TR>\n";
echo "<TR>";

echo "<TD align=left valign=top height=1 width=100><B class=\"cena\">Link2:&nbsp;</B></TD>";
echo "<TD valign=middle>" . $result->fields["link2"]

."&nbsp;</TD>";

echo "</TR>\n";
echo "</TABLE>\n";

echo "</div>\n";
}

//zwalniamy pamiec i zamykamy polaczenie z baza
$result->close();
$db->close();

} //koniec warunku aktualizacji bazy
else { // wlasnie trwa aktualizacja sql'a
echo "<b style=\"color:#DB2614\">";
echo "Przepraszamy! <BR> Właśnie trwa aktualizacja bazy danych.<BR>";

background image

62

echo "Proszę spróbować ponownie za chwilę...<BR><BR></b>";
};

echo "<br>\n";

if ($jestjava) { echo "<a href=\"javascript:window.close()\">zamknij...</a>\n";}
else { echo "<a href=\"http://www.vt.pl/#szukaj\">powrˇt...</a>\n";};

?>
</body></html>

K

OSZYK NA TOWARY

Chcąc w sposób nowoczesny a zarazem wygodny udostępnić klientom możliwość
wirtualnego i swobodnego dodawania do koszyka i wyjmowania zamawianych towarów,

opracowywany jest model wirtualnego koszyka na bazie mechanizmów utrzymywania sesji
w PHP4. Zasadą działania tej metody jest utrzymywanie wirtualnej sesji stałego i trwałego

połączenia, pomiędzy aplikacją działającą na serwerze a przeglądarką klienta. Protokół

HTTP nie został stworzony do tego celu i nie zapewnia trwałego utrzymywania połączenia.
Po wysłaniu danych do przeglądarki połączenie jest zamykane przez serwer. Komplikuje to

w znaczącym stopniu konstruowanie aplikacji wymagających trwałości nawiązanych

połączeń. Wprowadzony mechanizm sesji pozwala na wysyłanie pewnych unikalnych danych
do przeglądarki a po każdej zmianie strony ich zwrotny odbiór. Pozwala to na jednoznaczne

identyfikowanie klienta oraz dywersyfikację zachowania aplikacji w zależności od kontekstu
i użytkownika. Mechanizm sesji realizowany jest bądź przy użyciu „ciasteczek” (pliki

„cookies”), bądź poprzez generowanie tzw. „długich adresów URL”. PHP4 potrafi

samoczynnie rozpoznać czy przeglądarka akceptuje przyjmowanie „cookies” i w przypadku
gdy to nie jest możliwe, przełącza się na posługiwanie długimi adresami. W celu

utrzymywania takiej wirtualnej sesji konieczne jest otwarcie sesji i przekazywanie

identyfikatora sesji pomiędzy kolejnymi wywołaniami stron aplikacji. Dane przypisane do
sesji mogą być przechowywane bądź w bazie danych SQL, bądź jako tymczasowe pliki na

serwerze. Po zakończeniu sesji należy porzucić identyfikator sesji i usunąć przechowywane
dane o sesji. Utrzymywanie sesji można ustanowić na np. 30 minut w celu zachowania

jeszcze przez pewien czas „trwałości” zgromadzonych danych. Gdyby bowiem połączenie

z przeglądarką klienta mogło być utracone na skutek błędów sieci czy też zawieszenia
komputera itp. ponowne połączenie z przeglądarki z niewygasłą sesją „natrafi” na

utrzymywaną sesję po stronie serwera i pozwoli kontynuować realizację zakupów.

Mechanizmy tu przedstawione są szczegółowo opisywane w doskonałej dokumentacji
PHP4 (

www.php.net/manual-lookup.php?pattern=session

).

background image

63

Podsumowanie

Na podstawie doświadczeń zebranych podczas budowy aplikacji sklepu internetowego,
można z całą pewnością stwierdzić, iż na obecnym etapie rozwoju oprogramowania

OpenSource jest możliwe szybkie i efektywne projektowanie oraz wdrażanie różnego

rodzaju systemów i aplikacji sieciowych. Wysoka jakość oprogramowania tworzonego przez
społeczność internetową, gwarantuje zarówno dalszy efektywny rozwój tej idei darmowego

tworzenia systemów, czy też wręcz ustanawiania nowych standardów. Rozwój publicznie
dostępnego oprogramowania umożliwia samodzielne budowanie skomplikowanych

serwisów internetowych, finansowych, naukowych czy rozrywkowych. Kod źródłowy jest

powszechnie dostępny co doskonale wpływa na szybkość poprawiania znalezionych błędów
a tym samym na wysoką jakość tworzonych systemów. Dokumentacja tworzona na potrzeby

rozwijanych narzędzi jest wysokiej jakości „źródłem” niewyczerpanej wprost wiedzy. Projekt

sklepu internetowego początkowo pomyślany jako niewielki program promowania
i sprzedaży towarów, rozwija się szybko w kierunku całego i skomplikowanego systemu,

zapewniającego nie tylko obsługę sprzedaży online. Niejako „przy okazji” powstał cały
serwis internetowy firmy, rozwijane są moduły realizowania zamówień. W planach

przewidziane jest skonstruowanie platformy współpracy i wymiany towarowej pomiędzy

partnerami handlowymi. Korzystając ze zbudowanego zaplecza informatycznego, wdrożono
systemy pocztowe, autoryzacji umów sprzedaży ratalnej, natychmiastowej aktywacji

telefonów PlusGSM i wiele innych. Zastosowane narzędzia pozwoliły na znaczne

oszczędności i były ekonomicznie uzasadnionym rozwiązaniem szczególnie polecanym dla
firm sektora małej i średniej przedsiębiorczości.

background image

64

Spis literatury

[1] Fred Butzen, Dorothy Forbes, „Linux bazy danych” Mikom 1999r
[2] Hans Ladanyi, „SQL Księga eksperta” Helion 2000r

[3] W. Richard Stevens, „UNIX programowanie usług sieciowych” WNT 2000r

[4] Vijay Ahuja, „Bezpieczeństwo w sieciach” Mikom 1997r
[5] Craig Hunt, „TCP/IP Administracja sieci” READ ME 1998r

[6] Æleen Frisch, „UNIX Administracja systemu” READ ME 1997r
[7] D. Brent Chapman, Elizabeth D. Zwicky, „Building Internet Firewalls” O’Reilly 1995r

[8] S. Garfinkel, G. Spafford, „Bezpieczeństwo w UNIXie i Internecie” READ ME 1997r

[9] Bruce Momjian, „PostgreSQL Introduction and Concepts” Addison-Wesley 2001r
[10] „PHP Manual” PHP Documentation Group 2001r

[11] „FreeBSD Handbook” The FreeBSD Documentation Project 2001r

[12] „PostgreSQL Guide” PostgreSQL Global Development Group 2001r

background image

65

Streszczenie - Abstract

Wyższa Szkoła Informatyki i Zarządzania Rzeszów,

2001-07-12

Wydział Administracyjno–Informatyczny

Streszczenie pracy dyplomowej licencjackiej

Implementacja systemu sklepu internetowego

na bazie oprogramowania OpenSource.

Autor: Bartłomiej Siębab
Promotor: Dr inż. Janusz Świerzowicz

Implementacja projektu systemu sklepu internetowego przy wykorzystaniu narzędzi
OpenSource. Zastosowano technologię generowania stron internetowych w oparciu o język
skryptowy PHP, JavaScript, HTML oraz style kaskadowe CSS. Dynamiczne pobieranie
danych z bazy PostgreSQL umożliwiło zbudowanie efektywnego mechanizmu wyszukiwania

i prezentowania towarów.

University of Information Technology and Management

Rzeszów, 2001-07-12

Faculty of Administration and Computer Sciences

Diploma Thesis (BA) Abstract

OpenSource based software implementation

of internet shopping system.

Author: Bartłomiej Siębab
Supervisor: Dr Eng. Janusz Świerzowicz

The purpose of this work was to implement Internet shopping system based on OpenSource
software. Used technology allow dynamically produce HTML pages assembled with PHP,
JavaScript and cascading style sheet (CSS) templates. Efficient database engine based on

PostgreSQL and PHP persistent connections allows developing helpful search and
presentation system.

background image

66

Spis treści

WSTĘP ........................................................................................................................................................................ 2

CEL I ZAKRES PRACY ........................................................................................................................................... 3

ROZDZIAŁ I – ZAŁOŻENIA WSTĘPNE, PRZEDSTAWIENIE METOD I NARZĘDZI................................ 4

U

WARUNKOWANIA EKONOMICZNE

........................................................................................................................... 4

P

REZENTACJA BAZY SYSTEMOWEJ OPROGRAMOWANIA

............................................................................................ 5

ROZDZIAŁ II – TEORIA I FUNKCJONOWANIE............................................................................................... 8

W

YMAGANIA UŻYTKOWNIKÓW

................................................................................................................................ 8

M

ARKETING I REKLAMA

........................................................................................................................................... 9

Z

ASADA DZIAŁANIA

................................................................................................................................................ 11

M

ODEL LOGICZNY I FUNKCJONALNY

...................................................................................................................... 12

ROZDZIAŁ III – PRZYGOTOWANIE DANYCH............................................................................................... 15

KONWERSJA DANYCH

.............................................................................................................................................. 15

ARCHIWIZACJA I PRZESYŁANIE DANYCH

................................................................................................................. 17

S

TRUKTURA KONWERTOWANYCH PLIKÓW

............................................................................................................. 18

K

ONWERSJA STRONY KODOWEJ

.............................................................................................................................. 19

Z

AŁADOWANIE DANYCH DO BAZY

P

OSTGRE

SQL ................................................................................................... 20

ROZDZIAŁ IV – STRUKTURA I ORGANIZACJA BAZY EMARKET .......................................................... 24

S

KRYPTY ADMINISTRACYJNE

.................................................................................................................................. 24

S

KRYPTY

SQL ........................................................................................................................................................ 29

Kategoria skryptów „create” ........................................................................................................................... 29

Kategoria skryptów „delete”............................................................................................................................ 32

Kategoria skryptów „load” .............................................................................................................................. 33

Kategoria skryptów „check” ............................................................................................................................ 35

Kategoria skryptów „analysis” ........................................................................................................................ 35

S

TRUKTURA BAZY

.................................................................................................................................................. 36

ROZDZIAŁ V – WYSZUKIWARKA TOWARÓW ............................................................................................. 38

K

ONCEPCJA DZIAŁANIA

.......................................................................................................................................... 38

K

OD ŹRÓDŁOWY WYSZUKIWARKI

........................................................................................................................... 42

ROZDZIAŁ VI – KIERUNKI DALSZEJ ROZBUDOWY SKLEPU INTERNETOWEGO ............................ 60

M

ODUŁ INFORMACJI DODATKOWYCH

..................................................................................................................... 60

K

OSZYK NA TOWARY

.............................................................................................................................................. 62

PODSUMOWANIE .................................................................................................................................................. 63

SPIS LITERATURY................................................................................................................................................. 64

STRESZCZENIE - ABSTRACT ............................................................................................................................. 65

SPIS TREŚCI ............................................................................................................................................................ 66


Document Outline


Wyszukiwarka

Podobne podstrony:
streszczenie panelu, Prace dyplomowe i magisterskie, praca dyplomowa, materiały z internetu
Szkolenie iso zetom, Prace dyplomowe i magisterskie, praca dyplomowa, materiały z internetu
ISO PPJ, Prace dyplomowe i magisterskie, praca dyplomowa, materiały z internetu, iso 9000
iso 7, Prace dyplomowe i magisterskie, praca dyplomowa, materiały z internetu, iso 9000
IS0900, Prace dyplomowe i magisterskie, praca dyplomowa, materiały z internetu, iso 9000
ISO 4, Prace dyplomowe i magisterskie, praca dyplomowa, materiały z internetu, iso 9000
Praca Dyplomowa technikum internet, Informatyka
iso 2, Prace dyplomowe i magisterskie, praca dyplomowa, materiały z internetu, iso 9000
nadzor nad dokumentacja iso, Prace dyplomowe i magisterskie, praca dyplomowa, materiały z internetu
Praca Dyplomowa Informatyka Internet-Rola I Znaczenie Internetu, PRACA MAGISTERSKA INŻYNIERSKA DYPLO
iso 5, Prace dyplomowe i magisterskie, praca dyplomowa, materiały z internetu, iso 9000
streszczenie panelu, Prace dyplomowe i magisterskie, praca dyplomowa, materiały z internetu
Internet - UE prawo, Studia - IŚ - materiały, Semestr 07, Praca dyplomowa
praca dyplomowa Wykonanie układu połączeń i konfiguracja urządzenia Stałego Dostępu do Internetu(1)
praca licencjacka(9)Bankowość Internetowa jako nowa forma usługi bankowej, PRACA MAGISTERSKA INŻYNIE
praca dyplomowa wytyczne 2011 03 02, Studia - Politechnika Opolska, Semestr 6, Techniki Internetowe
Praca Dyplomowa Cala - Witryna internetowa, Różne
Internet - UE prawo, Studia - IŚ - materiały, Semestr 07, Praca dyplomowa

więcej podobnych podstron