Tải bản đầy đủ (.pdf) (133 trang)

Kỹ thuật và thủ thuật lập trình hướng đối tượng PHP tập 2 phần 2 nguyễn minh, lương phúc

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (2.35 MB, 133 trang )

155

C h ư ơ n g 10: x ử lý các lỗi

PH ẨN 3
fln ninh và xử lộ
sư cô'

Chiùyitg 10: x ử ỉý cá c lỗi
Cbươĩtg II: Bào vệ an toàn PHP
Chươĩtg 12: M ở rộng PHP


156

C h ư ơ n g 10: x ử iý các lỗỉ

Xứ lụ các iôi

Nhữtig kỹ năng và k h á i niệm chinh
u

T ìm h i ể i i c á c c ắ p l ỗ i c ủ a P H P

ẵ ! D i ề ĩ i k ũ iỂ n c á c t ô i n a o đ iíỢ c h i ể n i h ị t r u n g s c n p t P H Ỉ ’

*

B ỏ q u a p h iíơ n g th ứ c x ử lý lỗ i m ặ c đ ịn h c ủ a P H P v à c h u y ể n h ư ở n g
c á c lỗ i s a n g m ộ t h à m tù y ỷ


M T ìn t h i ổ ỉ t c á c h t ạ o v à X ĩ} l ý c á c n ^ o ạ i l ệ
K

T ự đ ộ n g g h i n b ậ l k ý ( lo g ) c á c lỗ i s a n g m ộ l f i l e h o ặ c đ ỉ a c h ỉ e - n i a i l

^

T ạ o m ộ t b a c k ir a c e đ ể g ỡ rố i c á c lồ i s c rip t

M

ột k h ái niệm sai lầm thường th ấ y đặc b iệ t tro n g số những
ngưdi đã p h á t triể n ít có k in h nghiệm hơn là m ột chương
trìn h "tốt” là m ột chương trìn h làm việc k h ô n g có lỗi. Thực
tế, điều n ày không h o àn toàn đúng: Một đ ịn h nghĩa rõ hơn có th ể là
chương trìn h dự đoán trước tâ't cả điều kiện lôi có th ể có và g iải quyết chúng
m ột cách n h ấ t quán và chính xác.
Viết các chương trìn h "thông minh" tu â n theo đ ịnh n g h ĩa n ày là m ột đòi
hỏi nghệ th u ậ t cũng như kỹ năng. K inh nghiệm và tr í tưởng tượng đóng
m ột vai trò quan trọng cho việc đ án h giá những nguyên n h â n gây lỗi tiềm


C h ư d n g 10: x ử lý các lỗi____________________________________________________ 15 7

án và dịnh n g h ĩa h à n h động hiệu chỉnh nhưng không k ém p h ần quan trọng
hơn là bản th â n ngôn ngữ lập trìn h dịnh nghĩa những công cụ v à chức nàng
có sẵ n để bẫy và giải quyết các lỗi.
T h ậ t m ay th ay , P H P giỏi về lĩnh vực này; ngôn ngữ n ày có m ột framew ork tín h vi để giúp các n h à p h á t triển đón b ắt các lỗi và có h à n h động sửa
chữa. Chương n ày sẽ giới thiệu bạn về framework này, trìn h bày cho b ạn về
mô h ìn h ngoại lệ P H P 5.3 và hướng dẫn bạn cách tạo các thường trìn h xử

lý lỗi được tùy b iến theo những nhu cầu của ứng dụng PHP.

Xử lý các lỗi S cript
N hư bạn đã làm việc qua những đự án trong sách này, chắc chắn b ạn sẽ
gặp m ột vài sự cố; M ột dấu ngoặc được đ ặt sai chỗ ở đây, thiếu m ột dấu
chấm phẩy ở đó; có lẽ m ột h àm được gọi ra nhầm ở nơi k hác nào đó. Và bạn
sẽ. chú ý ră n g P H P thực sự r ấ t giỏi về việc chỉ ra rõ nhữ ng lỗi này. Trong
trường hợp P H P tạo m ột th ô n g báo lỗi nhưng tiếp tục thực th i script; trong
nhữ ng trường hợp khác nghiêm trọng hơn, nó tạm dừng việc thực th i script
bằn g m ột th ô n g báo chỉ định số dòng đã gây ra lỗi.
Loại lỗi vừa được mô tả là các lỗi cấp "script"; chúng xảy ra k h i bộ máy
PH P gặp p h ải nhữ ng khiếm khuyết trong cú pháp hoặc cấu trúc của một
PH P. Chúng chỉ thường n h ậ n th ấy được một khi P H P thực sự b á t đầu p h ân
tích và thực th i m ộ t script. Để m inh họa, hăy thử tạo v à chạy scrip t sau
dây:

/ / try divỉding by 2ero
echo 45/0;
// try calling an undetined tunction
echo someFunc();

?>
Đầu ra của sc rip t này trông giông như h ình 10.1.
N hư h ìn h 10.1 m in h họa, script này đã tạo h ai loại lỗi: m ột "cảnh báo"
(w arning) về nỗ lực chia cho zero, và "lỗi nghiêm trọng" (fata error) về nỗ
iực gọi r a m ột h àm k hông xác định. Thực tế các lỗi P H P có th ể được p h ân
loại rộng th à n h b a h ạ n g mục chính như được liệt kê tro n g b ản g 10.1.
Có m ột sự p h â n cấp rõ ràn g cho các thông báo lỗi của PH P: các thông
báo (notice) ít ng h iêm trọ n g hơn các cảnh báo (vvarning) m à lầ n lượt ít

nghiêm trọ n g hơn các lỗi nghiêm trọng (fatal error). Theo m ặc định PHP


158

C h ư ơ n g 10: x ử lý các lỗi

chỉ hiển th ị các cảnh báo và lỗi nghiêm trọ n g tro n g đầu r a scrip t (mặc dù
như bạn sẽ th ấ y ngay sau đó, bạn có th ể th ay đổi h à n h vi m ặc định n ày sao
cho th ậ m chí các th ô n g báo chỉ n h ìn th ấy được trong đầu r a script). Các Ỉ5i
có th ể xảy ra tạ i các giai đoạn khác nhau tro n g vòng đời của m ột sc rip t - lúc
khởi động, vào thời gian p h ân tích, vào thời gian biên dịch hoặc vào thời
gian chạy - và do dó P H P cũng đưa ra những k hác b iệt nội tạ i về những giai
đoạn khác n h au này. Nói chung, tổng cộng là 12 cấp lỗi kháo n h au (cộng với
h ai cấp "đặc biệt") được tượng trưng b ằn g các h ằn g có tên . M ột d an h sách
hoàn chỉnh các cáp lỗi n ày có th ể tìm th ấ y tạ i w w w .php.neưm anuai/eĩi/'
ref.errorfunc,php#errorfunc.constants. B ảng 10.2 liệ t kê các cấp lỗi m à bạn
sô thường sử dụng n h ất.
H ầu h ế t nhừng câp lỗi n ày dễ hiểu. Các cấp lỗi m à có lẽ b a n gặp trụ c trặc
là các cấp lỗi E_ƯSER được đ ặ t sang m ột bên d àn h cho các lỗi cấp ứng dụng
t'jy ỹ Đừng bận tâ m về những cá'p lỗi này vì p h ần iđn chúnịỊ có dược thay
th ế bdi mô hình ngoại lộ mới được giới thiệu tro n g P H P 5

