P. 1
PHP nâng cao

PHP nâng cao

|Views: 507|Likes:
Được xuất bản bởikhoinhh

More info:

Published by: khoinhh on Jan 11, 2010
Bản quyền:Attribution Non-commercial

Availability:

Read on Scribd mobile: iPhone, iPad and Android.
download as DOC, PDF, TXT or read online from Scribd
See more
See less

04/12/2013

pdf

text

original

Thao tác với Email Trong PHP, chúng ta có thể viết các ứng dụng email ngon lành

cỡ outlook một cách khá đơn giản. Bài viết này giới thiệu một số kỹ thuật dùng để gửi và nhận email bằng PHP. Phần I. Gửi email bằng PHP Trong PHP có hai cách gửi mail: Gửi email trực tiếp bằng hàm mail (chạy trực tiếp trên máy chủ) và gửi email thông qua một mail server khác (cách này phức tạp hơn so với cách trên vì ta phải kết nối tới máy kia và biết cách họat động của chùm giao thức SMTP). 1. Gửi email thông qua hàm mail() Để gửi email trực tiếp từ máy chủ, ta có thể sử dụng hàm mail () với cú pháp như sau: mail (dia_chi_nhan,tieu_de,noi_dung,cac_tham_so_mo_rong_tuy_chon). Ví dụ: Code:
<html> <body> <?php if (isset($_REQUEST['email'])) //if "email" is filled out, send email { //send email $email = $_REQUEST['email'] ; $to = $_REQUEST['to'] ; $subject = $_REQUEST['subject'] ; $message = $_REQUEST['message'] ; mail( $to, "Subject: $subject",$message" ); echo "Thank you for using our mail form"; } else //if "email" is not filled out, display the form { echo "<form method='post' action='phpmail.php'> Người gửi: <input name='email' type='text' /><br /> Gửi tới: <input name='to' type='text' /><br /> Tiêu đề: <input name='subject' type='text' /><br /> Nội dung:<br /> <textarea name='message' rows='15' cols='40'> </textarea><br /> <input type='submit' /> </form>"; } ?>

</body> </html>

2. Kỹ thuật gửi email với phần Header mở rộng Kỹ thuật này sẽ cho phép bạn đưa thêm một số thông tin vào phần Header của thông điệp email (Nếu bạn kiểm tra email sẽ có phần Header, trong đó ghi rất nhiều thông tin , chẳng hạn như địa chỉ IP xuất phát, qua những máy email nào, thời điểm...). Ở đây chúng ta sẽ sử dụng phần tham số mở rộng. VD: Code:
$ThongTinMoRong="From: webmaster@$SERVER_NAME\r\n" ."Reply-To: webmaster@$SERVER_NAME\r\n" ."X-Mailer: PHP/" . phpversion(); mail($EmailGui, $EmailNhan, $NoiDung,$ThongTinMoRong);

3. Kỹ thuật gửi email theo định dạng HTML. Chú ý rằng ở chế độ mặc định, nội dung thông điệp được truyền tải đi dưới dạng văn bản thuần túy (plain text), và không thể hiện được các cấu trúc HTML thông thường. Để có thể đưa định dạng HTML vào mail, qua đó cho phép hiển thị hình ảnh, định dạng font chữ..., ta phải đưa thêm dòng sau đây vào phần header: MIME-Version: 1.0 Content-type: text/html; charset=iso-8859-1 Ví dụ: Code:
<? /* recipients */ $to = "Mary <mary@example.com>" . ", " ; //note the comma $to .= "Kelly <kelly@example.com>"; /* subject */ $subject = "Birthday Reminders for August"; /* message */ $message = ' <html> <head> <title>Birthday Reminders for August</title> </head> <body> <p>Here are the birthdays upcoming in August!</p> <table> <tr> <th>Person</th><th>Day</th><th>Month</th><th>Year</th> </tr> <tr> <td>Joe</td><td>3rd</td><td>August</td><td>1970</td> </tr> <tr>

<td>Sally</td><td>17th</td><td>August</td><td>1973</td> </tr> </table> </body> </html> '; /* To send HTML mail, you can set the Content-type header. */ $headers = "MIME-Version: 1.0\r\n"; $headers .= "Content-type: text/html; charset=iso-8859-1\r\n"; /* additional headers */ $headers .= "From: Birthday Reminder <birthday@example.com>\r\n"; $headers .= "Cc: birthdayarchive@example.com\r\n"; $headers .= "Bcc: birthdaycheck@example.com\r\n"; /* and now mail it */ mail($to, $subject, $message, $headers); ?>

Sử dụng Socket với PHP tác giả:Andrew Walsh ngDịch :phpnubie Sockets là một cách thức dùng trong PHP để kết nối với một server khác qua mạng hay internet. function căn bản để mở kết nối đến server là fsocken(). Có thể bạn sẽ thấy ngạc nhiên tại sao bạn lại muốn kết nối đến server khác. Nếu bạn cần thêm thông tin về 3rd party server thì sockets là cái cho bạn cần. Tutorial này hướng dẫn chúng ta các phương thức sau đây : # Connect To A Server Using Sockets # Disconnect From a Server%br% # Send a request to a server%br% # List the number of lines returned by the server on a request%br% # Use sockets in a practical project like a whois look-up script Kết nối qua sử dụng sockets với PHP Nếu bạn có ý nghĩ nối kết với internet server khác với php rất rắc rối , có lẽ bạn hơi lầm. Bạn chỉ cần nối mạng bằng một dòng code của php. trong phần này sẽ giải thích cách nối và ngắt nối mạng qua sử dụng sockets. Code:
<?php /* Tham số mà fsockopen cần là: fsockopen(IP/Hostname, cổng (port), Lỗi ($errno), miêu tả lỗi phát hiện($errd esc) */ $fp = fsockopen( "www.phpvn.org", 80, $errno, $errdesc); ?> Bạn đã thiết lập một kết nối đến server vd: phpvn.org. Bạn cũng nên làm quen với function fclose() để ngắt nối mạng.

<?php $fp = fsockopen( "www.phpvn.org", 80, $errno, $errdesc); //establish connection fclose($fp); //close connection ?>

