Query trong SQL

Học truy vấn SQL trong WordPress, mánh mẹo cho nhà phát triển giao diện và plugin

Truy vấn SQL trong Wordpress cực kì đơn giản, với các hàm được build sẵn, bạn chỉ cần gọi đúng là được, không như các mã nguồn khác rất nhì nhằng, hãy xem cách truy vấn, thêm cơ sở dữ liệu của Wordpress sau đây !

Xin chào các bạn, Jam đã sử dụng rất nhiều mã nguồn mở bao gồm Drupal, Joomla, WordPress, PHPbb hay VBB nhưng nói thật là không cái truy vấn nào lại ngắn gọn và dễ dàng như WordPress, tất nhiên là nó vẫn đảm bảo tính bảo mật chống các cuộc tấn công SQL Injection, sau đây chúng ta chú ý vài điểm nhé !

Về Class WPDB của WordPress

Class WPDB của WordPress sử dụng thư viện EzSQL của Justin Vincent ( không phải ca sĩ đâu nhá 😀 ) và được phát triển phù hợp hơn với WordPress nhưng vẫn giữ phong cách của EzSQL.

* Lưu ý: vì vấn đề bảo mật cho nên các bạn không được gọi trực tiếp class::WPDB mà hãy sử dụng object qua global $wpdb.

* Lưu ý tiếp: Vì vấn đề bảo mật, bạn cần phải escape toàn bộ các dữ liệu trước khi thêm vào cơ sở dữ liệu, các hàm escape bao gồm:

  • esc_html: escape toàn bộ các mã html, ví dụ dấu < sẽ là &gt;
  • esc_attr: escape toàn bộ các giá trị trong form !
  • esc_sql: escape các text cho SQL, tuy nhiên không nên dùng mà thay vào đó sử dụng hàm $wpdb->prepare !
  • esc_textarea: Mã hóa các thẻ html !

Các bảng cơ sở dữ liệu mặc định

Bảng mặc định:

$posts
$postmeta
$comments 
$commentmeta 
$terms 
$term_taxonomy 
$term_relationships 
$users 
$usermeta 
$links 
$options

Các bảng trong WordPress Multisite:

$blogs 
$signups 
$site 
$sitemeta 
$sitecategories 
$registration_log 
$blog_versions

Cách thức gọi cơ sở dữ liệu

Các bạn không nên gọi trực tiếp, hãy gọi theo biến toàn cục global như sau:

global $wpdb;

Mọi thứ cần được an toàn

Theo thứ tự về mức độ quan trọng, Jam sẽ viết hàm quan trọng lên gần đầu để các bạn tiện theo dõi, và để an toàn với các cuộc tấn công SQL Injection cực kì phổ thông, các bạn cần phải chạy các lệnh của SQL qua hàm prepare, sau đây là ví dụ:

global $wpdb;
$wpdb->prepare('select * from %s where user_id = %d', $wbdb->users, 5);

Trong hàm này ta thấy cách thức hoạt động của nó hoàn toàn giống hàm sprintf() trong PHP !

%f: Float – dữ liệu float ( ví dụ 1,234 )

%d: Decima – số ( ví dụ: 1220 )

%s: String – chuỗi kí tự ( ví dụ “chào các bạn tôi là string”)

Và nếu như Input vào mà sai so với mệnh đề thứ nhất, thì dữ liệu sẽ bị ép kiểu, các bạn để ý lần lượt ở câu lệnh trên là:

select * from %s <!-- string // --> where user_id = %d <!-- số // -->,
%s <!-- string // -->, %d <!-- sẽ bị ép kiểu là số  -->

Khi mọi lệnh chạy qua hàm Prepare thì các biến, câu lệnh và các giá trị của người dùng sẽ được lọc an toàn, các bạn lưu ý như sau, nếu trong câu lệnh mà không có giá trị nào người dùng thêm vào, ta không cần sử dụng hàm này, vì chỉ có người dùng input vào thì dữ liệu mới không an toàn, hoặc là sẽ bị báo lỗi, trường hợp sau sẽ bị báo lỗi:

$wpdb->prepare("select * from {$wbdb->users}");

Khi câu lệnh tuyệt đối an toàn như trên, chẳng có lý do gì bạn chạy qua hàm Prepare nữa, mà chạy thẳng qua $wpdb->query luôn !

* Xin lưu ý tới các bạn: Câu nổi tiếng trong lập trình mà chúng tớ cần phải học thuộc đó là “đừng tin vào bất kì một ai, kể cả bản thân” cho nên các bạn nếu viết plugin hay giao diện thì cần phải tuyệt đối an toàn, nếu không biết rõ mình làm gì thì tốt nhất không làm !

Query chung

Các bạn có thể chạy bất kì câu lệnh nào với $wpdb->query, dùng để chạy các lệnh rất cơ bản mà không cần trả về kết quả như SELECT, INSERT, DELETE, UPDATE như sau:

$wpdb->query( 
	$wpdb->prepare( 
		"
                DELETE FROM $wpdb->postmeta
		 WHERE post_id = %d
		 AND meta_key = %s
		",
	        13, 'gargle' 
        )
);

Hay như thế này:

$wpdb->query(
	"
	UPDATE $wpdb->posts 
	SET post_parent = 7
	WHERE ID = 15 
		AND post_status = 'static'
	"
);

* Kinh nghiệm: Các câu lệnh an toàn, do hệ thống chạy và không có trường nào do người dùng Input thì có thể chạy lệnh query trực tiếp như vậy, các câu lệnh thường không cần phải trả về một kết quả xác thực nào mà chỉ cần trả về đúng hoặc sai, hoặc ID của row bị ảnh hưởng …

* Ví dụ như sau:

Đếm số thành viên trên trang:

global $wpdb;
echo inval( $wpdb->query("select count(*) from $wpdb->users") );

Lấy giá trị của một biến nào đó trong bảng

Để lấy giá trị của một biến, một giá trị đơn nào đó trong bảng, hoặc đếm số recode, ta có thể sử dụng hàm get_var trong WordPress, ví dụ như sau:

<?php $wpdb->get_var( 'query', column_offset, row_offset ); ?>

Câu lệnh ví dụ về đếm thành viên trên trang:

$user_count = $wpdb->get_var( "SELECT COUNT(*) FROM $wpdb->users" );

Hoặc câu lệnh sau đây tính tổng giá trị trong bảng meta của Post, đếm giá tiền chẳng hạn:

$meta_key = '_price';
$allmiles = $wpdb->get_var( $wpdb->prepare( 
    "
        SELECT sum(meta_value) 
        FROM $wpdb->postmeta 
        WHERE meta_key = %s
    ", 
    $meta_key
) );

Lấy giá trị của một hàng

Để lấy toàn bộ giá trị của một hàng, chúng ta có thể sử dụng hàm get_row, code mẫu như sau:

 <?php $wpdb->get_row('query'); ?>

Câu lệnh trên sẽ trả về Object theo mặc định, các bạn xem code ví dụ như sau:

$mylink = $wpdb->get_row( "SELECT * FROM $wpdb->links WHERE link_id = 10" );

Lệnh trên lấy toàn bộ các giá trị trong một hàng với link_id là 10, trường hợp khác, bạn muốn lấy toàn bộ giá trị của Post ID là 10 thì sao ? Xem code sau:

$postdata = $wpdb->get_row( "SELECT * FROM $wpdb->posts WHERE post_id = 10" );

Và bạn có thể lấy giá trị của Post_content một cách dễ dàng:

echo $content = $postdata->post_content;

Lấy hàng loạt giá trị

Để lấy một giá trị đơn, các bạn sử dụng hàm get_var hoặc get_row, nhưng để lấy hàng loạt các giá trị thỏa mãn điều kiện thì bạn cần phải sử dụng hàm get_results nhé, xem code mẫu sau đây:

$wpdb->get_results( 'query');