Waỉtúng Divuionh y u r c inC:^ogram ỉĩl«sUnr0n 8t

ĩooấi\Apầche^Ju4o«^h^boak'«cblO*iútíAsi\(««-empr».phponlne 3
m »r 'tỉ .0 uiỉ'JeL/iedfinc&cnSởn<ỉ?u.icOmc
Tod<\ApaeK6lhi4ors\pỉip6-bMk\rhiO\lìitiii^<\iftè*errorf.php hne6



Hình 10.1 Một ví dụ về một trang lỗi PHP
Bảng 10.1 Các hạng mục lỗ i PHP

L o ạ i lỗ i

M ô tả

Ví dụ

Các thông báo (notice)

Các lỗi không quan
tr ọ n g k h ô n g n g á n
P H P th ự c th i m ộ t
script

Truy cập một biến dã
không được khởi tạo

Các cảnh báo (warning)

Các lỗi nghiêm trọng
hơn đòi h ỏ i chú ý
nhimg vẫn không dừng
việc thực th i sc rip t
(mặc dù một số phần
của script có thể hoạt
động không chính xác)

Đọc m ộ t file k hông

hiện hữu trong đường
dẫn được nêu rõ.


159

C h ư ơ n g 10: x ủ lý c á c lỗi

Các lỗi nghiêm trọng
(fatal error)

Các lỗi cú pháp hoặc
các lỗi quan trọ n g
buộc PHP dừng thực
thi một script

Thể hiện cụ th ể một
đô’i tư ợ n g cùa m ột
class không xác định

C ấ p lỗ i

M ô tả

E_PA R SE

Các lỗi phân tích (parse) nghiêm trọng

E .N O T I C E


Các lỗi thời gian chạy (thông báo) không
nghiêm trọng

E _ W A R N IN G

Các lỗi thời gian chạy (cảnh báo) không quan
trọng

E .E R R O R

Các lỗi thời gian chạy nghiêm trọng buộc
kết thúc script

E _ U S E R _ N O T IC E

Các lỗi ứng dụng (thông báo) không nghiêm
trọng do người dùng ấn định

E_ƯSER_WARNING

Các lỗi ứng dụng (cảnh báo) không nghiêm
trọng do người dùng ấn định

E_U SER _ER R O R

Các lỗi ứng dụng nghiêm trọng do người dùng
ấn dịnh

E _ S T R IC T


Các lỗi thời gian chạy không nghiêm trọng
nảy sinh từ cú pháp PHP thừa kêVkhông được
tán thành

E_A LL

Tất cả lỗi
Bảng 10.2 Các cấp lỗi PHP

Điều khiển việ c báo cáo lỗi
B ạn có th ể điều k h iển các lỗi nào dược hiển thị tro n g đầu ra scrip t bằng
m ột hàm P H P cài sẵ n dược gọi là errQr^reportingO, H àm này chấp n h ận
m ột hoặc nhiều h ằ n g được đ ạ t tên từ báng 10.2 và yêu cầu scrip t báo cáo
các iỗi khớp với các lỗi đó. Tuy nhiên, có m ột ngoại lệ: việc chuyển các lỗi
CE_PARSE) nảy sin h từ những khiếm khuyết cú pháp tro n g m ột script PH P
không th ể được ẩ n sử dụng hàm error_reporting(),
Để th ấ y trực tiế p điều này, xem xét b ản viết lại sau đây của m ột trong
các script trước đó để "làm ẩn" các lỗi không nghiêm trọ n g
// only đisplay fatal errors
error_reporting {E_ERROR);


1 6 0 _______________________________________________________ C h ư ớ n g 10: x ử lý cá c lỗi
echo 45/Q;

?>
T rong trường hợp này, khi script thực th i, cảnh báo sẽ không dược tạo ra
mặc dù những sc rip t thực h iện phép chia cho zero.
Hỏi chuyên gia

H ỏ i: C ấ p lỗi £ _ S T R IC T làm đ iẻ u gi?

Đáp: Tại cấp lỗi E _ S T R I C T , PHP kiểm tra mã vào thời gian chạy và tự
động lạo các đề xuất vể cách nó có tnể đưọc cải tiến nhu thế nào. sử
d ụ n g E . S T R I C T I h ư ờ n a c ó th ể tnộ t b á o đ ộ i ì g v ổ rihữniạ h à in m à s ẽ bi
h ỏ n g trcng tnôt phièn bản tương lai c ủ a

PHP

v à v iệ c sử d ụ n g PÓ dưỢc

đ ề n g h ị đ ể c ả i t h iệ n k h ả n ă n g b ả o trl m ã t ro n g th ờ i h ạ n d ài.

Ban cũng có th ể sử dụn^ v»rror reportiiigO để tắ t việx? háo
nghiêm trọ n g vào th ờ i gian chạy n h ư trong ví dụ sau đâ>:

ỉỗi

// only dispỉay vvarnings
error_reportíng (E_WARNING);
echo someFunc():

?>
Điều quan trọ n g là p h ải n h ậ n ra rằ n g error_reporting() không tự động
làm cho scrip t k hông có lỗi; tấ t cả những ^ m à nó làm là che giấu các lỗi có
m ột loại n h ấ t đ ịnh. M ặc dù script trước sẽ khòng h iển th ị m ột th ô n g báo lỗi
n h ìn th ấ y được, n h ư n g nó sẽ vẫn tạo ra m ột lỗi nghiêm trọ n g và việc thực
th i scrip t sẽ v ẫn dừng tạ i điểm lỗi.
B ạn cũng cố th ể chuyển đến error_reporting() m ột tổ hợp các cấp lỗi để

tùy biến hệ th ô n g báo cáo lỗi của P H P th ậ m chí xa hơn. Ví dụ, xem xét
script sau đây, sc rip t n ày chỉ báo cáo các th ô n g báo và lỗi nghiêm trọng
nhưng không p h ả i là các cảnh báo:
// only dỉspỉay notices and fatal errors
error_reportỉng{E_NOTICE I E_ERROR);
echo $var; // notice
echo 45/0; / / vvarning