Gởi một Request Trong phần kế tiếp này bạn sẽ làm quen với cách gởi một request đến server và cho thể hiện một danh sách mà server gởi trả lại cho bạn cũng như cách làm việc của nó. Việc trước tiên cần làm là mở một kết nối đến server với một tên biến $fp, có nghĩa bạn đã gởi một $fp và nhận được một kết quả trả về từ server mà bạn đã gởi đến. Code:
<?php /* Kết nối đến server vd: www. example.com */ $host = "www.example.com"; $page = "/index.html"; $fp = fsockopen($host, 80, $errno, $errdesc) or die("Connection to $host failed"); /* Chúng ta xác định thông tin của header để gởi đến cho server GET, được hiểu chúng ta muốn nhận được thông tin hay trang web từ server đó Bạn cũng có thể sử dụng POST để làm việc này. */ $request = "GET $page HTTP/1.0&#38;#92;r&#38;#92;n"; $request .= "Host: $host&#38;#92;r&#38;#92;n"; $request .= "Referer: $host&#38;#92;r&#38;#92;n"; /* Sử dụng function fput() gởi đòi hỏi(request) đến server và tạo một vòng lập (loop) lấy kết quả được từ mãng, được gọi là $page */ fputs($fp, $request); while(!feof($fp)){ $page[] = fgets($fp, 1024); } /* Đóng mạng đồng thời lấy tổng số trang nhận được */ fclose($fp); echo "The server returned ".(count($page)). " Lines"; /* Tạo vòng lập (for) và in dữ liệu. */ for($i=0; $i&lt;count($page); $i++){ echo $page[$i]; } ?>

Tìm kiếm (Searching for a page) Trong phần này chúng ta sử dụng fsockenopen() để kể nối đến nhiều server và kiểm soát một trang nào đó trong server.

Code:
<?php $servers = array( "www.example.com" =&gt; "/index.html", "www.example2.com" =&gt; "/index.php" ); /* Tạo vòng lập cho server array và kết nối đên mạng, Báo lỗi nếu không kết nối được */ foreach($servers as $host=&gt; $page){ $fp = fsockopen($host,80,$errno,$errdesc,10); echo "Trying $host&lt;br&gt;&#38;#92;n"; if(!$fp){ echo("couldnt connect to $host"); echo "&lt;br&gt;&lt;hr&gt;&lt;br&gt;&#38;#92;n"; continue; } /* Xác định thông tin, và gởi request đến server */ echo "trying to get $page&lt;br&gt;&#38;#92;n"; $request = "HEAD $page HTTP/1.0&#38;#92;r&#38;#92;n&#38;#92;r&#38;#92;n"; fputs($fp, $request); echo fgets($fp, 1024); echo "&lt;br&gt;&lt;br&gt;&lt;br&gt;&#38;#92;n"; /* Đóng mạng */ fclose($fp); } ?>

Dòng code trên được diễn như sau: Trying: www.example.com Trying to get: /index.html HTTP/1.1 200 OK Nó chỉ hiện những trang đã tìm được, nếu không sẽ thay thế trang 404 bằng mã số 200. ứng dụng Whois Bạn đã biết qua ứng dụng kết nối đến một server, tạo vòng lập để in kết quả và cách đóng mạng. chúng ta thực hành thêm một vài thao tác cho ứng dụng whois. Code:
<?php extract($_POST); function whois($domain,$ext){ $url=$domain.$ext; /* sử dụng switch() để xác định whois server nào là server thích hợp nhất để kết nối domain */

switch($ext){ case ".co.uk": $whois = "whois.nic.uk"; break; case ".com": $whois = "whois.networksolutions.com"; break; case ".fr": $whois = "whois.nic.fr"; break; case ".biz": $whois = "whois.biz"; break; default: $whois = "whois.networksolutions.com"; } if (trim($url) &lt;&gt; "") { $url = trim($url); /* kết nối đến server */ $f = fsockopen($whois, 43, $errno, $errstr, 30); if (!$f) { echo "Connection To Server Failed ($errno)"; } else { /* Gởi domain đến một server và chờ nhận kết quả */ fputs($f, "$url&#38;#92;r&#38;#92;n"); print "&lt;pre&gt;&#38;#92;r&#38;#92;n"; while (!feof($f)) { echo fread($f,128); } print "&lt;/pre&gt;"; /* Đóng mạng */ fclose($f); } }else{ echo "Invalid domain entered"; } } ?>

Phần I: Tổng quan về lập trình hướng đối tượng 1. Lập trình hướng đối tượng là gì? Lập trình hướng đối tượng (gọi tắt là OOP, từ chữ Anh ngữ object-oriented programming), hay còn gọi là lập trình định hướng đối tượng, là kĩ thuật lập trình hỗ trợ công nghệ đối tượng. OOP được xem là giúp tăng năng suất, đơn giản hóa độ phức tạp khi bảo trì cũng như mở rộng phần mềm bằng cách cho phép lập trình viên tập trung vào các đối tượng phần mềm ở bậc cao hơn. Ngoài ra, nhiều người còn cho rằng OOP

