Từ chối trách nhiệm quan trọng: cách thích hợp để làm điều này KHÔNG phải là sửa đổi cấu trúc bảng của bạn, mà là sử dụng wp_usermeta. Sau đó, bạn sẽ không cần tạo bất kỳ SQL tùy chỉnh nào để truy vấn các bài đăng của mình (mặc dù bạn vẫn sẽ cần một số SQL tùy chỉnh để nhận danh sách mọi người báo cáo cho người giám sát cụ thể - ví dụ như trong phần Quản trị viên). Tuy nhiên, vì OP đã hỏi về việc viết SQL tùy chỉnh, đây là cách thực hành tốt nhất hiện nay để đưa SQL tùy chỉnh vào Truy vấn WordPress hiện có.
Nếu bạn đang thực hiện các phép nối phức tạp, bạn không thể chỉ sử dụng bộ lọc post_where, vì bạn sẽ cần sửa đổi phép nối, chọn và có thể nhóm theo hoặc sắp xếp theo các phần của truy vấn.
Đặt cược tốt nhất của bạn là sử dụng bộ lọc 'post_clauses'. Đây là một bộ lọc rất hữu ích (không nên lạm dụng!) Cho phép bạn chắp thêm / sửa đổi các phần khác nhau của SQL được tạo tự động bởi nhiều dòng mã trong lõi WordPress. Chữ ký gọi lại bộ lọc là:
function posts_clauses_filter_cb( $clauses, $query_object ){ }
và nó mong bạn quay trở lại $clauses
.
Các khoản
$clauses
là một mảng chứa các khóa sau; mỗi khóa là một chuỗi SQL sẽ được sử dụng trực tiếp trong câu lệnh SQL cuối cùng được gửi đến cơ sở dữ liệu:
- Ở đâu
- nhóm
- tham gia
- đặt bởi
- khác biệt
- lĩnh vực
- giới hạn
Nếu bạn đang thêm một bảng vào cơ sở dữ liệu (chỉ làm điều này nếu bạn hoàn toàn không thể tận dụng post_meta, user_meta hoặc phân loại), có lẽ bạn sẽ cần phải chạm vào nhiều hơn một trong các mệnh đề này, ví dụ: fields
"CHỌN" một phần của câu lệnh SQL), join
(tất cả các bảng của bạn, không phải là bảng trong mệnh đề "TỪ" của bạn) và có thể là orderby
.
Sửa đổi các khoản
Cách tốt nhất để làm điều này là thay thế khóa có liên quan từ $clauses
mảng bạn nhận được từ bộ lọc:
$join = &$clauses['join'];
Bây giờ, nếu bạn sửa đổi $join
, bạn sẽ thực sự sửa đổi trực tiếp $clauses['join']
để thay đổi sẽ có $clauses
khi bạn trả lại.
Giữ nguyên các khoản gốc
Rất có thể (không, nghiêm túc, lắng nghe) bạn sẽ muốn duy trì SQL hiện có mà WordPress tạo ra cho bạn. Nếu không, có lẽ bạn nên xem posts_request
bộ lọc thay vào đó - đó là truy vấn myQuery hoàn chỉnh ngay trước khi nó được gửi đến cơ sở dữ liệu, do đó bạn hoàn toàn có thể tự mình ghi lại nó. Tại sao bạn muốn làm điều này? Bạn có thể không.
Vì vậy, để bảo toàn SQL hiện có trong các mệnh đề, hãy nhớ nối thêm các mệnh đề, không gán cho chúng (ví dụ: $join .= ' {NEW SQL STUFF}';
không sử dụng $join = '{CLOBBER SQL STUFF}';
. Lưu ý rằng vì mỗi phần tử của $clauses
mảng là một chuỗi, nếu bạn muốn nối vào nó, bạn có thể muốn chèn một khoảng trắng trước bất kỳ mã thông báo ký tự nào khác, nếu không bạn có thể sẽ tạo ra một số lỗi cú pháp SQL.
Bạn chỉ có thể giả sử sẽ luôn có một cái gì đó trong mỗi mệnh đề, và vì vậy hãy nhớ bắt đầu mỗi chuỗi mới bằng một khoảng trắng, như trong : $join .= ' my_table
, hoặc, bạn luôn có thể thêm một dòng nhỏ chỉ thêm một khoảng trắng nếu bạn cần:
$join = &$clauses['join'];
if (! empty( $join ) ) $join .= ' ';
$join .= "JOIN my_table... "; // <-- note the space at the end
$join .= "JOIN my_other_table... ";
return $clauses;
Đó là một điều phong cách hơn bất cứ điều gì khác. Điều quan trọng cần nhớ là: luôn để lại một khoảng trắng TRƯỚC chuỗi của bạn nếu bạn đang nối thêm một mệnh đề đã có một số SQL trong đó!
Đặt nó lại với nhau
Nguyên tắc đầu tiên của phát triển WordPress là cố gắng sử dụng càng nhiều chức năng cốt lõi càng tốt. Đây là cách tốt nhất để chứng minh công việc của bạn trong tương lai. Giả sử nhóm nòng cốt quyết định rằng WordPress sẽ sử dụng SQLite hoặc Oracle hoặc một số ngôn ngữ cơ sở dữ liệu khác. Bất kỳ myQuery viết tay nào cũng có thể trở nên không hợp lệ và phá vỡ plugin hoặc chủ đề của bạn! Tốt hơn là để WP tự tạo càng nhiều SQL càng tốt và chỉ cần thêm các bit bạn cần.
Vì vậy, đơn hàng đầu tiên của doanh nghiệp đang tận dụng WP_Query
để tạo ra càng nhiều truy vấn cơ sở của bạn càng tốt. Phương pháp chính xác mà chúng tôi sử dụng để làm điều này phụ thuộc phần lớn vào nơi danh sách các bài đăng này được cho là xuất hiện. Nếu đó là một phần phụ của trang (không phải truy vấn chính của bạn), bạn sẽ sử dụng get_posts()
; Nếu đó là truy vấn chính, tôi cho rằng bạn có thể sử dụng query_posts()
và thực hiện với nó, nhưng cách thích hợp để thực hiện là chặn truy vấn chính trước khi truy cập vào cơ sở dữ liệu (và sử dụng chu kỳ máy chủ), vì vậy hãy sử dụng request
bộ lọc.
Được rồi, vì vậy bạn đã tạo truy vấn của mình và SQL sắp được tạo. Vâng, trên thực tế, nó đã được tạo, chỉ không được gửi đến cơ sở dữ liệu. Bằng cách sử dụng posts_clauses
bộ lọc, bạn sẽ thêm bảng mối quan hệ nhân viên của mình vào hỗn hợp. Hãy gọi bảng này {$ wpdb-> tiền tố}. 'user_relationship' và đó là một bảng giao nhau. . .. nhưng tôi lạc đề).
Nếu tôi hiểu những gì bạn muốn làm, bạn muốn thông qua ID của Người dẫn đầu và sau đó chỉ xem các bài đăng của Người theo dõi đó. Tôi hy vọng tôi đã làm đúng. Nếu nó không đúng, bạn sẽ phải lấy những gì tôi nói và điều chỉnh nó theo nhu cầu của bạn. Tôi sẽ gắn bó với cấu trúc bảng của bạn: chúng tôi có một leader_id
và a follower_id
. Vì vậy, THAM GIA sẽ được bật {$wpdb->posts}.post_author
dưới dạng khóa ngoại đối với 'follower_id' trên bảng 'user_relationship' của bạn.
add_filter( 'posts_clauses', 'filter_by_leader_id', 10, 2 ); // we need the 2 because we want to get all the arguments
function filter_by_leader_id( $clauses, $query_object ){
// I don't know how you intend to pass the leader_id, so let's just assume it's a global
global $leader_id;
// In this example I only want to affect a query on the home page.
// This is where the $query_object is used, to help us avoid affecting
// ALL queries (since ALL queries pass through this filter)
if ( $query_object->is_home() ){
// Now, let's add your table into the SQL
$join = &$clauses['join'];
if (! empty( $join ) ) $join .= ' '; // add a space only if we have to (for bonus marks!)
$join .= "JOIN {$wpdb->prefix}employee_relationship EMP_R ON EMP_R.follower_id = {$wpdb->posts}.author_id";
// And make sure we add it to our selection criteria
$where = &$clauses['where'];
// Regardless, you always start with AND, because there's always a '1=1' statement as the first statement of the WHERE clause that's added in by WP/
// Just don't forget the leading space!
$where .= " AND EMP_R.leader_id={$leader_id}"; // assuming $leader_id is always (int)
// And I assume you'll want the posts "grouped" by user id, so let's modify the groupby clause
$groupby = &$clauses['groupby'];
// We need to prepend, so...
if (! empty( $groupby ) ) $groupby = ' ' . $groupby; // For the show-offs
$groupby = "{$wpdb->posts}.post_author" . $groupby;
}
// Regardless, we need to return our clauses...
return $clauses;
}