C hư dn g 10; x ử

lý các lỗi_________________________ ___________________ 161

echo someFunc(); / / íatal

?>
Cũng có th ể t ắ t chức n ăn g báo cáo lỗi một cách có chọn lọc, trê n cơ sở
mỗi hàm bằng việc b ắ t đầu lệ n h gọi hàm bằng to án tử
Ví dụ, đoạn m ã
sau đây thường tạo ra m ột lỗi nghiêm trọng bởi vì som eFunction() không
h iện hữu;
// call a non-existent tunction
someFunction();

?>
Tuy nhiên, lỗi này có th ể được bỏ qua bằng việc đ ặ t m ột ký hiệu @ trước
lện h gọi hàm n h ư sau:

/ / call a non-existant íunction
@someFunctỉon();

?>
Sử dụng m ột phương thức xử lý lỗi tùy ỷ
Theo mặc định, k h i m ột lỗi scrip t được kích khởi, phương thức xử lý lỗi
(error handler) cài sẵn của P H P n h ận dạng loại lỗi, h iể n th ị m ột th ô n g báo
lỗi th ích hợp (dựa vào xác lập error_repotingO) và tùy ý tạ m dừng việc thực
th i scrip t (nếu lỗi nghiêm trọng). Thông báo được tạo r a bdi phương thức xử
lý lỗi sử dụng m ột khuôn mẫu (tem plate) chuẩn: nó chỉ d ịn h loại lỗi, lý do
cho loại lỗi, và tê n file và số dòng nơi lồi đã được tạo (xem h ìn h 10.1 để
th â y m ột ví dụ).
Tuy nhiên, khi các ứng dụng P H P ngày càng trở n ê n phức tạ p hơn, cơ
câu xử lý lỗi mặc đ ịnh n ày rố t cuộc thường khong th ỏ a đáng. Ví dụ có th ể
b ạn muôn tùy biến tem p late được sử dụng bởi phương thức xử lý lôi dể hiển
th ị n h iều hoặc ít th ông tin hcfn hoặc có th ể b ạn muốn ghi n h ậ t ký lỗi sang
m ột íĩle hoặc cơ sở dữ liệu th a y vì hiển th ị nó cho người dùng. Đối với tấ t cả
tình huông này, P H P đưa r a h àm set_error_handler(), h à m n ày cho phép
b ạn th a y th ế phương thức xử lý lỗi cài sẵn của P H P b ằn g phương thức xử lý
lỗi riê n g của bạn.


1 6 2 ________________________________________ ____________ C h ư ớ n g 10: x ử lý các lỗi

H àm set_error_handler() chấp n h ậ n m ột đối số: tê n của h àm do người
dùng định n g h ĩa m à sẽ được gọi ra khi m ộ t lỗi xảy ra. H àm tùy ý n ày phải
có k h ả nỗLng chấp n h ậ n tối th iểu h ai đối sô' b ấ t buộc (loại lỗi và th ô n g báo
mô tả tương ứng) và lên đến th ê m ba dối sô' (tên file, sô' dòng nơi lỗi đã xảy
ra, và m ột sự k ế t xuất không gian biến vào th ờ i gian lỗi).
--------------------------------------------------------------------------------------


M ộ t p h ư ơ n g thứ c x ử lý lỗ i tù y ý k h ô n g th ế c h ặ n c ấ c ỉỗ i n g h iê m
trọ n g (E _ E R R O R ), c á c lỗ i p h â n tíc h (E _ P A R S E ), h o ặ c c á c th ô n g
b á o m ã th ừ a k ế (E _ S T R IC T ).

Đê’ m in h h ọ a diều này, hãy xem x é t ví dụ sau đây:
ở dây m ột hàm xử lý lôi do người dùng định n g h ĩa th a y th ế phương thức
xử 1>' (handler) cài sẵii uủa PK P, tạo động m ột tra n g lỗi tùy ý.
<!D0CTVPE html PUBLIC "-.//W3C//DTD XHTiVIL 1,0 Transitional//EN'"D TD /xhtm l1-transitional.đtđ">
<htm l xm lns="http://w w w .w 3.org/1999/xhtm !” xm l:lang=” en’' lang=” en”>
<head>
< title x /tiíle >
<slyle type="text/css">
.notice {
font-weight: bolder;
color: purple;

)
,warning {
font*weight; bolđer;
font-size: iarger;
color: red;
I

</style>
</head>

<body>
// đivert errors to custom error handler



C h U ớ n g 1 0 : x ử lý c á c lỗi_____________________ __________________________________ 1 6 3
set_error_handler{‘m yHandler’);
// report ail errors
error_reporting{E_A LL);
// generate some errors
echo $var;

// notice

echo 23/0;

// warning

// custom error handler
íunction m yHandler($type, $m sg, $file, $íine, Scontext) I
$text = “An error occurred on line $line while Processing your
request,


Please visií our <a href=>home page</a>
and try again,";
sw itch{$type) I
case E.NOTICE:
echo “<div class=\” notice\” >$text</điv>

";
break;
case E_WARNING;
echo “ <div class=V'wamingV'>$text</div>

” :
break;

)


1

?>
</body>
< /íitm l>

ở đây h à m set_error_handler() tự động chuyển hướng tấ t cả lỗi sang
h à m do người dùng định n g h ĩa myHandlerO- Khi m ột lôi xảy ra, hàm này
được chuyển loại lỏi, th ô n g báo lỗi, file và số dòng nơi lỗi đâ xảy ra cùng với
ngữ cảnh k h ả biến. Sau đó nó hiển th ị m ột tran g lỗi tùy ý chứa số dòng của
lỗi b ằn g m àu tía (các th ô n g báo) hoặc m àu đỏ (các cản h báo), và tạm đừng
b ằn g ta y việc thực th i script. H ình 10.2 m inh họa k ế t quả.


16 4

C h ư ơ n g 10: x ử lý các lồi

An emr oceurred on Iỉne27«4ùỉe proce^síngyỡor request
H e ầ ỉ e Y Ìs it o u r b o m ê p ạ g ẹ and X ry h g 9 Ìn .
A n m o r o c m iT c d
P ì e ,i S € v ĩ ỉ U

0U

lin í 2 S

p r o c ^ s ỉn g y o ìư re q u rs t.

>IU h o n i c p ạ g ẹ a i ì J U y


rm
Kình 10.2 Một trang lỗi được tạo ra bồi mộỉ phưđng thức xử lý lỗi tùy ý

