워드프레스 Query
워드프레스는 한 화면을 로딩할 때, 여러개의 쿼리를 요청하여서 화면에 랜더링.
주로 wordpress loop가 동작할 때, 해당 쿼리의 결과를 loop가 돌면서 화면으로 랜더링한다.
자세히 설명하면, 워드프레스의 랜더링 방식은
- 헤더 -> 워드프레스 루프() -> 쿼리 결과값을 랜더링
- 사이드바 -> 워드프레스 루프() -> 쿼리 결과값을 랜더링
- 컨텐츠(본문) -> 워드프레스 루프() -> 쿼리 결과값을 랜더링
이러한 방식으로 랜더링을 한다.
메인 쿼리는 사용자에 동작에 직접적으로 반응하는 쿼리
wordpress가 request URI에 표시 할 내용을 결정할 때, 자동으로 트리거 되는 쿼리.
사용자가 검색어를 입력하여, 검색 작업을 진행할 때,
url 형식은 [ /?s=검색키워드&post_type=product ]
http://martfurysearch.local/?s=phone&post_type=product
워드프레스는 이 url을 구문 분석(parsing)하여, 쿼리문을 작성한다.
wp-core에서 쿼리문를 작성하는 코드 흐름은
- wp-blog-header.php => wp( )
- functions.php => main( )
- class-wp.php => query_posts( )
- class-wp-query.php => query( )
- class-wp-query.php => get_posts( )
- 해당 파일 내 해당 함수 Ln1400 에서 쿼리 완성
- 쿼리의 키워드는 $wpdb -> posts의 값으로 가져오며
- 쿼리에 해쉬값은 prepare( )이 $placeholder 값을 키워드 앞뒤로 붙여줍니다. ( sql injection 대비/wp-db.php에서 해당 작업 처리 Ln2151 )
상단 2번에 main( ) 함수는 주요 로직을 실행
parse_request( )로 요청값을 구문 분석하여 쿼리에 필요한 변수 $query_vars를 세팅,
해당 함수 실행 후 query_posts( )함수가 실행하며, 바인딩 된 $query_vars의 정보를 활용하여 쿼리 생성
class-wp.php [WP] -> 워드프레스 환경설정 클래스
class-wp-query.php [WP_Query] -> 워드프레스 쿼리설정 클래스
%% 코드 리뷰 진행::디버깅 %%
검색창에 iphone 키워드 검색
- [core] index.php => define( 'WP_USE_THEMES')
- require ('wp-blog-header.php')
- [core] wp-blog-header.php => 3가지 큰 작업을 수행
- require('wp-load.php')
- wp()
- require('template-loader.php)
- [core] wp-load.php => [WP enviroment, ABSPATH 변경]
- require ('wp-config.php')
- [core] wp-config.php => [MySQL settings, Secret keys, Database table prefix, WP_DEBUG, ABSPATH]
- [core] wp-settings.php => 초기화에 필요한 파일들을 로드 (상수와 글로벌 변수, 플러그인, 버젼 정보 변수, 캐싱 정보, 코어 클래스 유틸), $wpdb 생성, mysql 연결, WP_Query 인스턴스 생성후 $GLOBALS['wp_the_query'] , $GLOBALS['wp_query']에 바인딩, WP 인스턴스 생성 후 $GLOBALS['wp']에 바인딩, 테마 설치, wp->init(), do_action('init')
- require('wp-settings.php')
- 여기서 해당 흐름은 종료 => 2-2 로직 실행
- [core] wp-blog-header.php => wp() 실행 [wp-settings.php 파일에서 functions.php를 로드하며 해당 파일에 정의 된 wp() 실행
- [core] functions.php => function wp()함수 정의부분
- wp−>main(query_vars) [class-wp.php 클래스 파일]
- public function main()는 6개의 함수를 실행 => 이중 query_posts()실행
- query_posts()는 생성된 $wp_the_query를 가지고 쿼리 스트링을 설정하고, query()함수를 실행 [여기서 쿼리스트링 설정하는 부분이 중요: bulid_query_string()]
- query()는 먼저 init()함수를 실행하고, wp_parse_args()된 결과값을 바인딩하여 get_posts()한다.
- get_posts()는 $wpdb(settings.php에서 생성)를 기반으로 쿼리문을 완성시킨다.
HASH코드는 sql injection 방지를 위해 붙는 해쉬값, esc_url(), $wpdb->prepare로 해쉬값을 붙일 수 있다.
메인 쿼리는 parse_search함수에 실행 결과를 $search변수에 담는데 prepare 메소드는 해당 쿼리에 %를 난독화한다.
add_placeholder_escape
마지막 로드함수 담겨있움 Ln2096참고
sql injection : https://noirstar.tistory.com/264
워드프레스 쿼리 변형
워드프레스 코어는 쿼리가 생성되고, 바인딩 되는 시점에 몇몇 hook 지점을 tag 해 놓았다.
해당 hook에 적합한 접근을 진행하면, 쿼리의 결과를 커스텀 할 수 있다.
클래스의 속성 중 WP_Query->query−>query_vars 라는 변수가 있다.
쿼리 변수의 값을 가지고 있는 연관 배열이다. pre_get_posts 훅으로
$query->query_vars['name'] 혹은 $query->query_vars['meta_key']의 값을 바인딩하고, $query->query_vars['order']='ASC' 로 정렬에 관한 변수를 넣으면, 해당 쿼리는 변경이 된다.
하지만 해당 방식은 한계가 있는데, posts 되기 전 값을 변경하는 것이지, sql을 새로 생성하는 방식은 아니다. 제한적인 sql 수정이 가능한 방식이다,
또한 워드프레스의 meta 정보의 범위까지는 핸들링이 가능하나, 우커머스 테이블로 접근해야 하는 경우 작업이 어려워진다.