Form là cái gì đó rất thường gặp trên các website. Hình thức biểu mẫu có thể đơn giản như một mẫu điền chỉ có một trường duy nhất để nhập địa chỉ email, vài trường để khai báo thông tin về một người, một tổ chức cho đến phức tạp như một bảng biểu trông giống Excel.
1. Một ví dụ biểu mẫu đơn giản
Trước hết, tui giả sử bạn có một biểu mẫu (form) liên hệ trông xâu xấu tệ hại:
Đoạn mã HTML của form trên tui nên tự ngồi gõ lóc cóc để tạo ra, mặc dù khá mất thời gian, tẻ nhạt nhưng về lâu dài bạn sẽ thấy cực kỳ lợi hại vì bạn có thể không cần Google mà vẫn làm nên được những trang web ngon lành một tự tin.
Chúng tôi cung cấp sự tham khảo (vì ngay khi viết bài này, tui ngồi gõ lóc cóc, khác với hình minh họa trên, nhưng vẫn đảm bảo về mặt minh họa viết mã, cố tình làm vậy để bạn có dịp thực hành lại HTML bài form):
Khi người dùng bấm nút Submit để gửi thông tin từ một form, thông tin này sẽ đi về đâu? Nó sẽ được trình duyệt web gửi lên server, thông qua phương thức POST. POST được W3C định nghĩa trong tập giao thức HTTP và được các trình duyệt web tich hợp.
Vì ta đang học PHP, nên server-side script ở đây là PHP. Ở các ngôn ngữ khác như Python, Java, Ruby, C# cũng tương tự. Ngôn ngữ lập trình server-side sẽ được phần mềm web server tiếp nhận thông tin qua HTTP và chuyển đến đến dưới dạng input để xử lý với cách thức khá tương tự nhau.
Câu hỏi đặt ra ở đây là “tui đang ngồi ở server đây, có cả trăm, cả ngày người truy cập website và website có thể có nhiều form nhập thông tin, tui biết đâu vô đâu mà xử lý”. Câu hỏi thật thích đáng, cần trả lời ngay.
Dễ hiểu phải không nào? Khi bạn muốn gửi lên cho file nào xử lý, hãy điền tên của nó như là giá trị của thuộc tính action của FORM, ở đây, contact.php sẽ đảm nhận việc xử lý. Để đơn giản cho học ban đầu, file đặt ngay cùng thư mục với file HTML chứa form, chúng tôi giả sử đó là lien-he.html
2. Hình dung việc Submit form một cách hình ảnh
Ví dụ như form nhập liệu ta điền các thông tin như sau:
Khi click nút Send, những gì xảy ra ở hậu trường? Trình duyệt sẽ “đóng gói” các thông tin này lại theo quy chuẩn của định nghĩa trong HTTP 1.1 và gửi thông tin này lên web server (thông thường bạn gọi là hosting đó). Gói đó trông gì đó rất “lập trình” như sau:
KACBT không có ý định hù dọa bạn nhưng dính đến lập trình là gặp những thứ “mật mã Da Vinci” như trên rất bình thường. Tui cũng không định đi sâu phân tích kỹ thuật về cấp thấp của HTTP, cái đó dành cho những nhà nghiên cứu.
Đến đây, bạn và tui bắt đầu rút ra nhận xét như sau: những gì được thẻ INPUT của HTML mà có thuôc tính name là abcd gì đó khi có thông tin nó sẽ được gửi lên server trong cái chuỗi loằng ngoằng. Ví dụ ta thấy ở trên: username=KACBT&email=kacbt%40khoancatbetong.com và …
Thông tin có sự mã hóa chứ không hoàn toàn trông giống những gì nhập vào. Cụ thể ở ví dụ trên, dáu @ đã biến thành %40 nào đó. Nội dung tiếng Việt có dấu nhập vào đã được mã hóa ra một chuỗi “hoàn toàn tậm tịt”. Không lo, khi xử lý trên server, khi viết mã PHP, bạn vẫn lưu trữ và hiển thị đúng, người dùng đọc được, vậy là ổn.
Mặc dù thẻ FORM có thuộc tính name=”contact” nhưng cái này hoàn toàn vô tác dụng khi Submit form, không có thông tin nào liên quan đến cái này đuọc gửi lên server. Do vậy, thuộc tính này của FORM bạn có thể loại bỏ mà không ảnh hưởng gì.
Đến đây, tui hoàn toàn té ngửa ra rằng hóa ra lâu nay tụi nào đó toàn chém gió nào là lập trình web gồm frontend, backend, fullstack nghe kêu loảng xoảng đến kinh người. Thực ra, mọi thứ khá đơn giản, dễ hiểu mà thôi. Đó là trình duyệt sẽ gói các thông tin ở những trường dữ liệu để gửi lên server, và server nhận được phản hồi lại. Nghe quen không? Có khác gì bạn mua hàng, shipper mang đến?
Những việc nào mà làm ở trình duyệt, đó gọi là client, khi lập trình thì gọi là frontend, còn những việc mà xử lý ở trên server, việc lập trình liên quan đến mớ đó gọi là backend.
3. Bóc tách các trường để xử lý
Ở phía server, PHP sẽ “đón lõng” được thông tin chứa trong một mảng $_POST, các phần tử mảng tương ứng với thuộc tính name ở HTML. Vì sao là $_POST? Vì đó là định nghĩa của ngôn ngữ lập trình PHP, ở chương Predefined Variables (những biến được định nghĩa trước/ sẵn).
Truy cập vào mảng $_POST như bất cứ mảng nào bạn biết. Mảng $_POST là dạng mảng có index là các chuỗi thay vì sử dụng các con số. Cái này, trong PHP người ta gọi là associative array.
Với hình minh họa ở trên, bạn đã chắc chắn hiểu những name ở HTML đã biến thành chỉ số của mảng $_POST khi gửi lên server. Còn chần chừ gì nữa tui không gõ tạo ngay một file contact.php với nội dung:
Chú ý: PHP có lúc phân biệt chữ thường, HOA, lúc lại không. Vì vậy, bạn cứ xem nó là ngôn ngữ có sự phân biệt thường/ HOA cho an toàn.
Quay lại với trang chứa form của bạn, giả sử nó là lien-he.html (tùy bạn đặt tên file, vì khi học PHP bạn đã nắm khá tốt về bộ 3 HTML + CSS + JavaScript, nếu chưa, hãy học ngay và luôn) điền form và bấm nút Submit. Kết quả:
Giờ đây, bạn đã biết cách lấy thông tin từ client gửi lên rồi. Xử lý nó như thế nào là việc của bạn. Trong thực tế, người ta thường lưu giữ xuống file hoặc vào cơ sở dữ liệu để dùng về sau. Cũng có những thông tin cần tính toán rồi gửi lại cho client hiển thị, hoặc lưu vào database để hiển thị về sau.
4. Mở rộng thêm một chút về form
Giờ giả sử bạn đang theo một trend rất đáng kinh ngạc (có thể tui đang tự nghĩ ra, mà bạn không biết) rằng thay vì lên làm các ứng dụng hẹn hò, tui đang áp dụng việc học lập trình web để tạo ra một cái như là landing page để nhận thông tin về các “đối tác tiềm năng”. Vậy, giờ đây HTML của FORM được sửa thành:
Nhìn ngay vô ta thấy rằng bây giờ thẻ FORM đã có thêm thuộc tính enctype. Giá trị thuộc tính như trên là vì chúng ta có trường Ảnh chân dung name=”photo” và type=”file” dùng để upload file.
Nếu chúng ta không đặt enctype=”multipart/form-data” thì PHP không bắt được file tải lên.
Sửa file contact.php để có thể tiếp nhận file upload lên:
Đây chỉ là bài cơ bản nên chưa bàn đến việc kiểm tra sự tồn tại dữ liệu của các trường, có nhập đủ thông tin và quy cách hay không, nên giả sử các trường là được nhập đầy đủ, hợp lệ, không bỏ trống trường nào. Trường Ảnh chân dung thì khi browser file để tải lên, cần chọn đích xác một file hình ảnh. Trong khi viết bài này tui dùng ảnh chân dung ai đó càng tốt để tránh khi nhìn thấy hình ảnh này vài lần bạn tự làm rối trí/ gây kích động/ buồn cười, xao nhãng việc học viết mã PHP.
Tui cũng khoan canh chừng các thứ liên quan bảo mật. Nên cứ tạm cho rằng thông tin văn bản nhập vào không có chứa mấy thứ mã nguy hại, file upload lên là file hình ảnh mà không phải là file nào khác, kích thước file cũng vài trăm KB để tốc độ đươc nhanh, không dùng ảnh cả chục MB, có khả năng upload thất bại hoặc ngồi đợi chán chê. Tên file hình ảnh tui cũng không đặt rối rắm, ký tự đặc biệt làm gì, chỉ cần tên file chan-dung.jpg là ổn.
Tuy vậy, ta cũng đã bắt đầu quan tâm xử lý trường dữ liệu là số, tránh trường hợp người dùng gửi lên không phải con số sẽ khiến dữ liệu thành… rác. Cụ thể: gọi hàm intva() (dòng 5, 6 trên hình) để kiểm tra trường tuổi, chiều cao, cân nặng.
Về sau, khi tui đã vứng về ngôn ngữ PHP, tui phải áp dụng những cái gọi là “kiểm tra dữ liệu đầu vào” (validate and sanitize user input), nếu làm biếng thực hiện, chỉ vài ngày sau có thể website trở thành ổ chứa mã độc hoặc dữ liệu bị đánh cắp.
Ở dòng 10, tui cảm thây giờ bắt đầu phức tạp hơn lên rồi. Hình ảnh được upload lên không được PHP sử dụng trong mảng $_POST mà trong mảng $_FILES.
Cứ học nằm lòng mà không biện luận lôi thôi gì về mảng $_FILES. Khi mà ở INPUT đặt thuộc tính name=”abcd” như thế nào thì PHP sẽ truy cập nó như này:
$FILES['abcd']['name']
Trong mã HTML đang thực hành, ta đặt name=”photo”, tất nhiên, ta có đoạn code dòng 10:
$file_name = basename($_FILES['photo']['name']);
Nghĩa là cái [‘name’] ngay sau $_FILES[‘tên-do-ta-đặt-ở-name-ở-HTML’] là luôn cố định, không thay đổi được, PHP quy định vậy. Dòng code trên có ý nghĩa: gán tên của file vừa upload lên vào biến $file_name, ta có dùng hàm basename() là để đề phòng việc có kèm theo đường dẫn gì đó, ta chỉ lấy tên file mà thôi.
Tương tự như vậy, dòng 11:
move_uploaded_file( $_FILES['photo']['tmp_name'], __DIR__ . '/' . $file_name);
Cái [‘tmp_name’] luôn đi theo sau như vậy, do PHP quy định, ta không thể thay đổi bằng cái gì khác. Để hiểukỹ hơn tui giải thích như sau: khi 1 file được upload (tải lên) server, nó được chứa trong thư mục tạm của hệ điều hành. Nếu file để nằm ở đó, rõ ràng là không có thể sử dụng về sau, hệ điều hành sẽ xóa mất.
Vì thế cho nên, tui dùng hàm move_uploaded_file() để di chuyển nó (file vừa tải lên) vô thư mục cần chứa. Cũng đơn giản hóa, tui di chuyển nó vô ngay thư mục đang chứa file lien-he.html, contact.php luôn. Cái __DIR__ ý nghĩa là thư mục hiện thời của cái script contact.php đang chạy, cộng thêm dấu chém tới, tên file nữa thì mới lưu được. Đó là do tham số yêu cầu phải có của hàm move_uploaded_file()
Bạn đã điền và Submit (bấm nút Send) lại biểu mẫu hẹn hò này chưa? Có thấy được kết quả không nào? Cho đến đây, bạn nắm tương đối cơ bản về việc tạo form, gửi form và xử lý đơn giản là gán vào biến và hiển thị nó lên màn hình.
5. Lưu trữ thông tin có được từ form
Giả sử bạn mới học PHP được chừng một tuần. Bạn là một học sinh năng động, mới vừa nhập học vào lớp 10. Môi trường mới, bạn mới, thầy cô mới, bạn đang muốn thành lập một câu lạc bộ cờ tướng/ văn nghệ/ khoa học,… chẳng hạn. Chần chừ gì nữa mà không làm ngay một trang web để các bạn khác ghi danh tham gia cùng. Nào, làm thì làm.
Mở ngay một file dang-ky-thanh-vien.html trông cũng xấu xí, lòe loẹt:
Mã HTML của FORM ngay bên dưới (chỉ có HTML, CSS là phần bạn tự làm để đẹp theo ý bạn):
Bạn để ý thuộc tính action=”cái-gì-đó” có giá trị cho khớp với file PHP của bạn, đừng có bắt chước một trăm phần trăm contact2.php như trên. Làm vậy, bạn có vẻ là không hiểu bài, để rồi mã không chạy được lại đổ thừa là tui viết code tào lao nữa là tui… khóc thét.
5.1. Lưu thông tin xuống file, dạng file CSV
File định dạng CSV được dùng khá thông dụng, có thể mở xem bằng trình soạn văn bản thô và phần mềm Microsoft Excel, Google Sheets hoặc phần mềm bản tính tương tự.
Bên file PHP của bạn (tên file là gì, tự tạo nhé), nội dung:
Dĩ nhiên đoạn mở đầu phần HEAD của HTML bạn tự viết. Đoạn kết thúc cũng tự viết. Tui mặc định rằng kiến thức cơ bản về HTML + CSS + JavaScript bạn đã nắm.
Giờ đây, theo như hình trên, đặt con trỏ text ở dòng 24, enter ở dòng, lúc này con trỏ nằm dòng 25, gõ các dòng, và sửa để gần giống:
Quay lại file đăng ký của bạn điền thông tin, bấm Đăng ký ngay để xem kết quả gần gần giống:
5.2. Lưu thông tin vào cơ sở dữ liệu MySQL hoặc MariaDB
Điên rồ hơn nữa, trên web hosting bạn đang thuê thì 99% khả năng có trang bị cái cơ sở dữ liệu MySQL. Tui nghe phong thanh nó dùng để lưu trữ dữ liệu, nó thường đi với PHP như hình với bóng. Mặc dù rất là niu-bai (newbie/ novice) nên tui cũng chẳng dại gì mà giới hạn bản thân, lưu luôn vào CSDL xem sao.
Mức newbie, tui không đòi hỏi bạn biết nhiều. Bạn chỉ cần biết sử dụng phpMyAdmin để tạo được một CSDL đơn giản, có vài table tự tay làm ra hoặc import dữ liệ mẫu ở đâu đó.
Đến đây, tui hình dung phần nào việc lưu dữ liệu vào cơ sở dữ liệu(viết tắt: CSDL) là như nào. Tui cũng bắt đầu biết đến một đại diện trong nhóm cơ sở dữ liệu quan hệ (relational database)) là MySQL hoặc MariaDB. Nhưng để trở thành lập trình viên gọi là biết làm việc được tốt với CSDL hẳn tui cũng phải đầu tư vài trăm giờ để có mức hiểu biết căn bản.
6. Áp dụng kiến thức để làm form đăng nhập
Giờ đây, chúng ta thử bắt tay vào làm một ứng dụng nho nhỏ với nhiệm vụ xác thực người dùng. Form đăng nhập là cái gì đó vẫn đang còn rất thông dụng hữu ích. Dù bạn dễ dàng copy & paste được mã nguồn PHP ở đâu đó nhưng chúng ta đang học, bắt tay làm để hiểu, làm để học, đừng vội xem ở đâu đó và mượn, điều đó không giúp bạn tiến bộ.
Đầu tiên, ta phải thiết kế FORM. Nghe từ “thiết kế” rất gớm ghiếc, nhưng nó là từ đúng, cần dùng ở đây. Tuy khá đơn giản nhưng không hoàn toàn dễ dàng cho người mới học PHP.
7. Bài tập thực hành
Như thông lệ, để nắm chắc bài, tui phải thực hành ít nhất thêm 3 bài khác, đó là một thói quen không rõ tốt hay xấu, chỉ biết nó mất khá nhiều thời gian, nó biến tui thành một gã được nhìn nhận như là “cần cù bù thông minh”. Bạn cũng nên như vậy, về lâu dài, cần cù cũng giúp tăng IQ đó.