Hỏi chuyên gia
H ỏ i: Làrn tn ế n â o tò i p h ụ c hồi c ơ cãu x ử lý lối m ặ c đ ịn h c ủ a P H P rr.ộ t khi
tõi đ à gọi s e t_ e rro r_ h a n d !e r() ?
Đ á p : C ó hai c á ch đ ể làm đ ié u n à y. P h ư ơng p h á p đơn g iả n n h á t là sử d ụ n g
hàm re s to re _ e rro r_ h a n d ie r() c u a PH P. H àm n à y p h ụ c h ồ i p h ư ơ n g th ứ c
x ử lý lỏi sau c ù n g đ a n g s ử d ụ n g trư ớc khi s e t_ e rro r_ h a n d le r() đ ư ợ c gọi,
T ro n g hẩu h ế t c á c trư ờn g h ợ p , đ â y s ẽ là p h ư ơ n g th ứ c x ử lý lỗi m ặ c định
của PHP.

Một tùy chọn k h ác là yêu cầu phương thức xử lý lỗi tùy ý tr ả về false;
điều này sè buộc lỗi được chuyển trở lại phương thức xử lý m ặc đ ịn h của
PH P để xử lý m ột cách bình thường. Kỹ th u ậ t n ày th ì tiệ n lợi nếu bạii cần
chuyển các lôi qua m ộ t h àm tùy ý trước tiê n để xử lý trước hoặc ghi n h ậ t k';
và sẽ th a y th ế m ột ví dụ trong p h ần "ghi n h ậ t ký" m ột lỗi,
Thực hành 10.1: Tạo m ột tran g lỗi sạch
Phương thức xử lý lỗi mặc định của P H P chỉ h iển th ị th ô n g tin về m ột
lỗi. Thông báo lỗi n ày thường xuất h iện tro n g khi m ột tr a n g đầu ra đang
được tạo, p h á vỡ việc sắp đ ặ t (layout) tra n g và gây r a sự n h ầm lẫ n và sự
căng th ẳ n g người dùng không cần th iế t (xem h ìn h 10.3 để th ấ y m ột ví dụ
về m ột tra n g như vậy). Tuy n h iên , bằng việc th a y th ế phương thức xử lý lỗi
m ặc định b ằn g m ột h à m tùy ý, b ạ n có th ể dễ d àn g g iải quyết v ấn đề này
bằng việc tạo m ột tra n g lỗi "sạch" khác trong k h i đồng th ờ i ghi n h ậ t ký các
lồi scrip t sang m ột cơ sở dữ liệu để xem lại sau đó. Ví dụ tiế p theo theo sau
đây sè hướng d ẫn b ạn cách làm điều này.



165

C h ư ơ n g 10: x ử lý các lỗi

Đ ể b ắ t đầu, tạo m ột cơ sở dữ liệu SQLite mới, và m ột b ản g để chứa thông
tin lỗi như được m in h họa ở đây:
shell> s q lite app.db
sqíite> CREATE TABLE errors (
„ > id INTEGER PRIMARY KEY,
..> date TEXT NOT NULL,
„ > e rro r TEXT NOT NULL,
..> s c rip t TEXT NOT NULL,
..> lin e TEXT NOT NULL
...>

):

T iếp theo đ ịn h nghĩa m ột phương thức xử lý lỗi tùy ý chặn tấ t cả lỗi
scrip t và ghi chúng sang bảng này sử đụng PDO n h ư tro n g scrip t sau dây
(app.php):
// report ali errors
error_reporting(E_ALL);
O Proỉe(t 10- ỉ: Generãting a CustomCrrorl^dge - MoỉiHd FlrefoK
ẹte

w

;H8tọfY


Ioofe

:

Hello and welcoiiie to thỉs page.
W an ù n g includiectỡcyư) C :\Prosraỉn FiJe$\ỉntemet
Tooỉs\A pdche\htdoc$^hp 6 -bcak\chl 0\proiect01\àpp.php O ĩiiĩii 60
op^ĩmig ’ni' 5 suìg 61e p h p ' fo r ứỉcluMộn
(mciudtf_pattỉ=*.;c.\ProgramFile\IntemetToộlí\PHP^eâr’) ìn Cĩ^l^-ogram F iies\lnl^m et
Tooli\Apache\htđĐC 5^hpỐ-boQk\cỉilO\prạịectŨlVapp.php on hnt 60
Ooođbyc.
W a n d n g ư ith iđ p ũ ÍB-mcticm m d u d e l Pôilcd