dễ tiếp thu hơn cho những người mới học về lập trình hơn là các phương pháp trước đó. Một cách giản lược, đây là khái niệm và là một nỗ lực nhằm giảm nhẹ các thao tác viết mã cho người lập trình, cho phép họ tạo ra các ứng dụng mà các yếu tố bên ngoài có thể tương tác với các chương trình đó giống như là tương tác với các đối tượng vật lý. Những đối tượng trong một ngôn ngữ OOP là các kết hợp giữa mã và dữ liệu mà chúng được nhìn nhận như là một đơn vị duy nhất. Mỗi đối tượng có một tên riêng biệt và tất cả các tham chiếu đến đối tượng đó được tiến hành qua tên của nó. Như vậy, mỗi đối tượng có khả năng nhận vào các thông báo, xử lý dữ liệu (bên trong của nó), và gửi ra hay trả lời đến các đối tượng khác hay đến môi trường. 2. Các tính chất cơ bản của lập trình hướng đối tượng Đối tượng (object): Các dữ liệu và chỉ thị được kết hợp vào một đơn vị đầy đủ tạo nên một đối tượng. Đơn vị này tương đương với một chương trình con và vì thế các đối tượng sẽ được chia thành hai bộ phận chính: phần các phương thức (method) và phần các thuộc tính (property). Trong thực tế, các phương thức của đối tượng là các hàm và các thuộc tính của nó là các biến, các tham số hay hằng nội tại của một đối tượng (hay nói cách khác tập hợp các dữ liệu nội tại tạo thành thuộc tính của đối tượng). Các phương thức là phương tiện để sử dụng một đối tượng trong khi các thuộc tính sẽ mô tả đối tượng có những tính chất gì. Các phương thức và các thuộc tính thường gắn chặt với thực tế các đặc tính và sử dụng của một đối tượng. Trong thực tế, các đối tượng thường được trừu tượng hóa qua việc định nghĩa của các lớp (class). Tập hợp các giá trị hiện có của các thuộc tính tạo nên trạng thái của một đối tượng. Mỗi phương thức hay mỗi dữ liệu nội tại cùng với các tính chất được định nghĩa (bởi người lập trình) được xem là một đặc tính riêng của đối tượng. Nếu không có gì lầm lẫn thì tập hợp các đặc tính này gọi chung là đặc tính của đối tượng. Lập trình hướng đối tượng là một phương pháp lập trình có các tính chất chính sau: Tính trừu tượng (abstraction): Đây là khả năng của chương trình bỏ qua hay không chú ý đến một số khía cạnh của thông tin mà nó đang trực tiếp làm việc lên, nghĩa là nó có khả năng tập trung vào những cốt lõi cần thiết. Mỗi đối tượng phục vụ như là một "động tử" có thể hoàn tất các công việc một cách nội bộ, báo cáo, thay đổi trạng thái của nó và liên lạc với các đối tượng khác mà không cần cho biết làm cách nào đối tượng tiến hành được các thao tác. Tính chất này thường được gọi là sự trừu tượng của dữ liệu. Tính trừu tượng còn thể hiện qua việc một đối tượng ban đầu có thể có một số đặc điểm chung cho nhiều đối tượng khác như là sự mở rộng của nó nhưng bản thân đối tượng ban đầu này có thể không có các biện pháp thi hành. Tính trừu tượng này thường được xác định trong khái niệm gọi là lớp trừu tượng hay hay lớp cơ sở trừu tượng.

Tính đóng gói (encapsulation) và che dấu thông tin (information hiding): Tính chất này không cho phép người sử dụng các đối tượng thay đổi trạng thái nội tại của một đối tượng. Chỉ có các phương thức nội tại của đối tượng cho phép thay đổi trạng thái của nó. Việc cho phép môi trường bên ngoài tác động lên các dữ liệu nội tại của một đối tượng theo cách nào là hoàn toàn tùy thuộc vào người viết mã. Đây là tính chất đảm bảo sự toàn vẹn của đối tượng. Tính đa hình (polymorphism): Thể hiện thông qua việc gửi các thông điệp (message). Việc gửi các thông điệp này có thể so sánh như việc gọi các hàm bên trong của một đối tượng. Các phương thức dùng trả lời cho một thông điệp sẽ tùy theo đối tượng mà thông điệp đó được gửi tới sẽ có phản ứng khác nhau. Người lập trình có thể định nghĩa một đặc tính (chẳng hạn thông qua tên của các phương thức) cho một loạt các đối tượng gần nhau nhưng khi thi hành thì dùng cùng một tên gọi mà sự thi hành của mỗi đối tượng sẽ tự động xảy ra tương ứng theo đặc tính của từng đối tượng mà không bị nhầm lẫn. Thí dụ khi định nghĩa hai đối tượng "hinh_vuong" và "hinh_tron" thì có một phương thức chung là "chu_vi". Khi gọi phương thức này thì nếu đối tượng là "hinh_vuong" nó sẽ tính theo công thức khác với khi đối tượng là "hinh_tron". Tính kế thừa (inheritance): Đặc tính này cho phép một đối tượng có thể có sẵn các đặc tính mà đối tượng khác đã có thông qua kế thừa. Điều này cho phép các đối tượng chia sẻ hay mở rộng các đặc tính sẵn có mà không phải tiến hành định nghĩa lại. Tuy nhiên, không phải ngôn ngữ định hướng đối tượng nào cũng có tính chất này. 3. Các khái niệm liên quan đến các ngôn ngữ lập trình OOP hiện đại Lớp (class) Một lớp được hiểu là một kiểu dữ liệu bao gồm các thuộc tính và các phương thức được định nghĩa từ trước. Đây là sự trừu tượng hóa của đối tượng. Một đối tượng sẽ được xác lập khi nó được thực thể hóa từ một lớp. Khác với kiểu dữ liệu thông thường, một lớp là một đơn vị (trừu tượng) bao gồm sự kết hợp giữa các phương thức và các thuộc tính. Để có một đối tượng (mà có thể được xem như là một biến) hoạt động được thì việc thực thể hóa sẽ có thể bao gồm việc cài đặt các giá trị ban đầu của các thuộc tính cũng như việc đăng kí bộ nhớ, mà công việc này thường được giao cho các phương thức gọi là "máy kết cấu" (constructor) hay hàm dựng. Ngược lại khi một đối tượng thuộc về một lớp không còn sử dụng nữa thì cũng có thể có một phương thức để xử lý gọi là "máy hủy diệt" (destructor) hay hàm hủy. Như vậy, để có được các đối tượng thì người lập trình OOP cần phải thiết kế lớp của các đối tượng đó bằng cách xây dựng các thuộc tính và các phương thức có các đặc tính riêng. Mỗi một phương thức hay một thuộc tính đầy đủ của một lớp còn được gọi tên là một thành viên (member) của lớp đó. Lớp con (subclass) Lớp con là một lớp thông thường nhưng có thêm tính chất kế thừa một phần hay toàn bộ các đặc tính của một lớp khác. Lớp mà chia sẽ sự kế thừa gọi là lớp phụ mẫu (parent class).

