Thực chiến cờ rút ngay trên bài hướng dẫn

Cờ rút ở đây là nói tếu táo vui vẻ của CRUD. Bài này nói về việc nhập dữ liệu và hiển thị thông qua một ứng dụng PHP kiểu trà sữa nhà làm. Một bạn học viên cũ của chúng tôi gửi và chúng tôi muốn “ủn đít” anh ấy đi tiếp trên con đường trở thành một người có thể kiếm cơm với lập trình web PHP.

1. Đề bài như thế nào?

Ta tạm gọi một file HTML có giao diện xanh lá mạ như sau là “phờ rông eng”, còn nó nghĩa là gì bạn tự tìm hiểu. Trông như này:

Hình 1. Giao diện HTML front-end của quản lý vi phạm của học sinh

Để đơn giản về “nghiệp vụ” chúng ta có thể mô tả phần mềm này ở mức đơn giản nhất với lời văn mà bất kỳ học sinh nào học xong tiểu học đều có thể mô tả lại. Nó sẽ gần như này:

Em là sao đỏ, được phân công làm cảnh sát lớp học. Mỗi buổi học, nếu có bạn nào trong lớp vi phạm em sẽ đưa các vi phạm này vào một danh sách. Cuối tuần, tổng kết lại ra các vi phạm để xếp loại các bạn.

Như vậy, chúng ta sẽ nhìn qua có các thông tin cần quản lý đó là học sinh và vi phạm. Những lỗi vi phạm là đã được định nghĩa trước, danh sách học sinh cũng như vậy. Lỗi vi phạm được tinh theo ngày, tức là sẽ có những lỗi ngày hôm đó chỉ có thể tính là một lần mà thôi. Có những cái tuy nằm trong “vi phạm” nhưng lại là tích cực, ví dụ như việc phát biểu.

Đến đây, chúng ta lờ mờ hiểu rằng như vậy đặt lên bàn cân, một vi phạm có một “giá tiền” (trọng số) của nó. Vậy là ta sẽ lập một bảng định nghĩa các vi phạm và giá của nó.

2. Giải quyết bài toán theo kiểu thợ vặt lông gà

Chúng ta cứ tiến hành vặt từng cọng lông gà như thợ vậy. Khi quan sát bạn thấy không phải lúc nào cũng vặt từng lông, cũng không phải lúc nào vặt từng mảng lông mà phải có sự linh động.

2.1. Thử “thiết kế” cơ sở dữ liệu của dân chưa từng học môn CSDL

Anh chàng học viên này gửi cho chúng tôi các thứ mà chúng tôi khuyến khích anh ấy tự nghĩ ra theo một cách nào đó các thông tin cân quản lý:

Một table trong phpMyAdmin cũng “ra gì” làm đấy

Tiếp theo là cái gì đó dạng bảng tablular trông không rõ là Word hay Excel:

Có vẻ HTML hơn là Word, Excel nhỉ?

Vân chưa hết, còn có một cái bảng biểu nữa:

Hóa ra lại là form tìm kiếm

Đoạn này gợi chúng tôi nhớ lại những ngày mài đũng quần với môn Lập trình Pascal, sau đó là đến C để cài đặt các giải thuật tìm kiếm, sắp xếp. Hóa ra, những cái như vậy thật là nền tảng, căn bản, dùng rất nhiêu trong thực tế công việc của dân lập trình.

Đó là chưa kể, bằng cách thân thánh nào đó mà TR và CH lại có thể nhầm lẫn với nhau, điều này càng giúp chúng tôi nhớ lại thuở học trò, lớp chúng tôi có những bạn không nói rõ được TR và CH nên mỗi lần nói chuyện mà có dính đến thì “Thằng Chung đó là chờ Che hay chờ Chó” (chết thật, ý là thằng này tên nó là Trung hay Chung đấy các bạn ạ).

Lần này chốn nào anh đã trốn học?

2.2. Chuyển những thứ trên thành table trong MySQL

