중요 고지 사항 :이를 수행하는 올바른 방법은 테이블 구조를 수정하는 것이 아니라 wp_usermeta를 사용하는 것입니다. 그런 다음 게시물을 쿼리하기 위해 사용자 지정 SQL을 만들 필요는 없습니다 (단, 관리자 섹션에서 특정 관리자에게보고하는 모든 사람의 목록을 가져 오려면 일부 사용자 지정 SQL이 필요합니다). 그러나 OP가 사용자 지정 SQL 작성에 대해 요청 했으므로 다음은 기존 WordPress 쿼리에 사용자 지정 SQL을 삽입하는 현재 모범 사례입니다.
복잡한 조인을 수행하는 경우에는 join_where 필터를 사용할 수 없습니다. 쿼리의 조인, 선택 및 그룹 별 또는 순서별로 섹션을 수정해야하기 때문입니다.
가장 좋은 방법은 'posts_clauses'필터를 사용하는 것입니다. 이것은 매우 유용한 필터입니다 (남용해서는 안됩니다!). WordPress 코어 내의 많은 코드 줄에 의해 자동으로 생성되는 SQL의 다양한 부분을 추가 / 수정할 수 있습니다. 필터 콜백 서명은 다음 function posts_clauses_filter_cb( $clauses, $query_object ){ }
과 같습니다
$clauses
.
조항
$clauses
다음 키를 포함하는 배열입니다. 각 키는 데이터베이스에 전송 된 최종 SQL 문에서 직접 사용되는 SQL 문자열입니다.
데이터베이스에 테이블을 추가하는 경우 (post_meta, user_meta 또는 taxonomies를 절대 활용할 수없는 경우에만 수행)이 절 중 하나 이상을 터치해야 할 수도 있습니다 fields
( 예 : "SELECT" SQL 문의 일부), join
( "FROM"절에있는 테이블 이외의 모든 테이블)orderby
.
조항 수정
이를 수행하는 가장 좋은 방법 $clauses
은 필터에서 얻은 배열 에서 관련 키를 하위 참조하는 것입니다 .
$join = &$clauses['join'];
이제를 수정 $join
하면 실제로 직접 수정 $clauses['join']
되므로 변경 사항이$clauses
을 반환 할 때 .
원본 절 보존
WordPress에서 생성 한 기존 SQL을 유지하려고 할 가능성이 있습니다 (심지어 들리지 않습니다). 그렇지 않다면 아마도posts_request
필터를 즉, 데이터베이스로 전송되기 직전에 완전한 mySQL 쿼리이므로 자신의 필터로 완전히 클로버 할 수 있습니다. 왜 이렇게 하시겠습니까? 당신은 아마하지 않습니다.
따라서 절에서 기존 SQL을 유지하려면 절에 추가하지 말고 절에 할당하지 마십시오 (예 : $join .= ' {NEW SQL STUFF}';
not 사용) $join = '{CLOBBER SQL STUFF}';
. $clauses
배열 의 각 요소 는 문자열이므로 추가하려는 경우, 다른 문자 토큰 앞에 공백을 삽입하고 싶을 수도 있습니다. 그렇지 않으면 SQL 구문 오류가 발생할 수 있습니다.
각 절에 항상 무언가가 있다고 가정 할 수 있으므로 다음과 같이 공백으로 새 문자열을 각각 시작 $join .= ' my_table
해야합니다. 또는 필요한 경우 공백을 추가하는 작은 줄을 항상 추가 할 수 있습니다.
$join = &$clauses['join'];
if (! empty( $join ) ) $join .= ' ';
$join .= "JOIN my_table... "; // <-- note the space at the end
$join .= "JOIN my_other_table... ";
return $clauses;
그것은 다른 어떤 것보다 문체적인 것입니다. 기억해야 할 중요한 점은 이미 일부 SQL이 포함 된 절을 추가하는 경우 문자열 앞에 공백을 남겨 두는 것입니다.
함께 모으기
WordPress 개발의 첫 번째 규칙은 최대한 많은 핵심 기능을 사용하는 것입니다.이것이 향후 작업을 증명하는 가장 좋은 방법입니다. 핵심 팀이 WordPress가 이제 SQLite 또는 Oracle 또는 다른 데이터베이스 언어를 사용할 것이라고 결정한다고 가정하십시오. 직접 작성한 mySQL이 유효하지 않게되어 플러그인이나 테마가 깨질 수 있습니다! WP가 가능한 많은 SQL을 자체적으로 생성하고 필요한 비트를 추가하는 것이 좋습니다.
따라서 비즈니스 우선 순위는 최대한 WP_Query
많은 기본 쿼리를 생성 하는 데 활용 됩니다. 이 작업을 수행하는 데 사용하는 정확한 방법은이 게시물 목록이 표시 되는 위치에 따라 다릅니다 . 페이지의 하위 섹션 인 경우 (기본 쿼리가 아님) get_posts()
; 기본 쿼리 인 경우 사용 query_posts()
하고 완료 할 수 있다고 생각 하지만 적절한 방법은 기본 쿼리가 데이터베이스에 도달하기 전에 차단하고 서버주기를 소비하므로 request
필터를 사용하는 것 입니다.
이제 쿼리를 생성했으며 SQL을 만들려고합니다. 사실, 그것은 데이터베이스로 보내지지 않고 만들어졌습니다. posts_clauses
필터 를 사용하면 직원 관계 테이블을 믹스에 추가하게됩니다. 이 테이블을 {$ wpdb-> prefix}라고하자. 'user_relationship'이며 교차 테이블입니다. (이런 식으로이 테이블 구조를 일반화하고 'relationship_id', 'user_id', 'related_user_id', 'relationship_type'필드가있는 적절한 교차 테이블로 바꾸는 것이 좋습니다. 훨씬 유연하고 강력합니다. .. 그러나 나는 산만하다.)
내가 원하는 것을 이해하면 리더의 ID를 전달한 다음 해당 리더의 팔로워가 게시 한 게시물 만 보려고합니다. 나는 그 권리를 얻었기를 바랍니다. 그것이 옳지 않다면, 내가 말한 것을 취하여 그것을 당신의 필요에 맞게 조정해야합니다. 테이블 구조를 고수하겠습니다 . a leader_id
와 a가 follower_id
있습니다. 따라서 JOIN은 {$wpdb->posts}.post_author
'user_relationship'테이블의 'follower_id'에 대한 외래 키로 사용됩니다.
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;
}