Lớp trừu tượng hay lớp cơ sở trừu tượng (abstract class) Lớp trừu tượng là một lớp mà nó không thể thực thể hóa thành một đối tượng thực dụng được. Lớp này được thiết kế nhằm tạo ra một lớp có các đặc tính tổng quát nhưng bản thân lớp đó chưa có ý nghĩa (hay không đủ ý nghĩa) để có thể tiến hành viết mã cho việc thực thể hóa. (xem thí dụ) Thí dụ: Lớp "hinh_phang" được định nghĩa không có dữ liệu nội tại và chỉ có các phương thức (hàm nội tại) "tinh_chu_vi", "tinh_dien_tich". Nhưng vì lớp hình_phẳng này chưa xác định được đầy đủ các đặc tính của nó (cụ thể các biến nội tại là tọa độ các đỉnh nếu là đa giác, là đường bán kính và toạ độ tâm nếu là hình tròn, ...) nên nó chỉ có thể được viết thành một lớp trừu tượng. Sau đó, người lập trình có thể tạo ra các lớp con chẳng hạn như là lớp "tam_giac", lớp "hinh_tron", lớp "tu_giac",.... Và trong các lớp con này người viết mã sẽ cung cấp các dữ liệu nội tại (như là biến nội tại r làm bán kính và hằng số nội tại Pi cho lớp "hinh_tron" và sau đó viết mã cụ thể cho các phương thức "tinh_chu_vi" và "tinh_dien_tich"). Phương Thức (method) Là hàm nội tại của một lớp (hay một đối tượng). Tùy theo đặc tính mà người lập trình gán cho, một phương pháp có thể chỉ được gọi bên trong các hàm khác của lớp đó, có thể cho phép các câu lệnh bên ngoài lớp gọi tới nó, hay chỉ cho phép các lớp có quan hệ đặc biệt như là quan hệ lớp con, và quan hệ bạn bè (friend) được phép gọi tới nó. Mỗi phương pháp đều có thể có kiểu trả về, chúng có thể trả các kiểu dữ liệu cổ điển hay trả về một kiểu là một lớp đã được định nghĩa từ trước. Một tên gọi khác của phương pháp của một lớp là hàm thành viên. Người ta còn định nghĩa thêm vài loại phương pháp đặc biệt: Hàm dựng (constructor) là hàm được dùng để cài đặt các giá tri ban đầu cho các biến nội tại và đôi khi còn dùng để khai báo về việc xử dụng bộ nhớ. Hàm hủy (destructor) là hàm dùng vào việc làm sạch bộ nhớ và hủy bỏ tên của một đối tượng sau khi đã dùng xong, trong đó có thể bao gồm cả việc xóa các con trỏ nội tại và trả về các phần bộ nhớ mà đối tượng đã dùng. Trong một số trường hợp thì hàm hủy hay hàm dựng có thể được tự động hóa bởi ngôn ngữ OOP như là trường hợp của Visual C++, C#. Tiện ích (utility) là các hàm chỉ họat động bên trong của một lớp mà không cho phép môi trường bên ngoài gọi tới. Các hàm này có thể là những tính toán trung gian nội bộ của một đối tượng mà xét thấy không cần thiết phải cho thế giới bên ngoài của đối tượng biết là gì. Thuộc tính (attribute) Thuộc tính của một lớp bao gồm các biến, các hằng, hay tham số nội tại của lớp đó. Ở đây, vai trò quan trọng nhất của các thuộc tính là các biến vì chúng sẽ có thể bị thay đổi trong suốt quá trình hoạt động của một đối tượng. Các thuộc tính có thể được xác định kiểu và kiểu của chúng có thể là các kiểu dữ liệu cổ điển hay đó là một lớp đã định nghĩa từ trước. Như đã ghi, khi một lớp đã được thực thể hoá thành đối

tượng cụ thể thì tập họp các giá trị của các biến nội tại làm thành trạng thái của đối tượng. Giống như trường hợp của phương pháp, tùy theo người viết mã, biến nội tại có thể chỉ được dùng bên trong các phương pháp của chính lớp đó, có thể cho phép các câu lệnh bên ngoài lớp, hay chỉ cho phép các lớp có quan hệ đặc biệt như là quan hệ lớp con, (và quan hệ bạn bè (friend) trong C++) được phép dùng tới nó (hay thay đổi giá trị của nó). Mỗi thuộc tính của một lớp còn được gọi là thành viên dữ liệu của lớp đó. Thực thể (instance) Thực thể hóa (instantiate) là quá trình khai báo để có một tên (có thể được xem như là một biến) trở thành một đối tượng từ một lớp nào đó. Một lớp sau khi được tiến hành thực thể hóa để có một đối tượng cụ thể gọi là một thực thể. Hay nói ngược lại một thực thể là một đối tượng riêng lẽ của một lớp đã định trước. Như các biến thông thường, hai thực thể của cùng một lớp có thể có trạng thái nội tại khác nhau (xác định bởi các giá trị hiện có của các biến nội tại) và do đó hoàn toàn độc lập nhau nếu không có yêu cầu gì đặc biệt từ người lập trình. Công cộng (public) Công cộng là một tính chất được dùng để gán cho các phương pháp, các biến nội tại, hay các lớp mà khi khai báo thì người lập trình đã cho phép các câu lệnh bên ngoài cũng như các đối tượng khác được phép dùng đến nó. Thí dụ: Trong C++ khai báo public: int my_var; thì biến my_var có hai tính chất là tính công cộng và là một integer cả hai tính chất này hợp thành đặc tính của biến my_var khiến nó có thể được xử dụng hay thay đổi giá trị của nó (bởi các câu lệnh) ở mọi nơi bên ngoài lẫn bên trong của lớp. Riêng tư (private) Riêng tư là sự thể hiện tính chất đóng mạnh nhất (của một đặc tính hay một lớp). Khi dùng tính chất này gán cho một biến, một phương pháp thì biến hay phương pháp đó chỉ có thể được sử dụng bên trong của lớp mà chúng được định nghĩa. Mọi nỗ lực dùng đến chúng từ bên ngoài qua các câu lệnh hay từ các lớp con sẽ bị phủ nhận hay bị lỗi. Bảo tồn (protected) Tùy theo ngôn ngữ, sẽ có vài điểm nhỏ khác nhau về cách hiểu tính chất này. Nhìn chung đây là tính chất mà mà khi dùng để áp dụng cho các phương pháp, các biến nội tại, hay các lớp thì chỉ có trong nội bộ của lớp đó hay các lớp con của nó (hay trong nội bộ một gói như trong Java) được phép gọi đến hay dùng đến các phương pháp, biến hay lớp đó. So với tính chất riêng tư thì tính bảo tồn rộng rãi hơn về nghĩa chia sẻ dữ liệu hay chức năng. Nó cho phép một số trường hợp được dùng tới các đặc tính của một lớp (từ một lớp con chẳng hạn). Lưu ý: Các tính chất cộng cộng, riêng tư và bảo tồn đôi khi còn được dùng để chỉ thị cho một lớp con