Tất nhiên, ở đây hướng dẫn học PHP với mức độ nghiệp dư, chúng tôi có thể hướng dẫn ở mức chuyên nghiệp hơn nhưng nếu vậy thì bạn nên tới giảng đường “kem bớt” (campus) . Đừng vô đây đòi hỏi chúng tôi phải thiết kế ra được cơ sở dữ liệu chuẩn chỉnh về quan hệ, đạt đươc chuẩn BC, 1NF, 2NF, 3NF gì đó nhé.

Tất nhiên ở đoạn này chúng tôi khuyến khích những người tự học biết chút ít về ngôn ngữ SQL, cụ thể là biết ANSI SQL là cái quái gì, rồi viết được một số câu lệnh SQL trên một DBMS cụ thể là MySQL.

Nào, mở phpMyAdmin lên và làm ngay và luôn:

2.2.1. Table hocsinh

Tạo table hocsinh

Tất nhiên, truóc đó bạn phải tạo một CSDL rỗng để có thể tạo table hocsinh. Với các trường dữ liệu sau:

Dữ liệu mẫu về học sinh để mồi ban đầu

Những ai thích nghiền ngẫm vấn đề ở mã hơn là dùng GUI, chúng tôi cũng cung cấp SQL để sử dụng ngay, trong phpMyAdmin cũng dễ dàng copy & paste đoạn mã:

CREATE TABLE `hocsinh` (
  `id` int(10) UNSIGNED NOT NULL,
  `hoten` varchar(40) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL,
  `lop` varchar(5) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;

ALTER TABLE `hocsinh` ADD PRIMARY KEY (`id`);

Nếu bạn là một người học có suy nghĩ, tìm tòi, dựa trên SQL bên trên và các table dạng trực quan, bạn có thể tạo thêm field (hoặc column tùy văn cảnh) chứa thông tin về học sinh mà bạn cần quản lý.

Giờ đây, tương tự, ta sẽ tạo một table định nghĩa các vi phạm để có thể căn cứ vào đó mà “bắt lỗi” học sinh để rồi đưa ra biện pháp thưởng/ phạt nào đó.

2.2.2. Table vipham chứa thông tin vi phạm

Table này có 3 cột: id, tên lỗi và điểm. Khi nhập dữ liệu “chim mồi” ban đầu, trông như sau:

Table vipham gồm có tenloi (tên lỗi) và diem (điểm)

Đoạn mã SQL để bạn có thể copy v& paste trong phpMyAdmin sẽ chính là:

CREATE TABLE `vipham` (
  `id` int(10) UNSIGNED NOT NULL,
  `tenloi` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL,
  `diem` int(5) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;

ALTER TABLE `vipham` ADD PRIMARY KEY (`id`);

Đến đây ta đã có 2 bảng table dữ liệu cơ bản để có thể ghi nhận học sinh nào vi phạm ra sao. Tuy nhiên, để có thể lưu trữ lịch sử vi phạm ta sẽ tạo ra thêm một table nữa, tạm gọi nó là chamdiem (chấm điểm).

2.2.3. Table chamdiem

Table này thực ra là ta sẽ map thông tin từ 2 table kia. Nếu bạn có học môn Thiết kế CSDL quan hệ, bạn sẽ dễ dàng hiểu được điều này. Không sao, giờ đây bạn cứ làm theo như con vẹt cũng khiến chúng tôi vui phát khóc lên rồi. Nào, table trông như sau:

Bảng chamdiem với vài dữ liệu mồi. Bạn tự tra xem học sinh nào vi phạm gì nhé?

Tương tự, table chamdiem có mã SQL để tạo ra nó là như này:

CREATE TABLE `chamdiem` (
  `id` int(10) UNSIGNED NOT NULL,
  `ngay` date NOT NULL,
  `hocsinh_id` int(10) UNSIGNED NOT NULL,
  `vipham_id` int(10) UNSIGNED NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;

ALTER TABLE `chamdiem` ADD PRIMARY KEY (`id`);

Đến đây, ta tạm có một cơ sở dữ liệu, KACBT gọi là kyluat đi nhé. Bạn đặt tên gì là tùy bạn.

Phần này nâng cao, bạn có thể bỏ qua

Mở rộng: nếu bạn thuộc loại thích cái khó, nhưng làm chủ được việc học tiếp cận bài bản, bạn có thể sử dụng cơ chế dòng lệnh để nhập những phát biểu SQL trên để tạo table. Gợi ý: vào Terminal và gõ:

mysql -uroot -p

Khi xuất hiện dấu nhắc của cửa sổ lệnh của MySQL bạn có thể tạo cơ sở dữ liệu với lệnh:

CREATE DATABASE kyluat;
USE kyluat;

Sau 2 dòng trên, bạn tiếp tục gõ các lệnh SQL tạo 3 table đã kể ở trên. Đến đây bạn có thể hiểu rằng thực ra khi thao tác trên phpMyAdmin, thực chất phần mềm này thay mặt bạn gõ những lệnh mà chúng ta vừa làm ở đây.

2.3. Quay về với viết phần mềm, sửa mã HTML, PHP

Giờ đây, giả sử bạn dùng XAMPP, vậy thì vào bên trong thư mục chứa phần mềm của bạn, ví dụ như đặt trong thư mục C:\xampp\htdocs\kyluat nhé, ta sẽ dùng file HTML ở Hình 1 đầu bạn để copy ra thành 1 file ta đặt tên là frontend.php được không nào.

Enter cho dòng DOCTYPE rớt xuống, chèn những dòng sau vào đầu file:

Đoạn mã PHP kết nối vào dữ liệu để lấy danh sách học sinh

Đến đây, nếu có học chút ít về PHP, bạn đã nhìn thấy rằng biến $chuoi_option đã chứa danh sách học sinh, nó là một đoạn mã HTML để có thể dùng làm “ruột” cho thẻ SELECT, thay cho phần nội dung đang được “code cứng” vào file ban đầu.

Giờ đây, ta tìm đoạn mã HTML được code cứng, nó đang là:

Vùng khoanh đỏ là danh sách học sinh, đang dùng HTML tĩnh

Thay vùng khoanh đỏ ở hình trên bằng đoạn mã HTML sau:

<?php echo $chuoi_option; ?>

Giờ đây, đoạn mã trên đã trở thành:

HTML tĩnh đã được thay bằng PHP động để nạp danh sách học sinh

Save file, quay về trinh duyệt, bấm F5, kết quả:

Giờ là các học sinh trong Cơ sở dữ liệu được lấy ra, nạp vào trang web

Tương tự như danh sách học sinh, chúng ta cũng lấy danh sách vi phạm từ cơ sở dữ liệu để thay vào danh sách HTML tĩnh đang có. Trước tiên, nhìn ngó qua đoạn mã HTML gốc ban đầu:

Những dòng HTML tĩnh sẽ được thay bằng PHP động (1)

Mang con trỏ text quay trở lại phần viết mã PHP ban đầu, ngay trước closing tag of a block of PHP code để gõ những dòng:

Đoạn mã lấy vi phạm từ CSDL và tạo thành thẻ HTML

Phỏng theo đoạn lấy dữ liệu học sinh bên trên, nếu bạn là ngươi “học một biết hai” bạn nhanh chóng làm bước tiếp theo đó là quay lại đoạn mã HTML ở hình (1) bên bên, sửa nó thành:

Các vi phạm giờ đây lấy từ CSDL ra, không phải HTML tĩnh

Một “thực hành tốt” mà chúng tôi suýt nữa thì quên đó là khi sử dụng CSDL xong, bạn nên đóng kết nối để giải phóng tài nguyên. Mặc dù việc PHP chạy xong thì tự nó cũng kết thúc kết nối, nhưng trong trường hợp website trở nên lớn, nhiều kết nối, có thể làm cho nặng tải server vì lý do cấu hình mặc định hoặc có thể sai sót đâu đó. Vì vậy, đóng CSDL với dòng sau:

$ketnoi->close();
?>

Nhìn đoạn trên, bạn cũng biết đặt mã đó vào ở đâu trong file PHP frontend.php đang thực hiện rồi phải không nào?

Xin phép được lan man tí xíu

Từ đâu đến giờ, chúng ta mới chỉ làm được một việc là R trong CRUD mà thôi. Nếu bạn vẫn chưa rõ CRUD là gì, lúc này là lúc cần biết, nhớ: CRUD là viết tắt của Create, Read, Update, Delete. Đây là 4 thao tác thường làm đối với dữ liệu. Hầu hết trong mọi phân mềm có liên quan đến cơ sở dữ liệu đều sử dụng đến CRUD.

Create chúng ta làm trên phpMyAdmin hoặc cơ chế dòng lệnh. Nhưng đó là trong bối cảnh bạn đang là lập trình viên, tuy có nghiệp dư đi nữa cũng phải hiểu rằng người tạo ra phần mềm cho người khác dùng sẽ khác với người chỉ dùng phần mềm.

Trong thực tế, phần mêm của bạn phải tích hợp chức năng để nhập liệu, người dùng phần mềm bình thường không sử dụng các công cụ của người lập trình. Do đó, phần tiếp theo đây, chúng ta sẽ phải đi qua chút ít về việc nhập dữ liệu.

Khi bạn dùng phân mềm trên web, giao diện tiếng Việt có thể làm bạn đã rất quen với Xem, Thêm, Sửa, Xóa. Đây chính là CRUD đấy. Chỉ là phần mềm đôi lúc gộp lại thành ra bạn không thấy rõ, nhất là Create và Read được gộp chung trên một giao diện, Sửa và Xóa trên cùng giao diện hoặc có khi việc thêm được tạo ra bằng cách nhân bản Copy một cái đang có và sửa chút ít rồi lưu lại.

2.4. Phần nhập liệu cho phần mềm

Phần này có thể nói là chức năng dành cho Admin. Việc tạo Admin Dashboard, quản lý người dùng, phân quyền này nọ khá nhiêu khê nằm ngoài phạm vi bài viết này nên chúng tôi sẽ đưa vào loạt bài hướng dẫn lập trình web với PHP.

Ở đây, chúng tôi làm thô sơ nhất để bạn có thể hình dung việc nhập dữ liệu khi tương tác giữa front-end và back-end ra sao, và cũng không dùng kỹ thuật Ajax hoặc tương tác API hiện đại mà cách truyền thống, mục đích giúp học viên của chúng tôi nắm được nền tảng luồng dữ liệu.

Chúng tôi cũng không valid dữ liệu đầu vào để mã PHP viết đươc ngắn gọn, dễ hiểu. Nhưng nếu trong thực tế bạn viết phần mềm web để dùng được, bạn cần phải chú trọng vào việc kiểm tra dữ liệu người dùng nhập vào xem có hợp quy cách hay không. Việc này rất quan trọng bởi 2 lẽ:

1) Liên quan vấn đề bảo mật, tránh chèn mã độc hoặc những thứ có thể khai thác thông tin không được phép truy cập từ website của bạn.

2) Dữ liệu nhập vào nếu không được kiểm tra đầy đủ tính hợp lệ (chưa nói đến nội dung có chuẩn chỉnh về chính tả, chính xác về thông tin đầu vào hay không) có thể khiến cho phần mêm của bạn trở thành thứ vô dụng bởi vì nó trở thành một bãi rác, chứa toàn thông tin sai lạc, gây nhầm lân, vô dụng. Một ví dụ cụ thể: ngày tháng năm mà lẫn lộn tháng với ngày là xem như khỏi “chúc mừng sinh nhật”, những trường buộc phải có thông tin như số điện thoại mà nhập thiếu số thì khỏi gọi.

2.4.1. Thực hiện chữ C trong CRUD, tức Create

Nào, tạo một thư mục admin bên trong thư mục kyluat, vào bên trong thư mục admin này tạo một file ketnoi.php với nội dung:

File này để include vào các file CRUD khác, tránh copy & paste lại code nhiều lần vô ích

File ketnoi.php này để dùng chung cho việc kết nối dữ liệu chung cho các file CRUD liên quan đến học sinh, vi phạm và ngay cả chấm điểm.

Tiếp tục, tạo file hocsinh-create.php :

Phần mã PHP phụ trách việc lưu thông tin học sinh

Cũng trong file hocsinh-create.php này ta phải có phần HTML để làm FORM nhập liệu:

Mã HTML để tạo form nhập liệu đơn giản với 2 trường họ tên, lớp

Nếu bạn làm không có sai sót, khi truy cập http://localhost/kyluat/admin/hocsinh-create.php sẽ thấy:

Form khi xem trên trình duyệt

Bạn thử nhật một học sinh và bâm nút Lưu thông tin để tạo một học sinh mới. Sau đó mở phpMyAdmin, duyệt đến table hocsinh xem thử có thêm học sinh không? Hoặc bạn có thể quay về trang frontend.php ban đầu, bấm F5 sẽ thấy xuất hiện học sinh trong danh sách.

2.4.2. Read/ Retrieve đã có sẵn nhưng ở front-end, giờ đây thực hiện ở backend

Cách nhanh nhất là bạn tạo một bản sao của hocsinh-create.php và đổi tên nó thành hocsinh-read.php, rồi sửa sao đó để nội dung nó như này:

Phần mã PHP đọc dữ liệu tạo thành table, trông quen?

Tất nhiên, bạn cũng có phần mã HTML để table kia có thể hiện ra màn hình:

Mã HTML để dữ liệu hiện lên giao diện web

Xem như giải quyết được CR trong chữ CRUD. Tiiếp tục giải quyết 2 chữ UD còn lại. Giờ đây nếu bạn vẫn còn tỉnh táo đọc bài này chú tâm, bắt đầu bạn nhận ra… cập nhật sẽ phải có sự kết hợp giữa FORM của Create và hiển thị thông tin của Read. Nào, chần chừ gì, lên đường.

2.4.3. Update (còn gọi là Edit) thực chất là mông má cho em nó

Lại tạo một file hocsinh-update.php để thực hiện việc cập nhật. Nội dung PHP đáng sợ:

Phần mã PHP kiểm tra xem phương thức POST, GET để thực hiẹn hành động tương ứng.

Tiếp nối đoạn mã PHP trên, lại cũng PHP:

Đoạn này cơ bản giống với phần Read

Đến đoạn mã HTML để có thể hiển thị được giao diện lên màn hình:

Code PHP cập nhật Học sinh
Chỉ có phần BODY, vì phần HEAD giống với các file khác

Thử chạy trên trình duyệt và sửa một học sinh trong danh sách để xem code có chạy? Nếu gặp lỗi, không cần phải nói nhiều, bạn cần phải vào Thảo luận để trao đổi nhằm hiểu rõ, hiểu sâu bài.

2.4.4. Delete (xóa) – chữ D cuối cùng của CRUD

Xóa là việc làm nguy hiểm nên dù có tối giản đến mức nào bạn cũng nên có việc xác nhận lại thực sự muốn xóa dữ liệu hay không. Hoặc bạn phải tạo cơ chế “thùng rác” để nếu có sơ sót thì còn có thể phục hồi.

Ở đây, chúng tôi sẽ dành cơ chế sọt rác cho những bạn có khả năng làm bài tập mở rộng/ nâng cao. Đoạn này chỉ đề cập đến việc hỏi lại trước khi xóa.

Mã PHP lấy danh sách và kiểm tra điều kiện xóa
Mã PHP xóa học sinh tếp theo
Mã PHP để chuẩn bị table xuất ra màn hình

Giờ đến mã HTML có nhúng chút ít PHP để có thể hiển thị danh sách kèm chức năng xóa:

Mã HTML danh sách học sinh xóa
Mã HTML hiện danh sách học sinh, có cột chức năng xóa.

Cơ bản chức năng CRUD đã hoàn thành, nói theo kiểu trên tivi “cơ bản hoàn thành”. Để hoàn chỉnh bài này, như KACBT đã nói ở trên rằng bạn còn rất nhiều việc để làm, việc “xây thô” và hoàn thiện một căn nhà thế nào, một ứng dụng web cũng giống như vậy.

Chúng tôi nhận thấy kha khá các bạn sinh viên tốt nghiệp ra trường không xin được việc bởi vì họ cũng chỉ mới làm đến mức như nãy giờ chúng ta bợt bạt. Tui mà là nhà tuyển dụng, tui đuổi ứng viên về luôn chứ không có tuyển vào đào tạo cho tốn cơm.

2.5. Một thứ quan trọng: chấm điểm học sinh

Đây có thể nói rằng đầu bài đã đặt ra nhưng lúc đó còn để dở dang, hơn nữa ở frontend chủ yếu là để xem chứ không nên có chức năng chỉnh sửa. Giờ đây, giả sử là một sao đỏ sử dụng phần mềm, chúng ta sẽ phải bê cái giao diện màn hình ban đầu vào phần backend. Copy file đó vào thư mục admin, đổi tên nó thành chamdiem.php và mông má nội dung thành:

Thuộc tính name của input
Thêm thuộc tính name để có thể submit giá trị lên server

Cũng đọc lướt qua file HTML ta sớm nhận ra rằng chưa có thẻ FORM nên bấm nút Submit không có tác dụng. Vì vậy, ta sẽ thêm thẻ FORM bằng cách bọc thẻ FORM bên ngoài các thẻ INPUT, nhìn một lượt, ta chỉ có thể đặt thẻ FORM ngay sau BODY:

Thẻ form bọc ngoài các input
Thẻ FORM đặt ở vị trí ngay sau BODY

Bạn nhớ xuống cuối file HTML, trước thẻ BODY để đóng thẻ FORM này lại, việc quên đóng thẻ có thể làm cho chương trình không thể hoạt động hoặc gây lỗi.

Tương tự như lỗi vi phạm cần có thuộc tính name để có thể submit giá trị lên server như vừa mơi làm ở trên thì để biết học sinh nào được chọn, bạn cũng phải có thuộc tính name:

Thuộc tính name cho học sinh
Thuộc tính name không thể thiếu

Giờ đây, hãy quay về đầu file chamdiem.php thêm nội dung:

Kiếm tra POST có hoạt động
Kiểm tra xem POST hoạt động?

Bấm F5 và chọn một học sinh trong danh sách, tick vào vài lỗi vi phạm và bấm nút Tính tổng vi phạm để xem, nếu bạn thấy:

Submit lên kiểm tra

là đang hoạt động đúng như mong đợi. Nếu không thấy, bạn cần kiểm tra lại mã HTML cho chuẩn chỉnh ở các thuộc tính name.

Khoan, vẫn chưa ổn đâu nếu bạn tỉnh táo sẽ phải hiện “Ngày tháng đâu sao không thấy?“. Một câu hỏi cực kỳ xịn sò khi bạn là người học rất chủ động, cẩn thận. Vậy, ta cũng phải xử lý ngay việc ngày tháng:

Input date để lưu giá trị ngày tháng
Thuộc tính name ngayphat (ngày phạt) để có thể submit ngày tháng

Nghe có vẻ ổn? Ấy vậy, giờ thử bấm các nút mà xem. Ô hay, hóa ra nút nào cũng submit hết. Vậy làm sao phân biệt được nút nào vừa được bấm để viết mã PHP xử lý tương ứng. Có vài cách xử lý khác nhau, chúng tôi chọn cách đơn giản, thô sơ nhất:

Thuộc tính name cho nút bấm
Thêm thuộc tính name cho nút bấm

Thông tin đã có thể gửi lên server ngon lành. Việc tóm bắt và xử lý giờ đây được chuyển qua cho PHP script thực hiện. Nói theo cách khoa trương, ta đang “lập trình web fullstack, stack ở phía client tạm xong, giờ nhảy sang stack ở phía server”.

Quay trở lại đầu file để xóa dòng có chữ print_r, khối mã giờ đây như sau:

Bonus thêm tí xíu xiu để dễ sử dụng

Bạn có phát hiện ra khi vào admin thiếu mất trang index.html hoặc index.php? Đó nên là trang có sẵn hiển thị menu các chức năng CRUD chúng ta đã thực hiện bên trên. Còn chần chừ gì nữa mà không bắt tay làm ngay index.php có nội dung hầu như chỉ HTML:

Lên đầu trang