2008.11_Sklep internetowy w PHP i SQLite_[Aplikacje Biznesowe].pdf
(
908 KB
)
Pobierz
441067342 UNPDF
E-commerce
Sklep internetowy
w PHP i SQLite
Zaprojektuj i zbuduj w mniej niż godzinę
Gotowych rozwiązań na rynku e-commerce są setki. Znajdziemy gotowe
skrypty o funkcjonalności systemów aukcyjnych, sklepów internetowych
oraz systemów barterowych. To najczęściej sprawdzone i tanie rozwiązania,
regularnie aktualizowane – dlatego skorzystanie z nich najczęściej bywa bardzo
kuszące. Jednak czy zawsze uzasadnione? Najczęściej o wiele lepiej stworzyć
własną platformę e-commerce. Nie jest to trudne – nam zajmie to 60 minut.
Dowiesz się:
• Jak zaprojektować od podstaw sklep interne-
towy;
• W jaki sposób korzystać z SQLite;
• Jak wykorzystać sesje do przechowywania da-
nych użytkownika.
Powinieneś znać:
• Co najmniej podstawy PHP oraz SQL;
• Podstawy programowania obiektowego.
zostać również umieszczony w konkretnej
kategorii – ułatwi to przeszukiwanie sklepu
użytkownikowi.
Klient naszego sklepu w przypadku doko-
nania zakupu powinien przekazać nam da-
ne niezbędne do zrealizowania zamówienia
(m.in. imię, nazwisko, adres, dane do faktu-
ry, dane wysyłki). Przyjęliśmy więc, że w ce-
lu dokonania zakupu konieczne jest posia-
danie konta w systemie. Rejestracja powin-
na być oczywiście bezpłatna, a klient powi-
nien mieć również możliwość samodzielne-
go usunięcia konta.
Warto również pomyśleć o systemie ra-
batów – pozwoli to zatrzymać klienta oraz
uatrakcyjnić cenowo naszą ofertę. Rabat mo-
żemy uzależnić od wielu elementów – wiel-
kości zakupów, kodu promocyjnego podane-
go podczas rejestracji lub przekroczenie okre-
ślonej wartości wszystkich zakupów od chwi-
li zarejestrowania konta. W naszym sklepie
rabat będzie przydzielany ręcznie przez ad-
ministratora – czytelnik jednak bez więk-
szych problemów będzie w stanie dopasować
system rabatowy do własnych potrzeb.
Ostatnim niezbędnym elementem jest lista
zamówień. Zastanówmy się jakie informacje
są naprawdę potrzebne do sprawnego obsłuże-
nia klienta. W większości przypadków powin-
no wystarczyć imię i nazwisko zamawiającego,
adres wysyłki, data złożenia zamówienia, stan,
data wysłania towarów oraz oczywiście zamó-
wione towary.
go wpływu na poziom trudności pracy. Dlate-
go nasz sklep zbudujemy wykorzystując PHP5
oraz… SQLite.
Poziom trudności
Przed rozpoczęciem pracy…
… należy zastanowić się nad funkcjonalnością
sklepu. Chcemy oczywiście sprzedawać okre-
ślone produkty – to oczywiste. Zastanówmy
się jednak, co dokładnie chcemy przedsta-
wić potencjalnemu nabywcy. Na pewno bę-
dzie to nazwa produktu oraz jego opis. Lu-
dzie lubią widzieć, co kupują, wskazane jest
więc umieszczenie co najmniej jednego zdję-
cia. Część produktów wymaga dokładniejsze-
go sfotografowania, tak więc nie powinniśmy
ograniczyć maksymalnej liczby zdjęć. Oczy-
wiście niezbędne jest również uwzględnienie
ceny oraz stawkę podatku VAT. W zależno-
ści od typu produktów można pomyśleć rów-
nież nad dodatkowymi polami określający-
mi jego parametry (dla sklepu z butami war-
to pomyśleć o polach z rozmiarami, sprzeda-
jąc dyski twarde warto zaznaczyć ich pojem-
ność) a jeśli znamy stan magazynu możemy
również wykorzystać tą informację. Nie ma
bowiem sensu pokazywać użytkownikowi to-
waru, którego nie mamy na stanie, lub który
został już raz sprzedany. Produkt powinien
żać gotowych rozwiązań może być wie-
le. Dla prostego sklepu internetowego,
w którym właściciel chce zaoferować kilka pro-
duktów wykorzystanie osCommerce może być
nieoptymalne. Dodatkowo modyfikowanie ta-
kiej gotowej platformy również nie należy do
rzeczy najprostszych – jeśli dostępna jest do-
kumentacja, wystarczy się z nią zapoznać. Jeśli
jednak jej nie ma, pozostaje metoda prób i (nie-
stety najczęściej) błędów. W obu przypadkach
potrzebujemy czasu – który możemy poświę-
cić na stworzenie własnego, dedykowanego roz-
wiązania. Za chwilę zobaczysz, że w mniej niż
60 minut można zbudować sklep interneto-
wy, który pomimo okazałej nazwy jest po pro-
stu interfejsem pośredniczącym pomiędzy ba-
zą danych a użytkownikiem, wykonującym na
niej określone operacje. Struktura takiej ba-
zy najczęściej nawet nie jest bardzo skompli-
kowana, tak więc można użyć praktycznie do-
wolnego silnika baz danych. Nie ma to żadne-
Minuta pierwsza – baza danych
Na początku prac zaprojektujemy struktu-
rę naszej bazy danych. Do stworzenia ba-
20
11/2008
P
owodów, dla których nie warto wdra-
Sklep internetowy w PHP i SQLite
zy można użyć zewnętrznych narzędzi (np.
zewnętrzny SQLite Manager działający ja-
ko dodatek do przeglądarki Mozilla Firefox)
lub napisanego samodzielnie prostego skryp-
tu w PHP.
Wystarczy do tego podstawowa znajomość
języka SQL oraz funkcji wbudowanych w PHP
służących do komunikacji z bazą sqlite.
Gotowy skrypt przedstawiony jest na Li-
stingu 1. Jego działanie jest proste – łączy-
my się z plikiem bazy danych, oraz wywo-
łujemy 5 zapytań tworzących 5 tabel – ta-
belę do przechowywania informacji o użyt-
kownikach, produktach, dostępnych kate-
goriach, oraz dwie tabele do przechowywa-
nia informacji o zamówieniach użytkowni-
ka. Strukturę utworzonych tabel przedsta-
wia Rysunek 1.
Część z was najprawdopodobniej zauwa-
żyła, że brakuje pól w których będą przecho-
wywane informacje o zdjęciach produktów.
Zamiast tego, zdjęcia będą miały nazwę od-
powiadającą unikalnemu polu zawierające-
mu unikalne ID produktu, znak separato-
ra (podkreślnik) oraz kolejny numer zdję-
cia produktu. Pozwoli to na umieszczenie
praktycznie nieograniczonej ilości zdjęć.
PHP dostarcza nam mechanizm umożliwia-
jący proste sprawdzenie czy plik w określo-
nej lokalizacji istnieje (służy do tego funk-
cja
file_exist()
) – dzięki temu nie musi-
my przechowywać informacji o tym fakcie w
bazie danych.
Zdziwić może również brak atrybutów
AUTOINCREMENT
przy tworzeniu bazy. Jest to
związane z tym, że w SQLite wszystko jest łań-
cuchem znaków. Typ kolumny pomaga silniko-
wi bazy dane te odpowiednio posortować, oraz
zwiększa przejrzystość tabel.
Autorzy jednak udostępnili substytut atry-
butu – wystarczy zadeklarować w tabeli pole
INTEGER PRIMARY KEY
.
Minuta 10 – obiekty
W kolejnym kroku utworzymy klasy repre-
zentujące trzy podstawowe typy obiektów
które zdefiniowaliśmy na początku artyku-
łu – dla użytkownika, produktu, oraz za-
mówienia.
W każdej klasie oprócz pól charaktery-
stycznych dla bazy danych znajduje się rów-
nież prywatne pole
error
– wykorzystamy
je do zapisywania informacji o ewentual-
nym błędzie (na przykład błędzie podczas
połączenia z bazą danych, lub nieprawidło-
wych danych logowania). Przyjmijmy rów-
nież, że wszystkie funkcje i metody zwraca-
ją wartość logiczną – prawdę, gdy realizowa-
na operacja się powiedzie, oraz fałsz gdy wy-
stąpi jakikolwiek błąd. Dzięki temu spraw-
dzenie poprawności wykonania nawet cy-
klu operacji jest dziecinnie proste – sprowa-
dza się do wprowadzenia kilku instrukcji wa-
runkowych.
Listing 1.
Skrypt tworzący tabele w bazie danych
<?
php
include
'conig.php'
;
if
(
$db
= sqlite_open
(
$sqlitePath
, 0666,
$sqliteerror
))
{
sqlite_query
(
$db
,
'CREATE TABLE "users" ( "users_id" INTEGER PRIMARY KEY , "users_username" TEXT NULL , "users_name" TEXT NULL
, "users_city" TEXT NULL , "users_postcode" TEXT NULL , "users_adress" TEXT NULL , "users_phone" TEXT NULL
, "users_mail" TEXT NULL , "users_dname" TEXT NULL , "users_deliverycity" TEXT NULL , "users_password" TEXT
NULL , "users_deliverypostcode" TEXT NULL , "users_deliveryaddress" TEXT NULL , "users_discount" TEXT NULL ,
"users_nip" TEXT NULL );'
)
;
sqlite_query
(
$db
,
'CREATE TABLE "products" ("products_id" INTEGER PRIMARY KEY , "products_name" TEXT NULL , "products_
description" TEXT NULL , "products_price" TEXT NULL , "products_tax" INT NULL , "products_count" INT NULL ,
"products_categoryid" INT NULL );'
)
;
sqlite_query
(
$db
,
'CREATE TABLE "category" ( "category_id" INTEGER PRIMARY KEY , "category_name" NULL);'
)
;
sqlite_query
(
$db
,
'CREATE TABLE "orders" ( "order_id" INTEGER PRIMARY KEY , "order_userid" INT NULL , "order_date" INT NULL ,
"order_status" TEXT NULL , "order_sdate" INT NULL );'
)
;
sqlite_query
(
$db
,
'CREATE TABLE "order_products" ( "product_id" INTEGER PRIMARY KEY , "order_id" INT NOT NULL , "op_amount" INT
NOT NULL );'
)
;
sqlite_close
(
$db
)
;
echo
'Tabele zosta³y utworzone!'
;
}
else
{
die
(
'Wystąpił błąd: '
.
$sqliteerror
)
;
}
?>
Listing 2.
Zawartość pliku conig.php
<?
php
$sqlitePath
=
'./sklep2.sqlite'
;
session_start
()
;
function __autoload(
$class_name
)
{
require_once
'./class/'
.
$class_name
.
'.php'
;
}
?>
www.sdjournal.org
21
E-commerce
Listing 3a.
Fragment klasy user – służącej do obsługi użytkownika
class
user
{
public
$id
;
public
$username
;
public
$password
;
public
$name
;
public
$city
;
public
$postcode
;
public
$adress
;
public
$phone
;
public
$mail
;
public
$dname
;
public
$deliverycity
;
public
$deliverypostcode
;
public
$deliveryadress
;
public
$discount
;
public
$nip
;
private
$error
;
function __constuct(
$id
=
''
)
{
if
(
$id
!=
''
)
$this
-
>
load
(
$id
)
;
}
function load(
$id
)
{
if
(
$db
= sqlite_open
(
$sqlitePath
, 0666,
$this
-
>
error
))
{
$value
= sqlite_array_query
(
$db
, "SELECT * FROM users
WHERE users_id =
'".$id."'");
}
}
function checklogin(
$username
,
$password
)
{
if
(
$db
= sqlite_open
(
$sqlitePath
, 0666,
$this
-
>
error
))
{
$value
= sqlite_array_query
(
$db
, "SELECT users_id
FROM users WHERE users_username =
'".$username."'
AND
users_password =
MD5
(
".
$password
."
)
"
)
;
if
(
sqlite_num_rows
(
$db
)
== 0
)
{
$this
-
>
error =
'Nieprawid³owa nazwa u¿ytkownika
lub has³o!'
;
sqlite_close
(
$db
)
;
return
-1;
}
return
$value
[
'users_id'
]
;
}
else
{
return
0;
}
}
function add(
$username
,
$password
,
$name
,
$city
,
$postcode
,
$adress
,
$phone
,
$mail
,
$dname
,
$deliverycity
,
$deliverypostcode
,
$deliveryadress
,
$discount
,
$nip
)
{
$this
-
>
username = sqlite_escape_string
(
$username
)
;
$this
-
>
password = sqlite_escape_string
(
$password
)
;
$this
-
>
name = sqlite_escape_string
(
$name
)
;
$this
-
>
city = sqlite_escape_string
(
$city
)
;
$this
-
>
postcode = sqlite_escape_string
(
$postcode
)
;
$this
-
>
adress = sqlite_escape_string
(
$adress
)
;
$this
-
>
phone = sqlite_escape_string
(
$phone
)
;
$this
-
>
mail
= sqlite_escape_string
(
$mail
)
;
$this
-
>
dname = sqlite_escape_string
(
$dname
)
;
$this
-
>
deliverycity = sqlite_escape_
string
(
$deliverycity
)
;
$this
-
>
deliverypostcode = sqlite_escape_string
(
$delivery
postcode
)
;
$this
-
>
deliveryadress = sqlite_escape_
string
(
$deliveryadress
)
;
$this
-
>
discount = sqlite_escape_string
(
$discount
)
;
$this
-
>
nip = sqlite_escape_string
(
$nip
)
;
if
(
$this
-
>
validate
())
{
if
(
$db
= sqlite_open
(
$sqlitePath
, 0666,
$this
-
>
error
))
if(sqlite_num_rows(
$value
) == 0)
{
$this
->error = "
Brak u¿ytkownika o podanym id!";
return
false;
}
$this
-
>
id =
$value
[
'users_id'
]
;
$this
-
>
username =
$value
[
'users_username'
]
;
$this
-
>
password =
$value
[
'users_password'
]
;
$this
-
>
name =
$value
[
'users_name'
]
;
$this
-
>
city =
$value
[
'users_city'
]
;
$this
-
>
postcode =
$value
[
'users_postcode'
]
;
$this
-
>
adress =
$value
[
'users_adress'
]
;
$this
-
>
phone =
$value
[
'users_phone'
]
;
$this
-
>
mail
=
$value
[
'users_mail'
]
;
$this
-
>
dname =
$value
[
'users_dname'
]
;
$this
-
>
deliverycity =
$value
[
'users_deliverycity'
]
;
$this
-
>
deliverypostcode =
$value
[
'users_
deliverypostcode'
]
;
$this
-
>
deliveryadress =
$value
[
'users_
deliveryadress'
]
;
$this
-
>
discount =
$value
[
'users_discount'
]
;
$this
-
>
nip =
$value
[
'users_nip'
]
;
$this
-
>
error=
''
;
sqlite_close
(
$db
)
;
return
true;
}
else
{
return
false;
{
sqlite_array_query
(
$db
,
"INSERT INTO users (users_
id, users_username, users_password,
users_name, users_city, users_postcode,
users_adress, users_phone, users_mail,
users_dname, users_deliverycity, users_
deliverypostcode, users_deliveryadress,
users_discount, users_nip) VALUES
22
11/2008
Sklep internetowy w PHP i SQLite
W naszym systemie skorzystamy z mecha-
nizmu automatycznego ładowania plików
z klasami wprowadzonego w piątej wersji
PHP. Dlatego klasy, z których będziemy korzy-
stać bezpośrednio w skrypcie musimy umie-
ścić w osobnych plikach o nazwach takich sa-
mych jak nazwy klas.
Sama funkcja
__autoload()
umieszczona
została w pliku
config.php
. Plik ten dołącza-
ny jest na początku projektu – gwarantuje to,
że funkcja będzie dostępna w każdym miej-
scu skryptu.
W pliku tym zdefiniowaliśmy również na-
zwę pliku z bazą danych oraz wystartowaliśmy
mechanizm sesji.
Klasa posiada zdefiniowany jednoparame-
trowy konstruktor. Podanie parametru nie
jest jednak konieczne – jeśli nie zostanie po-
dany, zostanie utworzony pusty obiekt. Jeśli
jednak jako parametr podamy
id
użytkow-
nika, zostanie wywołana metoda
load()
któ-
��������
��������������
�����
���������������
������������������
�������������������������
�������������������
����������������
������������������
�����������������������
��������������
������������
�������������
������������
�������������������
���������������
���������������
�������������������
�����������������
����������������
���������������
����������������
�����������������������
��������������������������
���������������������������
��������������������������
�������������������
��������������
�������
�������
Użytkownik
Na Listingu 3a i 3b przestawiono fragment
klasy reprezentującej użytkownika. Powinna
ona dostarczyć nam wszystkich operacji nie-
zbędnych do obsługi użytkownika. Wszyst-
kie pola wyłączając pole
$error
są publicz-
ne – chcemy mieć bowiem do nich dostęp
w każdym miejscu skryptu. Oczywiście mo-
żesz utworzyć zmienne prywatne i utwo-
rzyć metodę do ich zwracania. Pole
error
nie powinno być modyfikowane z zewnątrz
klasy – dlatego pozostanie prywatne, a do-
stęp do jego zawartości spoza klasy odby-
wa się wyłącznie za pośrednictwem meto-
dy
geterror()
.
��������
������
���������������
�������������
������������
����������������
��������������
�����������������
���������������
�������
�������
�������
Rysunek 1.
Schemat utworzonej bazy danych
Listing 3b.
Fragment klasy user – służącej do obsługi użytkownika
(NULL, "
.
$this
-
>
username.
", "
.
$this
-
>
password.
", "
.
$this
-
>
name.
",
"
.
$this
-
>
city.
", "
.
$this
-
>
postcode.
",
"
.
$this
-
>
adress.
", "
.
$this
-
>
phone.
",
"
.
$this
-
>
mail
.
", "
.
$this
-
>
dname.
",
"
.
$this
-
>
deliverycity.
", "
.
$this
-
>
deliverypostcode.
", "
.
$this
-
>
deliveryadress.
", "
.
$this
-
>
discount.
",
"
.
$this
-
>
nip.
");"
)
;
sqlite_close
(
$db
)
;
return
true;
}
else
{
return
false;
}
}
}
function validate(
)
{
//realizację funkcji validate pozostawiamy czytelnikowi.
//funkcja powinna zwróciæ false gdy nie podano wszystkich
wymaganych pól
return
true;
}
function geterror(
)
{
return
$this
-
>
error;
}
}
Listing 4.
Metoda updatecount() klasy product
function updatecount(
$id
,
$newcount
)
{
if
(
$db
= sqlite_open
(
$sqlitePath
, 0666,
$this
-
>
error
))
{
sqlite_array_query
(
$db
, "UPDATE products SET products_
count =
'".$newcount."'
WHERE products_
id =
'".$this->id."'
;"
)
;
sqlite_close
(
$db
)
;
return
true;
}
else
{
return
false;
}
}
www.sdjournal.org
23
E-commerce
Listing 5.
Fragment odpowiedzialny za wyświetlenie kategorii oraz spisu towarów
<?
php
include
'conig.php'
;
$error
=
''
;
$categories
=
array
()
;
$products
=
array
()
;
if
(
$db
= sqlite_open
(
$sqlitePath
, 0666,
$error
))
{
//wybieramy wszystkie dostêpne kategorie
$table
= sqlite_array_query
(
$db
,
'SELECT * FROM category'
)
;
foreach
(
$table
as
$value
)
{
$categories
[]
=
array
(
$value
[
'category_id'
]
,
$value
[
'category_name'
])
;
}
//Wyœwietlamy u¿ytkownikowi menu z wyborem kategorii:
echo
'
<
div name=
"categories"
>
';
foreach($categories as $category)
{
echo '
<
a href=
"list.php?category='.$category[0].'"
>
'.$category[1].'
<
/a
><
br
>
';
}
echo '
<
/div
>
';
//sprawdzamy, czy u¿ytkownik wybra³ kategorie:
if
(
$_GET
[
'category'
]
==
''
)
{
echo
'
<
div name=
"message"
>
Witaj w naszym sklepie internetowym! Wybierz interesuj¹c¹ Ciê kategorie!
<
/div
>
';
}
else
{
//jeœli tak - pobieramy towary z bazy:
$table
= sqlite_array_query
(
$db
,
'SELECT products_id FROM products WHERE products_categoryid = "'
.sqlite_escape_string
(
$_
GET
[
'category'
])
.
'" AND products_count>0;'
)
;
if
(
count
(
$table
)
==0
)
{
echo
'
<
div name=
"message"
>
Nie znaleziono produktów w kategorii!
<
/div
>
';
}
else
{
foreach($table as $value)
{
$products[] = $value['
products_id'
]
;
}
//oraz wyœwietlamy:
echo
'
<
div name=
"products"
>
';
foreach($products as $id)
{
$product = new product($id);
echo '
<
div name=
"singleproduct"
><
a href="details.php?productid='.$product-
>
id.
'">'
.
$product
-
>
name.'
<
/a
><
br
>
Cena netto:
'.$product->price.'
(
+
'. $product->tax.'
)
z³
<
br
>
Opis:
'.substr($product->description, 0, 150).'
<
a href="details.php?productid='.$product-
>
id.'"
>[
...
]
dalej
<
/a
><
/div
>
';
}
echo '
<
/div
>
';
}
}
sqlite_close($db);
}
else
{
die('
Wyst¹pi³ b³¹d: '.
$error
)
;
}
?>
24
11/2008
Plik z chomika:
Kapy97
Inne pliki z tego folderu:
2010.03_SOA Tworzenie serwisów wspomagających proces integracji_[Aplikacje Biznesowe].pdf
(1004 KB)
2010.05_Wdrożenia SAP – droga przez mękę_[Aplikacje Biznesowe].pdf
(1197 KB)
2010.06_Stary, dobry znajomy Oracle Forms_[Aplikacje Biznesowe].pdf
(548 KB)
2010.05_C++ Qt 4.5 _[Aplikacje Biznesowe].pdf
(1019 KB)
2009.09_Websphere MQ 7 _[Aplikacje Biznesowe].pdf
(581 KB)
Inne foldery tego chomika:
Algorytmy
Antyhaking
Aspekty
Bazy Danych
Biblioteka Miesiaca
Zgłoś jeśli
naruszono regulamin