Trong thiết kế lập trình web với PHP và MySql việc thiết kế
cơ sở dữ liệu là một việc hết sức quan trọng. Nhưng đôi các bạn thường gặp phải
một số vấn đề khi truy xuất dữ liệu. Sau đây là một số cách truy cập cơ sở dữ
liệu trong mã PHP và cách sửa chữa những lỗi phát sinh trong quá trình truy xuất
dữ liệu sử dụng MySQL trực tiếp
Khi sử dùng các hàm mysql_ để truy cập trực tiếp vào cơ sở dữ
liệu có một vấn đề phổ biến là mã PHP đã cũ. Cách truy cập trực tiếp vào cơ sở
dữ liệu.
Access/get.php
<?php
function get_user_id( $name )
{
$db = mysql_connect(
'localhost', 'root', 'password' );
mysql_select_db(
'users' );
$res = mysql_query(
"SELECT id FROM users WHERE login='".$name."'" );
while( $row =
mysql_fetch_array( $res ) ) { $id = $row[0]; }
return $id;
}
var_dump( get_user_id( 'jack' ) );
?>
Hãy lưu ý việc sử dụng hàm mysql_connect để truy cập vào cơ
sở dữ liệu. Cũng chú ý truy vấn trong đó có dùng sự liên kết chuỗi để bổ sung
tham số $name vào truy vấn đó.
Kỹ thuật này có hai sự lựa chọn tốt: mô đun PEAR DB và các lớp
PHP Data Objects (PDO-Các đối tượng dữ liệu PHP). Cả hai đều cung cấp sự trừu
tượng từ việc lựa chọn của một cơ sở dữ liệu cụ thể. Do đó, mã của bạn có thể
chạy mà không cần điều chỉnh quá nhiều trên IBM® DB2®, MySQL, PostgreSQL, hoặc
cơ sở dữ liệu khác bất kỳ mà bạn muốn kết nối đến.
Các giá trị khác trong việc sử dụng các tầng trừu tượng của
mô đun PEAR DB và PDO là bạn có thể sử dụng toán tử ? trong các câu lệnh SQL của
bạn. Việc này làm cho SQL dễ dàng bảo trì hơn và bảo vệ ứng dụng của bạn khỏi
các cuộc tấn công nội xạ SQL.
Mã thay thế khi sử dụng
PEAR DB được hiển thị dưới đây.
Access/get_good.php
<?php
require_once("DB.php");
function get_user_id( $name )
{
$dsn =
'mysql://root:password@localhost/users';
$db =&
DB::Connect( $dsn, array() );
if (PEAR::isError($db))
{ die($db->getMessage()); }
$res =
$db->query( 'SELECT id FROM users WHERE login=?',
array( $name ) );
$id = null;
while(
$res->fetchInto( $row ) ) { $id = $row[0]; }
return $id;
}
var_dump( get_user_id( 'jack' ) );
?>
Chú ý rằng tất cả các đề cập trực tiếp của MySQL đã diễn ra,
trừ chuỗi kết nối cơ sở dữ liệu trong $dsn. Ngoài ra, chúng ta sử dụng biến
$name trong SQL thông qua toán tử ?. Sau đó, dữ liệu với truy vấn này được gửi
đi thông qua array ở cuối phương thức query().
Không sử dụng chức
năng tăng tự động
Giống như hầu hết các cơ sở dữ liệu hiện đại, MySQL có khả
năng tạo các trình nhận dạng (identifier) duy nhất tăng tự động trên một cơ sở
cho mỗi bản ghi. Mặc dù vậy, chúng ta vẫn thấy mã lần đầu tiên chạy một lệnh
SELECT để tìm mã nhận dạng (id) tối đa, sau đó bổ sung thêm một vào id đó, cũng
như một bản ghi mới. Phần mã code sau cho thấy một lược đồ mẫu bad (xấu).
Badid.sql
DROP TABLE IF EXISTS users;
CREATE TABLE users (
id MEDIUMINT,
login TEXT,
password TEXT
);
INSERT INTO users VALUES ( 1, 'jack', 'pass' );
INSERT INTO users VALUES ( 2, 'joan', 'pass' );
INSERT INTO users VALUES ( 1, 'jane', 'pass' );
Trường id ở đây được quy định đơn giản là một số nguyên. Vì
vậy, mặc dù nó sẽ là duy nhất, chúng ta có thể thêm vào bất kỳ giá trị nào mà
chúng ta muốn, như đã chỉ ra trong câu lệnh INSERT tiếp theo câu lệnh CREATE. Mã
PHP bổ sung thêm users (những người sử dụng) vào kiểu lược đồ này.
Mã thêm users: Add_user.php
<?php
require_once("DB.php");
function add_user( $name, $pass )
{
$rows = array();
$dsn =
'mysql://root:password@localhost/bad_badid';
$db =&
DB::Connect( $dsn, array() );
if
(PEAR::isError($db)) { die($db->getMessage()); }
$res =
$db->query( "SELECT max(id) FROM users" );
$id = null;
while(
$res->fetchInto( $row ) ) { $id = $row[0]; }
$id += 1;
$sth =
$db->prepare( "INSERT INTO users VALUES(?,?,?)" );
$db->execute(
$sth, array( $id, $name, $pass ) );
return $id;
}
$id = add_user( 'jerry', 'pass' );
var_dump( $id );
?>
Mã trong add_user.php đầu tiên thực hiện một truy vấn để tìm
ra giá trị tối đa của id. Sau đó tệp này chạy một câu lệnh INSERT với giá trị
id cộng thêm một. Mã này có thể không chạy thành công trong các điều kiện ganh
đua (race) trên các máy chủ có một tải nặng. Hơn nữa, nó không hiệu quả.
Vì vậy, sự thay thế là gì? Sử dụng tính năng tăng tự động
trong MySQL để tạo các ID duy nhất cho mỗi lần chèn tự động. Lược đồ cập nhật
được hiển thị bên dưới như sau:
Goodid.php
DROP TABLE IF EXISTS users;
CREATE TABLE users (
id MEDIUMINT NOT
NULL AUTO_INCREMENT,
login TEXT NOT NULL,
password TEXT NOT
NULL,
PRIMARY KEY( id )
);
INSERT INTO users VALUES ( null, 'jack', 'pass' );
INSERT INTO users VALUES ( null, 'joan', 'pass' );
INSERT INTO users VALUES ( null, 'jane', 'pass' );
Chúng ta thêm cờ NOT NULL để chỉ ra rằng các trường này
không rỗng (null). Chúng ta cũng đã bổ sung cờ AUTO_INCREMENT để chỉ thị rằng
trường này tăng tự động, cũng như cờ PRIMARY KEY để chỉ thị trường nào là id.
Những thay đổi này cho phép tăng một chút tốc độ. Liệt kê 6 cho thấy mã PHP đã
cập nhật, mã này chèn users (những người dùng) vào bảng.
Add_user_good.php
<?php
require_once("DB.php");
function add_user( $name, $pass )
{
$dsn =
'mysql://root:password@localhost/good_genid';
$db =&
DB::Connect( $dsn, array() );
if
(PEAR::isError($db)) { die($db->getMessage()); }
$sth =
$db->prepare( "INSERT INTO users VALUES(null,?,?)" );
$db->execute(
$sth, array( $name, $pass ) );
$res =
$db->query( "SELECT last_insert_id()" );
$id = null;
while(
$res->fetchInto( $row ) ) { $id = $row[0]; }
return $id;
}
$id = add_user( 'jerry', 'pass' );
var_dump( $id );
?>
Thay vì nhận được giá trị id tối đa, tôi bây giờ chỉ cần sử dụng
câu lệnh INSERT để chèn dữ liệu, sau đó sử dụng một câu lệnh SELECT để lấy id của
bản ghi vừa mới được chèn vào. Mã này đơn giản hơn nhiều và hiệu quả hơn so với
phiên bản gốc và lược đồ liên quan của nó.
Một lựa chọn khác đối với chức năng tăng tự động của MySQL
là sử dụng phương thức nextId() trong hệ thống PEAR DB. Trong trường hợp của
MySQL, điều này tạo ra một bảng tuần tự mới và quản lý việc sử dụng một cơ chế
khóa phức tạp. Lợi thế của việc sử dụng phương thức này là nó sẽ hoạt động trên
các hệ thống cơ sở dữ liệu khác.
Dù bằng cách nào, bạn nên sử dụng một hệ thống quản lý sự
tăng các ID duy nhất cho bạn và không dựa vào hệ thống mà bạn truy vấn đầu
tiên, sau đó tăng giá trị của chính bạn và thêm bản ghi. Cách tiếp cận thứ hai
dễ bị ảnh hưởng theo các điều kiện ganh đua trên các trang có khối lượng cao.
Không có nhận xét nào:
Đăng nhận xét