Trả về sẽ là mặc định một array có chứa các Object khác nhau, ví dụ trong trường hợp cụ thể, tôi muốn lấy toàn bộ các bài đăng của User 1 thì làm thế nào ?

$user_id = 1;
$data  = $wpdb->get_results( $wpdb->prepare(
    'select * from %s where user_id = %d LIMIT 99',
    $wpdb->posts, $user_id
));
foreach ( $data as $k ) {
    echo $k->post_title;
}

Trong hầu hết các trường hợp, bạn sẽ sử dụng get_var và get_results để lấy kết quả 😀 và trong các vòng lặp của WordPress, người ta cũng sử dụng hàm get_results này nhé các bạn !

Insert giá trị vào bảng

Để Insert một giá trị nào đó vào bảng, các bạn sử dụng hàm insert sau đây để thêm nhé, tuyệt đối không thêm bằng cách sử dụng $wpdb->query, trừ trường hợp rất an toàn, các bạn xem mẫu code sau:

$wpdb->insert( $table, $data, $format );

Code ví dụ như sau, các bạn cần chèn thêm dữ liệu trong bảng posts trong WordPress chẳng hạn, làm như sau:

$wpdb->insert( $wpdb->posts,
array('ID' => $wpdb->insert_id, 'post_content' => $content),
array('%d', '%s')
);

Nếu Insert thành công, bạn sẽ được hàm trả về giá trị là 1, nếu không sẽ là False hoặc 0.

Thay thế một trường trong bảng

Để thay thế trường, cột nào đó trong bảng dữ liệu, các bạn cũng làm tương tự như Insert, nhưng dùng hàm Replace nhé:

$wpdb->replace( $table, $data, $format )

Ví dụ như sau:

$wpdb->replace( 
	'table', 
	array( 
                'indexed_id' => 1,
		'column1' => 'value1', 
		'column2' => 123 
	), 
	array( 
                '%d',
		'%s', 
		'%d' 
	) 
);

Hàm này cũng trả về true hoặc false nếu thực hiện được hoặc không thực hiện được !

Update trong dữ liệu

Để update một hàng hay một giá trị trong hàng ta thực hiện bằng lệnh update, code như sau:

$wpdb->update( $table, $data, $where, $format = null, $where_format = null );

Ví dụ, ta cần thay thế Post_title có Post ID 10 bằng Post_title mới, ta làm như sau:

$wpdb->update( $wpdb->posts,
array('post_title' => 'Thân chào các bạn'),
array('ID' => 10),
);

Xóa một dữ liệu

Để xóa hàng, trường dữ liệu nào đó ta có thể sử dụng hàm delete như sau:

 $wpdb->delete( $table, $where, $where_format = null );

Ví dụ bạn muốn xóa bài đăng có ID là 2, bạn làm như sau:

$wpdb->delete( $wpdb->posts, array('ID' => 2));

Câu lệnh trả về ID bị xóa hoặc false;

Chống hacker hack vào cơ sở dữ liệu

Các bạn nên sử dụng Sprintf hoặc hàm Prepare để giảm thiểu rủi ro bị tấn công SQL injection, trường hợp khác, các bạn có thể sử dụng các hàm đã có sẵn trong WordPress để sử dụng, tôi lấy ví dụ như sau:

Sử dụng Sprinf:

$wpdb->query( sprinf('select * from %s where user_id = %d ', $wpdb->users, 12) );

Sử dụng hàm mặc định:

  • wp_delete_post( postID );
  • wp_delete_user( $userID );
  • Delete_option( $name );
  • Wp_trash_post( $postID );

Vân vân, các bạn có thể tham khảo Codex trên WordPress.org để tìm đúng hàm mình cần, tránh tình trạng viết code dài dòng mà không an toàn !

Chúc các bạn thành công !

TÁC GIẢ:

Tôi là Jam, thâm niên 7 năm thiết kế website và làm SEO. Hãy theo dõi blog của tôi để nhận được nhiều chia sẻ thú vị xung quanh chủ đề công nghệ.

Có 4 bình luận !

Trả lời

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *