PHP III — Learn to connect web servers to databases, execute SQL queries, retrieve data, and protect against SQL injection attacks. PHP III — 學習如何將網絡伺服器連接到數據庫、執行 SQL 查詢、取得數據,並防範 SQL 注入攻擊。
Click any card to navigate to that section 點擊任意卡片跳轉至對應章節
In previous chapters, we learned HTML forms, HTTP requests, data validation, and cookies. Now we reach the most powerful part of server-side scripting — connecting our web server to a database. 在前幾章中,我們學習了 HTML 表單、HTTP 請求、數據驗證和 Cookie。現在我們進入伺服器端腳本最強大的部分 — 將網絡伺服器連接到數據庫。
A database allows us to store information such as usernames, passwords, product listings, and much more. This enables us to build real-world applications like booking systems, discussion forums, shopping sites, and online surveys. 數據庫讓我們能夠存儲用戶名、密碼、產品列表等各種信息。這使我們能夠構建現實世界的應用程序,如預訂系統、討論論壇、購物網站和在線調查。
A web server and a database are two separate entities that operate independently. While clients and servers communicate via HTTP, a web server uses an Application Programming Interface (API) to communicate with a database. 網絡伺服器和數據庫是兩個獨立的實體,各自獨立運行。客戶端和伺服器通過 HTTP 通信,而網絡伺服器則通過應用程式介面 (API) 與數據庫通信。
Request-Response Flow: 請求-回應流程:
The user's browser sends a request to the web server (e.g., visiting a PHP page).用戶的瀏覽器向網絡伺服器發送請求(例如,訪問一個 PHP 頁面)。
The PHP script runs on the server. It forms an SQL query and sends it to the database using the mysqli API.PHP 腳本在伺服器上運行。它形成一個 SQL 查詢,並使用 mysqli API 將其發送到數據庫。
The database executes the SQL and returns the result set back to the web server.數據庫執行 SQL 並將結果集返回給網絡伺服器。
The PHP script uses the query result data to generate an HTML page, which is returned to the client's browser.PHP 腳本使用查詢結果數據生成 HTML 頁面,然後返回給客戶端的瀏覽器。
A PHP extension that provides functions to connect and interact with MySQL databases. "mysqli" stands for MySQL Improved.一個 PHP 擴展,提供連接和與 MySQL 數據庫交互的函數。"mysqli" 代表 MySQL Improved(改進版 MySQL)。
API functions like mysqli_connect() involve network communications and can fail unexpectedly (e.g., database offline). Always implement error-handling mechanisms.像 mysqli_connect() 這樣的 API 函數涉及網絡通信,可能意外失敗(例如數據庫離線)。務必實現錯誤處理機制。
mysqli_query() returns a mysqli_result object for SELECT queries — think of it as a table representing the query results. You need mysqli_fetch_assoc() to access individual rows.mysqli_query() 為 SELECT 查詢返回一個 mysqli_result 對象 — 可以把它想像成代表查詢結果的表格。你需要 mysqli_fetch_assoc() 來訪問各行數據。
mysqli_fetch_assoc() converts each row into an associative array where column names are the keys. E.g., $row["name"] accesses the "name" column value.mysqli_fetch_assoc() 將每行轉換為關聯數組,其中列名是鍵。例如,$row["name"] 訪問 "name" 列的值。
| Function函數 | Purpose用途 | Returns (Success)返回值(成功) | Returns (Fail)返回值(失敗) |
|---|---|---|---|
mysqli_connect() |
Connect web server to database連接網絡伺服器到數據庫 | mysqli object ($link)mysqli 對象 ($link) | false |
mysqli_query() |
Execute SQL query on database在數據庫上執行 SQL 查詢 | mysqli_result object (SELECT) / true (INSERT/UPDATE/DELETE)mysqli_result 對象(SELECT)/ true(INSERT/UPDATE/DELETE) | false |
mysqli_fetch_assoc() |
Fetch next row as associative array以關聯數組形式獲取下一行 | Associative array (one row)關聯數組(一行) | NULL |
mysqli_num_rows() |
Count rows in query result統計查詢結果中的行數 | Integer (number of rows)整數(行數) | — |
mysqli_real_escape_string() |
Sanitise string for SQL query清理字符串以用於 SQL 查詢 | Sanitised string已清理的字符串 | — |
mysqli_connect()
Used to establish a connection between a PHP script and a MySQL database. Requires 4 parameters. 用於在 PHP 腳本和 MySQL 數據庫之間建立連接。需要4個參數。
mysqli_query()
Executes an SQL statement on the connected database. Takes the connection object and the SQL string as parameters. 在已連接的數據庫上執行 SQL 語句。以連接對象和 SQL 字符串作為參數。
mysqli_fetch_assoc()
with while loop
配合 while 循環
Fetches one row from the query result as an associative array. Used in a while loop to iterate through all rows. 從查詢結果中以關聯數組形式獲取一行。在 while 循環中使用以遍歷所有行。
In PHP, when an assignment statement is used in a while-loop condition: 在 PHP 中,當賦值語句用於 while 循環條件時:
mysqli_fetch_assoc($result)) is first assigned to the variable on the left ($row).右側的值(mysqli_fetch_assoc($result))首先被賦值給左側的變量($row)。NULL, FALSE, 0, or empty string → loop stops. Otherwise → loop continues.PHP 然後評估賦值的值:如果是 NULL、FALSE、0 或空字符串 → 循環停止。否則 → 循環繼續。mysqli_fetch_assoc() returns NULL when there are no more rows — this stops the loop automatically.當沒有更多行時,mysqli_fetch_assoc() 返回 NULL — 這會自動停止循環。Note: mysqli_fetch_assoc() also removes the top row from the result object each time it's called (pass-by-reference). 注意:每次調用 mysqli_fetch_assoc() 時,它還會從結果對象中移除頂部行(按引用傳遞)。
mysqli_num_rows() — Check if results exist檢查是否有結果Since SQL statements are strings in PHP, you can insert (parse) variables to create dynamic queries with different filter or sort criteria. 由於 SQL 語句在 PHP 中是字符串,你可以插入(解析)變量來創建具有不同過濾或排序條件的動態查詢。
WHERE country = '$c'. Missing the quotes is a painful bug that is hard to identify!
在 SQL 字符串中,文本(字符串)過濾值務必用單引號括起來:WHERE country = '$c'。漏掉引號是一個難以識別的痛苦 bug!
SQL injection is an attack method that exploits server scripts that use user-provided values without precautions in SQL queries. A hacker can "inject" malicious SQL commands and cause catastrophic consequences. SQL 注入是一種攻擊方法,它利用在 SQL 查詢中不加防範地使用用戶提供值的伺服器腳本。黑客可以"注入"惡意 SQL 命令,造成災難性後果。
Suppose a hacker enters the following into a city search form: 假設黑客在城市搜索表單中輸入以下內容:
' closes the string in SQL. The semicolon ; ends the first query. DROP TABLE city_info becomes a second, executed command. -- comments out the rest.
單引號 ' 在 SQL 中結束字符串。分號 ; 結束第一個查詢。DROP TABLE city_info 成為第二個被執行的命令。-- 注釋掉其餘部分。
Always sanitise client-sent values before using them in an SQL query. mysqli_real_escape_string() escapes special characters (like ', ") by adding a backslash, preventing them from being interpreted as SQL syntax.
在 SQL 查詢中使用客戶端發送的值之前,務必先清理這些值。mysqli_real_escape_string() 通過添加反斜杠來轉義特殊字符(如 '、"),防止它們被解釋為 SQL 語法。
Before sanitization:清理前:
After sanitization:清理後:
The escaped \' is treated as a literal apostrophe character, not as SQL syntax. The DROP TABLE command is never executed.
轉義後的 \' 被視為字面上的撇號字符,而不是 SQL 語法。DROP TABLE 命令永遠不會被執行。
12 questions covering all key topics. Select your answers and submit to see your score. 12道題目涵蓋所有重要主題。選擇答案後提交以查看分數。
Q1. What does mysqli_connect() return when the connection to the database is successful? Q1. 當成功連接到數據庫時,mysqli_connect() 返回什麼?
Q2. Which of the following is the correct order of parameters for mysqli_connect()? Q2. 以下哪個是 mysqli_connect() 參數的正確順序?
Q3. What does mysqli_query() return when a SELECT query fails? Q3. 當 SELECT 查詢失敗時,mysqli_query() 返回什麼?
Q4. What does mysqli_fetch_assoc() return when there are no more rows in the result? Q4. 當結果中沒有更多行時,mysqli_fetch_assoc() 返回什麼?
Q5. A database table "students" has columns: id, name, grade. After running $result = mysqli_query($link, "SELECT * FROM students");, how do you access the name of the current row in the while loop?
Q5. 數據庫表 "students" 有列:id, name, grade。執行 $result = mysqli_query($link, "SELECT * FROM students"); 後,如何在 while 循環中訪問當前行的 name?
Q6. Which function is used to count the number of rows in a query result? Q6. 哪個函數用於統計查詢結果中的行數?
Q7. What is SQL injection? Q7. 什麼是 SQL 注入?
Q8. What does mysqli_real_escape_string() do? Q8. mysqli_real_escape_string() 的作用是什麼?
Q9. When using the wildcard (*) in a SELECT query, what case are the column names in the returned result? Q9. 在 SELECT 查詢中使用通配符 (*) 時,返回結果中的列名是什麼大小寫?
Q10. What is the hostname value 'localhost' commonly used for in mysqli_connect()? Q10. 在 mysqli_connect() 中,主機名值 'localhost' 通常用於什麼情況?
Q11. When using an aggregate function like COUNT(*) in a PHP SQL query, what must you do to access the result? Q11. 在 PHP SQL 查詢中使用像 COUNT(*) 這樣的聚合函數時,你必須做什麼才能訪問結果?
Q12. What is the correct way to parse a variable $category into an SQL WHERE clause for a text field? Q12. 將變量 $category 解析到文本字段的 SQL WHERE 子句中的正確方式是什麼?
Click any card to flip it and reveal the answer. 20 key terms and concepts. 點擊任意卡片翻轉以查看答案。20個關鍵術語和概念。
Exam-style questions based on chapter content. Click "View Reference Answer" to see the model answer. 基於章節內容的考試風格題目。點擊「查看參考答案」查看範本答案。
mysqli_connect() in a PHP script.
說明 PHP 腳本中 mysqli_connect() 的用途。
$query = "";
Kathy 正在開發 list_places.php。她想從 PLACES 表中選取所有挪威地點的 code、city 和 priority。為第18行寫出 SQL 查詢字符串:$query = "";
Note: Use lowercase for column names (code, city, priority). Enclose the text value 'Norway' in single quotes. 注意:列名使用小寫(code, city, priority)。文本值 'Norway' 用單引號括起來。
Key points: (1) Use $row["column_name"] to access each column value. (2) Since wildcard (*) is used, column names are all lowercase. (3) Use curly braces {$row["..."]} for variable parsing inside strings. 要點:(1) 使用 $row["column_name"] 訪問每列的值。(2) 由於使用了通配符 (*),列名全部小寫。(3) 在字符串中解析變量時使用大括號 {$row["..."]}。
mysqli_real_escape_string() before using user input in an SQL query. State the benefit of this modification.
開發者修改了代碼,在 SQL 查詢中使用用戶輸入之前添加了 mysqli_real_escape_string()。說明此修改的好處。
Key points: (1) Start with WHERE TRUE so additional AND conditions can be appended without issues. (2) Text values (name, brand) must be enclosed in single quotes. (3) Numeric values (max_price) can also be enclosed in single quotes for consistency. (4) In production, always sanitise with mysqli_real_escape_string() first! 要點:(1) 從 WHERE TRUE 開始,這樣可以無問題地附加額外的 AND 條件。(2) 文本值(name, brand)必須用單引號括起來。(3) 數值(max_price)也可以用單引號括起來以保持一致性。(4) 在生產環境中,務必先用 mysqli_real_escape_string() 清理!
(a) The request retrieves data (no modification to server state), so GET is appropriate. GET requests can also be bookmarked/shared via URL.該請求是取得數據(不修改伺服器狀態),因此 GET 是合適的。GET 請求也可以通過 URL 收藏/分享。
(b)
(c) mysqli_real_escape_string() escapes special characters (e.g., single quotes) in the user-provided name. This prevents SQL injection — a malicious user cannot inject extra SQL commands through the name field, protecting the database from unauthorized queries or data destruction.mysqli_real_escape_string() 轉義用戶提供的名稱中的特殊字符(例如單引號)。這防止了 SQL 注入 — 惡意用戶無法通過名稱字段注入額外的 SQL 命令,保護數據庫免受未授權查詢或數據破壞。