ŨOO0
Kình 10.3 Dầu ra lỗi xen lẫn với nội dung trang
// dse custom handler
set_error_handỉer(‘myHandler');
// create an output butter


166

C h ư ơ n g 1 0 : X ử lý c á c lỗi

ob_start();
// detine a cusíom handler
// vvhich logs errors to the database
/ / then generates an error page
íunction m yHanđler($type, $msg, $file, $line. $context) {

// log error to database
$db ^ 'app.db';
$ p d o = ,new PDO(‘‘sqlite:$db”);
Smsg

$pơo-->qtjoỉ9($msg);

$file = $pdo->quote($fi!e)i
$line = $pdo->qưote($line);

$date = $pcio->quote(date('cl-M-Y h;i;s’, mKtimeO)):
$sql = “ INSERTINTO errors {đate, error, script, line) VALUES {Sđate. $msg
$file, $line)";
$pđo->exec{$sql);

// reset and close the output buffer
n generate a new error page
ob_end_clean{);
$errorPage = ‘
“ DTD/xhtm l1-transitionai,dtci">
<htm l xmlns="lìtlp://www,w3.org/19S9/xh1.m í'’ !(ml:ỉan9 = 'e n ’’ ìang=^” eiV’>
<head>
<titỉe>Error Page</titỉe>
</head>
<body>
/ / outpưt some page text

echo “ Goũdbye.";
// dump output bưffer
o b _en d Jlush ();

?>
</body>
< /htm l>

N goài nhữ ng th à n h p h ần m à b ạn dã quen thuộc (PDO và các phương
thức xử lý lỗi tùy ý), sc rip t này cũng giới thiệu m ột sin h v ậ t mới; các hàm
điều k h iể n đầu r a của PH P. Như vứi tê n gọi, những h à m n à y cung cấp m ột
cách cho các n h à p h á t triể n tác động m ột mức độ điều k h iể n cao lên trê n
đầu ra được tạo r a bởi m ột script PHP.


168

C h ư ơ n g 10: x ử lý các lỗi

Các h à m điều k h iể n đầu ra của P H P làm việc bằng cách chuyển hướng
tấ t cả đầu ra dược tạo bdi m ột scrip t sang m ột bộ đệm đầu ra (output buíTer)
đ ặc b iệ t tr o n g bộ n h ớ th a y vì gởi n ó trực tiế p s a n g t r ì n h d u y ệ t Client. Nội
dung của bộ đệm này vẫn n ằm trong bộ n h ớ cho dến khi chúng được làm
cho n h ìn th ấ y được đối với người dùng một cách tường m inh. H oặc chúng có
th ể bị xóa đơn giản b ằn g việc xác lập lại bộ đệm.
Có ba h à m chính để học về API điều khiểr, đầi: ra của PH P:
K Hàm ob_start() khởi lạo một bộ đệm đầu ra va chuẩn t)ị nó đ ê chặn
idệc X ìiấ t một script. Không cản phải nói bàm này nên đĩcạc gọi intôc
hhi hất kỳ iíii/ ra được tạo bồi scripi.
m Hàm ob_cndJĩushO kết thúc việc đệm đầu ra (onípul biiffcring) và gởi

nội đung hiện hành cứa bộ đệìu đầu ra sang thiết bị đẩu ra Ohường là
trình duyệt của ngKòi dùng).


ỉỉà m o b _ c n d .íic a u C kổĩ ihúc viộc đ ệm đâu ra , ’à làm scỊCi' n ộ i dìDĩiĩ

hiộn hãnh của bộ đệm đầíi ra.
Sau k h i ghi nhớ lý th u y ết này, hăy quay trở lại scrip t trước để th ấ y các
bộ đệm đầu ra có th ể giúp tạo các tran g lỗi sạch hơn như th ế nào. N hìn
th o án g qua scrip t n ày và bạn sẽ th ấy rằn g nó b ắ t đầu b àn g việc khởi tạo
m ột bộ đệm đầu ra mới b ằn g ob_start() và m ột phương thức xử iý lỗi tùy ý
với set_error_handler(). B ất kỳ đầu ra được tạo ra bởi scrip t bây giờ sẽ được
lưu trừ tro n g bộ đệm đầu ra cho đến khi nó được giải phóng san g Client
b ằn g cách gọi đ ến ob_end_flush().
B ây giờ h ãy xem x ét những gì xảy ra k h i m ột lỗi x u ất h iệ n tro n g script.
Đ ầu tiê n phương thức xử lý lỗi tùy ý sẽ chặn lỗi nàv, m ở m ột h an d le PDO
d ẫn đến íile cơ sở dữ liệu SQLite được tạo ở bước trước và chuyển đổi lỗi
(thông báo hoặc cảnh báo) th à n h m ột query SQL INSERT. Sau đó query
này sẽ được sử dụng để lưu lỗi sang cơ sở dữ liệu b ằn g phương thức execO
của PDO cùng với ngày th á n g và thời gian chính xác, Sau đó việc gởi đến
ob_end_clean{) sẽ xóa sạch bộ đệm dầu ra, gởi m ột tra n g lỗi tùy ý đ ến trìn h
duyệt và k ế t thúc việc thực th i script.
K ết quả của những h à n h động này là th ậ m chí nếu dã có m ột tra n g Web
đang được tạo n h a n h k h i lỗi xảy ra, nó sẽ k hông bao giờ th ấ y á n h sán g ban
ngày vì nó sẽ bị loại bỏ và được th a y th ế bằng tra n g lỗi tùy ý. M ặt k hác nếu
scrip t thực th i không có b ấ t kỳ lỗi nào, việc gọi sau cùng đến ob_end_flush()
sẽ giải quyết việc gởi tra n g đầy đủ và sau cùng đến trìn h duyệt.


C h ư ơ n g 10: X ử iý các lỗi


169

^ ^E rto rP d Q e • NoỉH là FÌreÍ6M

St
ij htlp://Vxd(hc»ỉ/^Tỗ*boc^ch)0/pr9)ect01/4pp.php

Oops!
T Id ỉ $crip: e n c o u n te rc 4 àn inU m ã! tTTữĩ and
w a s u nâble t o ex e c u ỉe T he ecTor ha$ b t m
lo g g c d a n d wỉU b e re c b £ c d a s ỉỗ o n â s

possible

U aỉiỉ tbcDỉ p ỉe a s e r e tu m to th e h o m e p ỉg e ao d
se ỉe c t anoCher acbvicy.

i»«*.

- í - '

'■

Hình 10.4 Một trang lỗi sạch

Và bây giờ, k h i b ạ n chạy script, thay vì đầu ra bị hỏng được m in h họa
trước đó tro n g h ìn h 10.3, b ạn th ấ y m ột tra n g lỗi sạch hơn nhiều, H ìn h 10.4
m inh họa nhữ ng gì có lẽ b ạn sẽ thấy.
T rong k h i b ạ n xem nó, cũng h ãy n h ìn vào báng SQLite. B ạn có th ể th ấy

các th ô n g báo được đưa ra bởi scrip t như được m inh họa ở đây:
1l13-Feb-2008 06:25;30IUndefíned variable: m yVar!/ch10/project01/
app.phpl28
2l13-Feb-2008 06:25:301include(missingfíle.php): íaiied to open
stream; No suctí file or đirectoryl /ch10/projecf01/app.phpl31
3l13-Feb-2008 06:25:30iinclude(): Failed opening 'm issingíile.php' for
inclusion (include_path='. ')l/ch10/project01/app.phpl31

M ột th iế t lặp n h ư vậy làưi cho m ột Iihà quản trị n h à p h á t triể n dỗ duy
trì m ột record thư ờng trực của các lỗi script và quay trở về record n ày b ất
cứ lúc nào để xem hoặc kiểm tr a các lỗi trong khi cũng bảo đảm rằ n g sự trả i
nghiệm người dùng là n h ấ t quán và không phức tạp.


C h ư ó n g 10: x ử lý các lỗi

170

Hỏi chuyên gia

Hỏi: Điều gi xảy ra nếu bản thân hàm xử lý lỗi tùy ý chứa một lỗi?
Đ áp: Nếu bản th â n p h ư ơ ng thúc xử lý lỗi tùy ý chứa một lỗi, lỗi sẽ được
chuyển hướng lên cơ cấu xử iý lỗi mặc định của PHP. Do đó. ví dụ nếu
m ã b ê n t r o n g m ộ t p h ư ơ n g t h ứ c lỏi t ù y ý tạ o r a m ộ t c ả n h b á o , c ả n h b á o

này sẽ được báo cáo theo cãp báo cáo lỗi hiện hành của PHP và được
x ỉ í lý b ở i p h u ơ n g th ứ c x ử lý lỗi m ặ c đ ịn h c ủ a P H P .

Sử dụng các ngoại iệ
N goài các ỉõi, P H P 5 cũng giới thiệu m ột mò h ìn h ngoại lộ mới [ương tự

như mô h ìn h được sử dụng bởi những ngôn ngữ lậo trìn h k h ác n h ư Ja v a và
P ython, T rong phương p h áp dựa vào ngoại lệ này, m ã chương trìn h được
hao
tvong rAỘt. lchối
và cốc ngoí^i lệ >1ươc tạo ''a bỏ'i '10 được "đón bổt"
và được giổi quyết ‘udi n iộ t hoặc n h iềa khô'i catch. Bởi vì nhiều khô'i cAtch cõ
th ể thực h iệ n được, các Iihà p h á t triề n có th ế bẩy (trap ) các loại ngoại lô
khác n hau và xử lý mỗi loại ngoại lệ m ột cách khác nhau.
Để m in h h ọ a điều này, hãy xem xét listin g sau đây, listin g n ày ccT tạo
m ột p h ầ n tử m ản g không tồn tạ i sử đụng m ột A rray lterato r:
<’ php
/ / detine array
$cities » ãrray(
"United Kingdom ” => “ London",
"United States" => “W ashington” ,
“ Prance" => '‘Paris",
"In d ia ” => “ Delhi”

):
// try accessing a non-existent array element
// generates an OutOíBoundsException
//

oLrtpưt; 'Exception: Seek posỉtion 10 is out of range’

try {
$iterator = new Arraylterator($cities);
$iterator->seek(10);
} catch (Exception $e) {



Xử lý các lòi_____________________________________________________ 1 7 1

C h ự ớ n g 10:

echo ‘ ERROR: An exception occurred in your script.';

)
?>
K hi P H P gập p h ải lỗi được bao bọc bên trong m ột khôi try-catch, đầu
tiên nó cô’ thực th i m ã bên trong khối try. Nếu m ã này được xử lý m à không
có bâ’t kỳ ngoại lệ được tạo ra, quyền diều khiển được chuyển san g các dòng
sau khcTi try-catch. Tuy nhiên, nếư m ột ngoại lệ được tạo ra tro n g k h i chạy
m ã bên tro n g khô'i try (như xuất h iện trong listing trước), P H P dừng thực
th i khối tạ i điểm đó và b ắ t đầu kiểm tr a mỗi khôi catch để xem có m ột
phương thức xử lý trong ngoại lệ hay không. Nếu m ột phương thức xử lý
được tìm th ấy , m ã bên trong khối catch thích hợp được thực th i và sau đó
các đòng sau khối try được thực thi. Nếu không, m ột lồi ngh iêm trọ n g sẽ
được tạo ra và việc thực th i script dừng tại điểm lỗi.
Mọi đối tượng Exception đều chứa thêm một sô’ th ô n g tin m à có th ể được
sử dụng cho việc gỡ rối nguồn của ỉỗi. Thông tin này có th ể được tru y cập
thông qua các phương thức cài sẵn của đối tượng E xception và chứa m ột
thông báo lỗi mô tả, m ột m ã lỗi, tê n file và số dòng gây r a lỗi và m ột
backtrace của các lần gọi ra hàm d ẫn đến lỗi. B ảng 10.3 liệ t kê những
phương thức này.
Và bản ch ĩn h sửa sau đây của listing trước m inh họa nhữ ng phương thức
này đ ang sử dụng:
/ / detine array
$cỉties = array{

“ United Kingdom" => “ London",
"United States" => “Washington",
■'Prance" => "Paris",
“ India” => "Oeihi”

);
// try accessing a non-existent array element
/ / generates an OutOíBoundsException

íry l
Siterator = new Arraylterator($cities);
$ìterator->seek(10);


172

Chướng 10: x ử lý các lỗi
} catch (Exception $e) {
echo “ ERROR: Something w ení w rong!\n” ;
echo "Error message: “ . $e->getMessage() . '‘\n ” ;
echo “ Error code: “ . $e->getCode() . "\n” ;
echo “ File name: “ . $e->getFile() , "\n";
echo “ Line: “ . $e->getLine() . "\n” ;
echo 'Backtrace: " . $e->getTraceAsString() .

1

?>
Bảng 10.3 Các phương thức cùa dãi tượng ngoại lệ PKP


T ên p h ư ơ n g th ứ c

C hứ c n ă n g

gt'tHessag'ỉ(;

Trả về laột ihón^ báo mô tả trực trặo
xảy ra

getCodeO

Trâ về một mă lỗi dạng sô’

getFile()

Trả về đường dẫn đĩa và tê n củascript
tạo ra ngoại lệ

getLineO

Trả về số dòng đã tạo ra ngoại lệ

getTraceO

Trả về một backtrace của các lệnh gọi dã
dẫn đến lổi dưới dạng một mảng

getTraceAsStringO

Trả về một backtrace của các lệnh gọi đã

dẫn đến lỗi dưới dạng một chuỗi

gì dá

đà

• • • • • • •

Thủ thuật
c ỏ t h ể x ứ lý c á c loại ngoại lệ k h á c nhau m ộ t cá c h k h á c n h a u b ằ n g v iệ c tạo
nhiều khốỉ catrh và gán các hành độníỊ khác nhau vào mỗi khối này. Bạn sẽ
thấy một ví dụ về điều nàỵ thêm nữa trong chương.
Bây giờ nếu b ạn nghĩ về nó, có th ể b ạn muôn k ế t luận rà n g các ngoại lệ
chỉ là rượu cũ tro n g m ột b ìn h mới. Rốt cuộc những k h ả n ăn g đă được mô tả
dường như hoàn toàn dễ dàng sao chép sử dụng m ột phương thức xử lý lỗi
tùy ý như được mô tả tro n g p h ần trước. Dù vậy, thực t ế phương pháp dựa
vào ngoại lệ n ày tin h vi hơn nhiều so với vẻ bề ngoài bởi vì nó m ang lại
thêm những lợi ích sau đây:
# Trong mô hình trỉiyền thống, cần kiểm tra giá trị trả vẻ của mọi hám
được gọi đ ể nhận dạng xem một lỗi đã xảy ra bav kbông và có hành
động Sĩỉa chũa. Điều n à v có th ể tạo ra mã phức tạp không cẩỉì thiết và
các khối mã điíợc xếp lồng sản. Trong mô hình dựa vào ngoại lệ, một


C h ư ớ n g 10: x ù lý các lỗi___________________________________ 173

khối catch có thể điíợc sử dụng đ ể đầy bất kì> lỗi xả v ra trong khối mã
irìíớc. D iều n à v loại bỏ nhu cầti về n hiều cuộc test lỗi p h â n tầng và nó

tạo ra mã đơn giản bơn lủ dẻ đọc hơn.

» về bản chất mô hình tniyền thống có tinh m ệnh lệnh: nó đòi hỏi nhà
p h á t triển suy n g h i qua tổi cả lỗi m à có th ể x ả v ra và viết m à đểXÌC lý
từ ng k h ả n ă n g này. Trái lại, phương p h á p d ự a i>ào m ô h ìn h lin h hoạt
b ơ n . M ộ t p h ỉ i ơ n g t h ứ c x ừ lý n g o ạ i lệ g e n e r i c l à m v i ệ c n h ĩC m ộ t l ư ớ i a n

loàn, đ ó n bắt và x i'( ỉỷ thâm chí các lỗi m à m ã X íỉ lý lỗi cụ th ể đ ã không
đĩCỢC niết. Đ iều n à y c h ỉ giúp là m cho m ã ĩỉng d ụ n g m ạ n h hơn và kiên
ciíờng irìcởc n h ũ n g tình hiiống không lítòng tntớ c đĩCỢC.

K Bởi vì mô hình ngoại lệ đã sứ dụng mộ/ phương pháp dựa vào đối
tượng, các nhà phát triển đã có thểsữdiỊng nhũng khái niệm OOP về sự
tbừa k ế (inheritance) và khả nãng mở rộng (extensibiỉity) đ ể tạo subclass (class con) cho đối tỉiỢng Exception cơ sở và tạo nhĩìng đối tiíợng
Exception khác nhau cho những loại ngoại lẽ khác nhan. Diềỉi nàv làm
cho có thể phân biệt giũa các loại lỗi khác nhau và x ứ lý mọi loại lỗi
mộl cách kbác nhau.
^ Phtíơng pháp dựa vào ngoại lệ bỉiộc các nhà phái triển đìCa ra những
quyết định khó khăn í,’ể cách x ứ lý các loại lỗi khác nhau. Không giống
n h ư trong m ô h ìn h truyền thống nơi các nhà p h á t tn ể n có th ể d ễ dàng

bỏ qita (i>ô ỷ hoặc cố ý) các cuộc lest đ ể kiểm tra giá trị trà về của các
hàm , cá c ngoại lộ không d ễ bỏ qua n h ií vậv. B ằng việc đ ò i hỏi cá c nhà
p h á t triển tạo I'à tập hợp lại các khối catch, m ô b ìn h ngoại lệ buộc họ
su y n g h ĩ ĩ>è nhữ n g ngnvôn n h â n và hậít quả cửa cá c lỗi nà cuối củng
d ã n đ ế n sự th iết k ế tốt hơn và Sỉ[ thực thi m ạ n h bơn.

K huyết diểm duy nh ất? Các ngoại lệ dã được giới th iệ u chỉ tro n g PH P 5,
và k ế t quả chúng chỉ được tạo riêng bởi extension ngôn ngữ mới hơn chẳng
h ạn n h ư SimpIeXML, P H P D ata Object (PDO), Service D ata Objects (SDO),
và S ta n d a rd P H P L ibrary (SPL). Đô'i với tâ't cả hàm P H P khác, cần phải
kiểm tr a giá tr ị tr ả về của hàm dể tìm các lỗi và chuyển đổi nó th à n h m ột

ngoại lệ (exception) bằng th ủ công.
Tạo hoặc đưa ra các ngoại lệ bằng thủ công theo cách n ày là m ột tác vụ
cho câu lệ n h throw của PH P. Câu lệnh này cần được chuyển m ột th ô n g báo
lỗi mô tả và m ột m ã lỗi tùy ý. Sau đó nó tạo ra m ột đối tượng Exception sử
dụng n h ữ n g th a m sô n ày và làm cho th ô n g báo và m ă có sẵ n cho phương
thức xử lý ngoại lệ. T iến trìn h này dược m inh họa tro n g listin g sau đây:


174

C h ư ở n g 1 0 : x ử lý c á c lỗi

<’í’ php
// set file name
/ / attem pt to copy and then đelete file
$file = 'đum m y.txt';
try {
if {!file..exists($fiỉe)) ỉ
t h r c w r e w E x c e p tỉo n (“ rỉle '$ file ’ w a s not íGund,");

I
'f (fi:e_extst3í"$f:le.new"}) !
throw new Exception(“ Destination file '$file.new’ already exists.” )'

1
if (!copv($file, "$íile.n9w” }) {
throw new Exception(“ filfi '$file’ couid not be copieđ."),

)
íf (!unlínk($file)) {

throw new Exception(“ File ’$file’ Cũuld not be rem oved,” };

)
í catch {Exception $e) {
echo ‘Oops! Something bad happened on ỉ i n e ' , $e->getLíne() .

,

$e->getMessage();
exit();
I
echo 'SUCCESS; Filc operation successtul.';

?>
ở đây phụ thuộc vào k ế t quả của các h o ạ t động file k h ác nhau, m ột ngoại
lệ mới được đưa ra bởi script bằng th ủ công. Sau đó ngoại lệ n ày được đón
b ắ t bởi phương thức xử lý ngoại lệ generic và thông tin d à n h riên g cho lỗi
được trích xuất và được h iển th ị cho người dùng.
Sử dụng các ngoại lệ tù y ý
M ột phương p h áp tin h vi hơn là tạo subclass cho đối tượng Exception
generic và tạo các đôi tượng Exception riên g b iệ t cho mỗi lỗi. Phưcmg pháp
này hữu dụng k h i b ạn cần xử lý các loại ngoại lệ khác n h au m ột cách khác


x ù lý các íỗi____________________________

C h ư d n g 10;

___________________1 7 5


nhau vì nó cho phép b ạn sử dụng một khối catch riên g b iệt (và m ã xử lý
riêng biệt) cho mỗi loại ngoại lệ. Sau đây là m ột b ản chỉnh sửa của ví dụ
trước m inh h ọ a phương pháp này:
/ / subclass Exception
class MỉssingPileException extends Exception I Ị
class DuplicateRleException extends Exception { )
ciass PilelOException extends Exception {1
/ / set file name
// attem pt to Cũpy and then delete file
$file = 'dum m y.txt’ ;
trỵ {
if (!file_exists($file)) {
throvv new MissingFileException($file);

1
if (file_exlsts("$file,new ")) í
throvv new DuplicateFileException('‘$file,new’’);

}
if (!copy($fiie, “ $file.new” )) {
throw new FilelQException(“ $fỉle.new” );
I
if (!unlink($file)) {
throw new FilelOException($fiie);

1
} catch (MissingPileException $e) {
echo 'ERROR: Could not find file \” , $e->getMessage() ,
exit();

} catch (DuplicatePileException $e) (
echo 'ERROR: Destinaíion file V’ . $e->getMessage() . 'V already exỉsts’;
exit();
I catch (PỉlelOException $e) {
echo 'ERROR: Could not pertorm tile inpuưoutput operation on file \" .


1 7 6 _______________________________________________________ C h ư ớ n g 1 0 : x ử lý c á c lỗi
$e->getMessage() .
exit{);
} catch (Exception $e) I
echo ‘Oops! Something bad happened on line ‘ , $e->getLine() .

‘ . $e-

>gelMessage();
exiự);

}
echo '3UCCESS: Rle operatìon successíul.’;

?>
Script này mở rộng class Exception cơ sở để tạo ba loại E xception mới,
mối loại tượng trư n g cho m ột lỗi catch có th ể có. M ột khô’i catch riên g biệt
cho niỗi Exception bày giờ làin cho có th ể vùy biến cách xử lý mui m ọt trong
ba Exception Iià.v, lỉliối catch sau cùng là m ột phương thúe xử lý "bao tĩùm "
generic: Các Iigoại lệ khỏiig được xử lý bởi các khô'i cụ th ế nơn ở tré n nó sẽ
th ấ t bại và sẽ được giải quyết bằng phương thức xử lý nàvHỏi chuyên gia
H ỏ i: T ô i đ ă th ấ y rằ n g c á c n g o ạ i lệ k h ô n g đư ợ c đ ó n b ắ t tạ o ra m ộ i lỗi
p g h iê m trọ n g kh iế n c h o s c n p t k ế t th ú c đ ộ t ngột. T ô i cc th ể th a y d ổ i (iiể u

n à y đ ư ợc h a y kh ò ng ?

Đáp: Có và kh ô n g . PHP đưa ra hàm set_error_handler(), cho phép bạn
thay thế phương thức xử lý ngoại lệ mặc định của PHP bằng mâ tùy ý
riêng của bạn giống y như cách với set_error_handler(). Tuy nhiên, có
một điều kiện quan trọng cần lưu ý ở dây. Như bạn đã thấy phương thức
xử lý ngcại lệ mặc định của PHP hiển thị một thông báo và sau đó kết
thúc ngoại !ệ script. s ử đụng một phương Ihúc xử lý ngoại lệ tùy ý cho
p h é p giới n ạn Kiểm so á t h à n n vi này; Trong khi b ạ n c ó thể th ay th ế kiểu

cách và diện mạo của sự hiển thị thông báo, bạn không thể làm cho
s c rip t tiế p tụ c th ự c thi bên n g o à i đ iể m n ơ i n g o ạ i lệ đ ả đ ư ợ c tạ o .

Bài học của v ấn đề n ày là m ột ngoại lệ không được đón b ắ t sẽ luôn dẫn
đến việc k ế t thúc script. Đây ià lý do tạ i sao luôn n ê n bao h àm m ột khối
catch generic tro n g m ă xử lý ngoại lệ để đón b ắ t tấ t cả ngoại lệ được đưa ra
bởi script, b ấ t kể loại.


C h ư d n g 10; x ử íý

các lỗi__________________________________

177

Thực hành 10.2: Hiệu lực hóa đầu vào của Form
Bây giờ k h i b ạn đã hiểu cơ bản cách làm việc của các ngoại lệ cũng như
cách đưa ra v à đón b ắ t các ngoại lệ tùy ý, hãy áp dụng k iến thức này vào
m ột dự á n nhỏ m in h h ọ a thực t ế những công cụ này. Ví dụ tiế p theo này cho
phép người dùng đ ặ t h à n g m ột số tác phẩm mỹ th u ậ t b ằn g cách chọn m ột

nghệ sĩ, phương tiệ n và phạm vi giá cả. Sau đó đơn đ ặ t h àn g được hiệu lực
hóa, được đ ịn h d ạn g b ằn g m ột th ô n g báo email, và được chuyển san g mail
se rv e r để gởi. Các lỗi tro n g tiế n trìn h này được xử lý sử dụng các phương
thức xử lý ngoại lệ tùy ý, tạo ra m ã dọc dễ hơn và dễ duy tr ì hơn.
Sau đây là m ã (art.php):
“ D T D /xh tm ll-tran sitio na l.d td ’’>
<htm! xm ins= "http ;//w w w .w 3.org/1999/xhtm r' xm l:lang=” en” lang="en” >
<heađ>
<title>Project 10-2: Vaỉidating Form lnpưtc/tit!e>

<style type="texưcss” >
div.success (
w idth:200px;
padding:5px;
border:solid 1px black;
color:green;

1
div.error {

w idth;400px;
padding:5px;
border:so!iđ 1px biack:
co lo rre d ;
ì
</styie>
</head>
<body>

Projecí 10-2: Validaíing Form Input</lì2>



178

C h ư đ n g 1 0 : x ử lý c á c lỗi

Purchase Rne Art


// if form not yet submitíeđ
/ / đisplay form
ií (!isset($_POST('siJbmit’])) {

?>
<form methoữ=-"posĩ" acíion="art,php'’>
Artist:

<option value=” ”>— select one— </option>
<option value="Picasso">Picasso</option>
<option valLie=’V=ỉn Gngh” >van Gogtì</npíion>
<option va[ue="ChagaH">C‘ iagall</option>
<option vaìue=’'Degas’’>Degas</option>
<option vaỉue="Monet'’>Monet</option>
<optíon value="Matỉsse">IVIatisse</option>
</select>


Medium:

<select name="mediurĩi’’>
<option value=” ”>— select one— </option>
<option va!ue="oir’>Oil</optỉon>
<optior value-"v^atercolor” >Waíercolor</option>


<option value="ink">lnk</option>
</select>


Price betvveen:

<inpưt type="text” size=” 4 ' n am e*"m in"/> and size="5" name=” max"/>


Email address:

<input type=” text" size="25" name=’'emair7>


C h ư d n g 10: x ử iý các lỗi

179


<inpưt type=” submit” name=’'submit" value=” Submit" />
</form >

// if form submitted
/ / process íorm input

} else {
error_reporting(E_ERROR);
// detine exception classes
class InputException extends Exception { }
class LogicalExceplion extends Exception { }


class MailException extends Exception { }
// get form input
Sartist = $_POST['artist’];
$m edium = $_POST['medium’];
$m in = $_POSTỊ'min’];
$m ax = $_POST('max'];
$email = $_POST[‘em air];
try {
// validate form input
if (em pty($artist)) {
íhrow new lnputException('Artist’):

1
if (empty($medium)) {
throw new lnputException{'Medium');
ì
if (em pty{$em ail)) 1
throw new lnputException('Émail address');

1
if {em pty($m in) II empty($max) I! (ỉnt)$min <~ 0 II {int)$m ax <= 0) {
throw new lnputException('Price');
1