cách thức kế thừa một lớp cha mẹ như trong C++. Đa kế thừa (muliple inheritance) Đây là một tính chất cho phép một lớp con có khả năng kế thừa trực tiếp cùng lúc nhiều lớp khác. Vài điểm cần lưu ý khi viết mã dùng tính chất đa kế thừa: Khi muốn có một sự kế thừa từ nhiều lớp phụ mẫu thì các lớp này cần phải độc lập và đặc biệt tên của các dữ liệu hay hàm cho phép kế thừa phải có tên khác nhau để tránh lỗi "ambiguilty". Bởi vì lúc đó phần mềm chuyển dịch sẽ không thể xác định được là lớp con sẽ thừa kế tên nào của các lớp phụ mẫu. Không phải ngôn ngữ OOP loại phân lớp nào cũng hỗ trợ cho tính chất này. Ngoài các khái niệm trên, tùy theo ngôn ngữ, có thể sẽ có các chức năng OOP riêng biệt được cấp thêm vào.

Lập trình hướng đối tượng trong PHP 5 a. Khai báo lớp và thể hiện của lớp trong PHP Như chúng ta đã biết, một lớp bao gồm các kiểu thuộc tính và phương thức. Trong PHP5, chúng ta khai báo một lớp với cú pháp như sau: Code:
class tên_lớp { // Danh sách các biến, hằng, lớp... (thuộc tính) // Danh sách các hàm (phương thức) }

Trong đó, các lớp được khai báo thông qua từ khoá class, các thuộc tính được khai báo dưới dạng các biến, còn các phương thức được xây dựng dưới dạng các hàm. Các thuộc tính và các phương thức trong lập trình hướng đối tượng có thể được thiết lập những tính chất đặc biệt như : riêng tư (private), công cộng (public)... Các tính chất này thường được đặt trước các khai báo thuộc tính và phương thức. Ví dụ đơn giản dưới đây thể hiện một lớp có tên là ho_so với các thuộc tính công cộng bao gồm ho_ten, ngay_sinh: Code:
class hoso { public $ho_ten; public $ngay_sinh; }

Đoạn mã trên mới chỉ khai báo một lớp thực thể với hai biến là $ho_ten và $ngay_sinh. Bây giờ chúng ta sẽ khai báo một thể hiện của lớp trên.

Để khai báo một thể hiện của một lớp, ta dùng từ khoá new, tiếp đó là tên lớp: $ten_thuc_the = new ten_lop; Để truy cập vào từng thuộc tính hay phương thức của lớp, ta dùng toán tử -> với cú pháp như sau: $ten_thuc_the-->ten_thuoc_tinh; Ví dụ sau đây sẽ tạo ra một thực thể của một cá nhân có tên là Hoàng: Code:
<HTML> <HEAD> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> </HEAD> <BODY> <? class hoso { public $ho_ten; public $ngay_sinh; } $hoang=new hoso; $hoang->ho_ten="Nguyễn Huy Hoàng"; $hoang->ngay_sinh = "25/7/2003"; echo "Họ tên: " . $hoang->ho_ten . ". Ngày sinh: " . $hoang->ngay_sinh; ?> </BODY> </HTML>

Bây giờ, chúng ta sẽ trang bị thêm một phương thức để thay đổi giá trị của các thuộc tính ho_ten và ngay_sinh. Để tham chiếu tới các phần tử trong chính bản thân lớp đối tượng, chúng ta sử dụng biến $this và toán tử tham chiếu ->, theo sau đó là tên của phương thức hoặc thuộc tính: Code:
<HTML> <HEAD> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> </HEAD> <BODY> <? class hoso { public $ho_ten; public $ngay_sinh; public function lap_gia_tri($hoten,$ngaysinh) { $this->ho_ten = $hoten; $this->ngay_sinh=$ngaysinh; } } $hoang=new hoso; $hoang->lap_gia_tri("Nguyễn Huy Hoàng","25/7/2003"); echo "Họ tên: " . $hoang->ho_ten . ". Ngày sinh: " . $hoang->ngay_sinh;

?> </BODY> </HTML>

Chú ý rằng khi khai báo một lớp, chúng ta cũng có thể thiết lập những giá trị mặc định ban đầu cho tất cả các thành viên được tạo ra từ lớp đó. Ví dụ: Code:
<HTML> <HEAD> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> </HEAD> <BODY> <? class hoso { public $ho_ten = "Nguyễn Huy Hoàng"; public $ngay_sinh = "25/7/2003"; public function lap_gia_tri($hoten,$ngaysinh) { $this->ho_ten = $hoten; $this->ngay_sinh=$ngaysinh; } } $hoang=new hoso; echo "Họ tên: " . $hoang->ho_ten . ". Ngày sinh: " . $hoang->ngay_sinh; ?> </BODY> </HTML>

Cơ chế đóng kín và tính rõ ràng của các phần tử trong lớp Như chúng ta đã biết, lập trình hướng đối tượng tập trung vào việc “đóng gói” các phương thức và thuộc tính của một đối tượng nào đó. Trong lập trình hướng đối tượng, các thành viên trong một lớp cần phải được xác định xem chúng có thể được truy xuất từ đâu (tính rõ ràng). Có ba khả năng xảy ra: - Chế độ truy xuất công cộng (public): Các thành viên nếu được thiết lập ở chế độ này sẽ được nhìn thấy và truy xuất ở mọi nơi trong chương trình. - Chế độ truy xuất riêng tư (private): Các thành viên nếu được thiết lập ở chế độ này sẽ chỉ được nhìn thấy và truy xuất được ở bản thân lớp định nghĩa thành viên đó. - Chế độ bảo vệ (protected): Chế độ này sẽ được dùng để giới hạn truy cập tới các lớp được thừa kế và bản thân lớp định nghĩa thành viên đó. Trong PHP5, tất cả các thành viên của một lớp đều phải được khai báo tính rõ ràng với các từ khoá tương ứng là public, protected và private. Ví dụ: Code:

<?php class MyClass { public $public = 'Public'; protected $protected = 'Protected'; private $private = 'Private'; public function printHello() { echo $this->public; echo $this->protected; echo $this->private; }

}

$obj = new MyClass(); echo $obj->public; // Làm việc tốt echo $obj->protected; // Gây lỗi do thuộc tính $protected đã bị đặt ở chế độ bảo vệ echo $obj->private; // Gây lỗi do thuộc tính $protected đã bị đặt ở chế độ ri êng tư $obj->printHello(); // Hoạt động bình thường, do các thuộc tính được triệu gọi bên trong một phương thức nằm trong lớp. class MyClass2 extends MyClass { protected $protected = 'Protected2'; function { echo echo echo } } $obj2 = new MyClass2(); echo $obj->public; // Chạy tốt echo $obj2->private; // Chưa được định nghĩa echo $obj2->protected; // Gây lỗi $obj2->printHello(); // Hiển thị Public, Protected2, not Private ?> printHello() $this->public; $this->protected; $this->private;

Nếu như chúng ta không đặt các từ khoá xác định tính rõ ràng của các thành viên, theo mặc định chúng sẽ ở chế độ public.

ế thừa lớp trong PHP 5 Ở phần trên, các bạn đã biết đến khái niệm kế thừa giữa các lớp, đó là khả năng một lớp có thể được kế thừa các thành phần dữ liệu cũng như phương thức của một lớp nào đó. Lớp thừa kế những phương thức và thuộc tính của lớp khác được gọi là lớp con, còn lớp được kế thừa được gọi là lớp cha. Trong PHP, một lớp có thể thừa kế các phương thức cũng như các thuộc tính của một lớp khác

bằng cách sử dụng từ khoá extends trong khi khai báo tên lớp. Ví dụ dưới đây thực hiện việc mở rộng lớp hoso ở trên thêm một số thuộc tính mới bằng cách kế thừa từ lớp hoso: Code:
<HTML> <HEAD> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> </HEAD> <BODY> <? class hoso { public $ho_ten = "Nguyễn Huy Hoàng"; public $ngay_sinh = "25/7/2003"; public function lap_gia_tri($hoten,$ngaysinh) { $this->ho_ten = $hoten; $this->ngay_sinh=$ngaysinh; } } class hoso2 extends hoso { public $noi_sinh="Thanh Hoá"; public function in_hoso() { echo "Họ tên: " . $this->ho_ten . ". Ngày sinh: " . $this>ngay_sinh . " . Nơi sinh: " . $this->noi_sinh; } } $hoang=new hoso2; $hoang->in_hoso(); ?> </BODY> </HTML>

Các phương thức và thành viên thừa kế từ lớp cha sang lớp con có thể bị ghi đè nếu như lớp cha không định nghĩa chúng dưới dạng các phương thức cuối cùng với từ khoá final. Kỹ thuật ghi đè cho phép chúng ta có thể định nghĩa lại các hàm trong lớp cha bằng các hàm cùng tên trong lớp con nhưng hai hàm này có hai chức năng hoàn toàn khác nhau. Nhiều người gọi kỹ thuật này là “đa hình” do chúng tạo ra nhiều hình thái khác nhau ở các lớp thừa kế. Chúng ta có thể truy cập đến các phương thức hay thành viên đã bị ghi đè bằng cách tham chiếu chúng với từ khoá parent và toán tử tham chiếu ::, tiếp theo là phương thức hay thành viên cần tham chiếu (parent::ten_phuong_thuc). Ví dụ dưới đây mô tả cách thức ghi đè: Code:
<HEAD> </HEAD> <BODY> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />

<? class hoso { public $ho_ten = "Nguyễn Huy Hoàng"; public $ngay_sinh = "25/7/2003"; public function in_hoso() { echo "Họ tên:" . $this->ho_ten . ". Ngày sinh: " . $this>ngay_sinh; } } class hoso2 extends hoso { public $noi_sinh="Thanh Hoá"; public function in_hoso() { parent::in_hoso(); echo ". Nơi sinh: " . $this->noi_sinh; } } $hoang=new hoso2; $hoang->in_hoso(); ?> </BODY> </HTML>

Như các bạn đã thấy, đối tượng $hoang thuộc lớp hoso2 đã được kế thừa mọi thứ ở lớp hoso. Trong lớp hoso2, chúng ta đã định nghĩa một hàm trùng tên với một hàm đã có sẵn trong lớp hoso (hàm in_hoso()). Hàm in_hoso() của lớp hoso2 đã ghi đè lên hàm in_hoso() của lớp hoso, nhưng trong bản thân nó lại có thể triệu gọi trực tiếp đến hàm in_hoso() trong lớp cha (hoso).

Ngưỡng cửa vào thế giới ZendFramework Tác giả Bob Allen www.arkabat.com người dịch: phpnubie.phpvn.org Hướng dẫn này nhằm giúp các bạn đi vào thế giới của ZendFramework để có thể dễ dàng tạo các ứng dụng web qua thư viện của ZF. trong phần hướng dẫn này chúng ta cùng nhau làm một ứng dụng lưu giữ dữ liệu của CD trong CSDL. Cấu trúc Model-View-Controller Một lối viết code bình thường trong ừng dụng PHP như sau: Code:
<?php include "common-libs.php"; include "config.php"; mysql_connect($hostname, $username, $password); mysql_select_db($database); ?>

<?php include "header.php"; ?> <h1>Home Page</h1> <?php $sql = "SELECT * FROM news"; $result = mysql_query($sql); ?> <table> <?php while ($row = mysql_fetch_assoc($result)) { ?> <tr> <td><?php echo $row['date_created']; ?></td> <td><?php echo $row['title']; ?></td> </tr> <?php } ?> </table> <?php include "footer.php"; ?>

Dần theo thời gian tuổi đời của ứng dụng nó khó có thể phát triển theo nhu cầu của khách hàng, khi cần được được phát triển toàn bộ. Cách tốt nhất dùng để cải tiến và chăm sóc một ứng dụng cho dễ dàng là chia cắt ngăn nấp cấu trúc của ứng dụng thành 3 tầng riêng lẻ. Mỗi tầng sẽ có một trách nhiệm riêng của nó ( và hầu hết các tệp tin đều nằm riêng lẽ ). - MODEL : Mô hình MD là một trong 3 lớp như vừa kể trên, nó có tác dụng đến thuộc tính của các tệp tin có nhiệm vụ thi hành một chức năng nào đó. Ứng dụng trên cho thấy cách thiết kế về dữ liệu Tin Tức. Do đó Mô hình MD tập trung một cánh lô ghíc lôi dữ liệu ra từ csdl cộng thêm chức năng cất giữ dữ liệu vào csdl. - VIEWS : Mô hình Views có nhiệm vụ liên kết với Mô hình Model và xuất các dữ liệu ra trình duyệt theo nhu cầu đòi hỏi của người tiêu dùng (user). Điển hình là các văn bản HTML. - CONTROLLER : Mô hình CT liên kết hai mô hình MD và Views cúng như kiểm soát chính xác các tệp tin trước khi cho tệp tin đó hiện thị ra trình duyệt. Zend Framework đáp ứng đầy đủ các đòi hỏi trên theo cấu trúc Model-View-Controller (MVC). ZF được sử dụng vào các phát triển theo nhu cầu nhiều phần và chức năng động để cải tiến và sửa chữa ứng dụng sau này. Nhu cầu cần thiết Zend Framework cần các điều kiện như sau: • PHP 5.1.4 (hoặc mới hơn) • Web-Server cho phép thao tác với mod_rewrite , nếu chưa kích hoạt bạn nên xóa # trước dòng rewrite_mode này. (tệp config này nằm trong hộp thoại Apache/config) Tải Zendframework : http://framework.zend.com/download/stable Cấu hình ứng dụng( chúng ta sắp làm) : theo trình bày của Zend trong Document chúng ta không cần một cấu hình căn bản nào cả, nhưng khi viết một ứng dụng chung ta cần một tổ chức mạch lạc cho cấu trúc hộp thoại.

và cho rằng chúng ta là một Admin của một host để có đủ quyền sửa chữa các tệp tin cần thiết. Bắt đầu tạo một cấu trúc với tên zf-tutorial trong Document Root của server. địa chỉ của Url sẽ là như vầy : http://localhost/zf-tutorial Tạo các hộp thoại sau như cấu hình này: Code:
zf-tutorial/ /application /controllers /models /views /filters /helpers /scripts /library /public /images /scripts /styles

Như bạn thấy chúng ta đã thiết lâp mô hìnheo kiểu MVC với cách thức chia cách mạch lạc, ngăn nắp .Các hộp thoại hình ảnh, Javascript và tệp Css đều nằm riêng và nằm trong cấu trúc của thư mục Public. Thư viện ZendFramework sau khi unzip ra chúng copy nó vào trong thư mục library/Zend.

Bootstrapping
Zend Framework (ZF) được thiết kế để hỗ trợ url “trong sáng”. Tức là mọi request đều tập trung vào 1 tập tin duy nhất là index.php, được biết đến như bootstrapper. Nó cung cấp cho chúng ta một hợp điểm duy nhất mọi trang của ứng dụng web và bảo đảm rằng môi trường được thiết lập đúng để chạy ứng dụng. Để thực hiên điều này chúng ta sẽ sử dụng khả năng rewriteurl của Apache bằng cách dung tập tin .htaccess trong thư mục zf-tutorial: zf-tutorial/.htaccess Code:
RewriteEngine on RewriteRule .* index.php php_flag magic_quotes_gpc off php_flag register_globals off

Rất đơn giản dung để đổi mọi request về tập tin index.php. Chúng ta cũng phải bảo đảm rằng magic_quotes_gpc và register_globals trong tập tin php.ini Tuy nhiên có những tập tin không cần rewriteurl như hình ảnh, css, JavaScript,… chúng ta sẽ đặt các tập tin này trong thư mục public và vô hiệu hóa rewriteurl đối với thư mục này bằng .htaccess zf-tutorial/public/.htaccess Code:

RewriteEngine off

Chúng cũng nên thêm .htacces vào các thư mục library và application để chống việc truy cập trực tiếp và ứng dụng không qua index.php. Code:
zf-tutorial/application/.htaccess deny from all zf-tutorial/library/.htaccess deny from all

Tập tin Bootstrapper: index.php
zf-tutorial/index.php là tập tin bootstrapper và chúng ta sẽ đầu với nó: zf-tutorial/index.php Code:
<?php error_reporting(E_ALL|E_STRICT); date_default_timezone_set('Europe/London'); set_include_path('.' . PATH_SEPARATOR . './library' . PATH_SEPARATOR . './application/models/' . PATH_SEPARATOR . get_include_path()); include "Zend/Loader.php"; Zend_Loader::loadClass('Zend_Controller_Front'); // setup controller $frontController = Zend_Controller_Front::getInstance(); $frontController->throwExceptions(true); $frontController->setControllerDirectory('./application/controllers'); // run! $frontController->dispatch();

Cần chú ý thêm nữa là không có ?> ở cuối file php. Chúng ta có thể bỏ nó đi trong những tập tin php chỉ chứa mã, không chứa php xen lẫn html (tập tin template). Điều này giúp ta tránh được lỗi header has sent khi sử dụng seesion do còn khoảng trắng phía sau?>. Chúng ta sẽ tìm hiểu từng dòng mã. Code:
error_reporting(E_ALL|E_STRICT); date_default_timezone_set('Europe/London');

Dòng đầu tiên là để thiết lập báo lỗi: hiển thị tất cả những lỗi mà ứng dụng gặp phải kể cả những lỗi không gây dừng ứng dụng (Notice, Warning, …) và cách viên mã không hợp lý có thể sẽ không tương thích với các phiên bản sau của php. Dòng thứ 2 là để thiết lập múi giờ của bạn, đây là yêu cầu của PHP5.1+. Code:
set_include_path('.' . PATH_SEPARATOR . './library' . PATH_SEPARATOR . './application/models/' . PATH_SEPARATOR . get_include_path()); include "Zend/Loader.php";

ZF được thiết kế mà các file của nó phải được include vào ứng dụng nên chúng ta phải thêm đường dẫn của thư mục library vào include path. Chúng cũng thêm thư mục models để sau này dễ dáng load các class model vào ứng dụng. Ngoài tập tin Zend/Loader.php cần được include thì những lớp khác của ZF có thể load một cách đơn giản bằng cách: Code:
Zend_Loader::loadClass('Zend_Controller_Front');

Dòng trên sẽ include tập tin trong Zend/Controller/Front.php có chứa lớp Zend_Controller_Front. Chúng ta cũng có thể sử dụng Zend_Loader inluce các thư viện của chúng ta. Lớp đầu tiên cần include của ZF là Zend_Controller_Front. Front Controller (FC) được sử dụng như một “bộ định tuyến” để hướng các request đến đúng các trang được yêu cầu. Chúng ta cần cấu hình FC để nó biết thực mục chứa controller của chúng ta. Tôi quyết định để cho FC “ném” (throw) mọi exception mắc phải. Mặc định thì chúng sẽ được “bắt” (catch) và giữ trong thuộc tính _exceptions của “đối tượng Response”. Đối tượng Response chứa thông tin về những dữ liệu trả về cho máy gửi request. Bao gồm HTTP header, nội dung trang, và exception. FC sẽ gửi HTTP header và nội dung trang trước khi nó kết thúc công việc của mình. Điều này giúp chúng ta dễ nhận ra các lỗi của ứng dụng và xử lý, và tất nhiên là một ứng dụng thật chạy trên server thì không nên để báo lỗi hiện ra (rất dễ bị hacker lợi dụng tấn công). Cuối chúng ta có “trái tim” của ứng dụng và chạy nó: Code:
// run! $frontController->dispatch();

Nếu bãn truy câp vào http://localhost/zf-tutorial/ để kiểm tra, bạn sẽ thấy báo lỗi tương tự như sau: Quote Fatal error: Uncaught exception 'Zend_Controller_Dispatcher_Exception' with message 'Invalid controller specified (index)' in… Chúng ta chưa thiết lập xong ứng dụng (các controller). Ứng Dụng Chúng ta chỉ xây dựng một ứng dụng nhỏ thôi. 1 ứng dụng lưu trữ các CD trong CSDL. Trang chính sẽ hiện thị 1 danh sách các dữ liệu CD và liên kết (links) để thêm, xóa v.v... Cụm từ CD và Album chỉ là biểu tượng liên đới với nhau mà thôi (1 CD bao gồm nhiều bài hát trong đó, được gọi là Album). Chúng ta thiết lập 1 csdl với 1 bảng chưa thông tin như sau: Code:
Feldname id Auto-Increment artist title Typ Integer Varchar(100) Varchar(100) Null? No No No Primary,

Cấu trúc trang (sites) - Homepage : hiển thị thông tin cộng thêm phần sửa, xóa, thêm. - thêm Album: tạo 1 form để thêm dữ liệu - Sửa Album: tạo 1 from để sửa dữ liệu - Xọa Album: tạo 1 form để xóa dữ liệu

Cơ cấu tổ chức của trang web Trước khi chúng ta thiết lập các trang web. chúng ta thử tìm hiểu cách thức tổ chức của thư viện ZF ra sao. Mỗi trang được xem như một tác động "Action" và Action này được tạo thành 1 nhóm (Groupe) thông qua hệ thống Controller. ví dụ: đường dẫn của url là http://localhost/zf-tutorial/news/view. thì news là hệ thống Controller và views là 1 Action. (Chú thích của của ng dịch : Ở đây chúng ta nên hiểu Action và Group đều là những thư mục chứa các tệp tin có các tác dụng của nó.) Chúng cho phép thiết lập nhóm (group) gồm nhiều tác động (Actions) có liên hệ với nhau.bên cạnh Action views, Controller "news" còn có thể có nhiều Action khác. ví dụ như Action current, archive ... Hệ thống MVC của ZF cho phép xây dựng Controller trong hệ thống modul. Tuy nhiên chúng ta dừng ở đây vì ứng dụng của chúng ta không đồ sộ lắm. Hoạt động Controller của ZF được xem như kiểu dựng sẵn trong đó Action Index là Action mặc định , nghĩa là khi 1 url như thế này http://localhost/zftutorial/news/ được gọi , thì Action Index của Controller news tự động kích hoạt (active). Tương tự Controller (standard Controller) trong framework cũng kích hoạt, nếu không có ấn định nào khác. theo chiêu thức " Ngạc nhiên nào cũng là Index". xem vd này, khi địa chỉ http://localhost/zftutorial/ được gọi lập tức Action index trong Controller Index sẽ được kích hoạt. Trong khuôn khổ của một tuto đơn giản chúng ta không nên đi sâu vô chi tiếc, xin hẹn đến diệp khác tròng những tuto kế tiếp. Chúng ta hiện có 4 trang web liên quan đến sự việc lưu dự trứ album trong csdl, do đó chúng ta tạo chúng thành một nhóm được xem như là nhóm Actions qua kiểm soát của Controller. Cách tốt nhất chúng ta nên sử dụng 1 Controller mặc định ( default Controller). Code:
Page Homepage Album thêm Album sửa Album xóa Controller Index Index Index Index Action Index Add Edit Delete

Đơn giản quá phải không? Thiết lập Controller Chúng ta đã có tất cả chung với nhau , để có thể thiết lập một Controller. Trong thư viện ZF, Controller là 1 lớp (class) nó phải có 1 tên như sau: {Name of Controller} Controller. Chú ý tên của 1 Controller đều bắt đầu 1 ký tự hoa (Lớn). tệp tin trong class này được ấn định như sau: {Name of Controller} Controller.php .cũng như đường dẫn (path) cũng phải được ấn định rõ ràng. Tên của 1 Controller được viết hoa các ký tự sau viết nhỏ. Mỗi Action là 1 phương thức của Controller được định nghĩa theo dạng Public, theo bản thảo sau {Name of Action} Action(). Tên của Action không được bắt đầu 1 ký tự lớn (phải viết nhỏ).

Tên của tệp tin IndexController được mặc định như thế này trong thư mục Controller : zftutorial/application/controllers/IndexController.php Code:
<?php class IndexController extends Zend_Controller_Action { function indexAction() { echo "<p>in IndexController::indexAction()</p>"; } function addAction() { echo "<p>in IndexController::addAction()</p>"; } function editAction() { echo "<p>in IndexController::editAction()</p>"; } function deleteAction() { echo "<p>in IndexController::deleteAction()</p>"; }

}

Xem như chúng ta đã thiết lập xong phần Controller. Tên tệp tin dẽ được gọi mỗi khi Action kích hoạt, chúng ta hãy thử các địa chỉ sau : URL output http://localhost/zf_tutorial/ in IndexController::indexAction() http://localhost/zf_tutorial/index/add in IndexController::addAction() http://localhost/zf_tutorial/index/edit in IndexController::editAction() http://localhost/zf_tutorial/index/delete in IndexController::deleteAction() Cho thấy ít nhất Default Routing đã hoạt động tốt.mọi Actions đều chỉ đến trang web ta muốn gọi.

You're Reading a Free Preview

Tải về
scribd
/*********** DO NOT ALTER ANYTHING BELOW THIS LINE ! ************/ var s_code=s.t();if(s_code)document.write(s_code)//-->