티스토리 뷰

 

Wordpress의 Custom Theme를 만들다 보면 몇몇 답답함들이 있다.

그 중 하나는 page-{slug}.php와 같이 페이지에 대한 테마 파일을 연결할 때 항상 최상위 디렉토리에 존재해야 한다는 점이다. 하위 디렉토리에 존재하게 될 경우 Wordpress는 자동으로 찾아주지 못하기 때문에 이를 위해 여러가지를 조합해 특별힌 function을 만들어 사용하기도 한다. 하지만.. 이 마저도 각각의 맹점들을 가지고 있어 특별히 권장되는 사항은 아니다. 

 

페이지에 대해 상위 페이지를 줄경우 domain.co.kr/parent/child/와 같이 URL을 설정할 수 있다.

그럼에도 슬러그는 child이기에 wordpress는 최상위 디렉토리에서 page-child.php를 찾게 된다. 

 

이때 우리가 원하는 것은 theme_name/parent/page-child.php 파일로 연결하는 것이고 이에 대한 방법을 본 페이지를 통해 기술하고자 한다. 이는 필자가 가장 오랫동안 답답함을 느껴온 장벽이였고 내 손에서 탄생한 수많은 프로젝트들의 오점이였기 때문이다. 

 

 

 


어투가 바뀌었지만 신경쓰지 않아 주셨으면 합니다. 

우선 워드프레스의 템플릿 파일 탐색 순서에 대한 이해가 필요합니다.

 

템플릿 계층 구조 내의 페이지 템플릿

클라이언트가 웹 사이트를 탐색하면 WordPress는 해당 페이지를 렌더링하는 데 사용할 템플릿을 선택합니다. WordPress는 다음 순서로 템플릿 파일을 찾습니다.

  1. Page Template —  페이지에 사용자 지정 템플릿이 할당된 경우 WordPress는 해당 파일을 찾아 찾은 경우 이를 사용합니다.
  2. page-{slug}.php —  사용자 지정 템플릿이 할당되지 않은 경우 WordPress는 페이지의 슬러그가 포함된 특수 템플릿을 찾아 사용합니다.
  3. page-{id}.php —  페이지의 슬러그를 포함하는 특수 템플릿을 찾을 수 없는 경우 WordPress는 페이지 ID로 명명된 특수 템플릿을 찾아 사용합니다.
  4. page.php —  페이지의 ID를 포함하는 특수 템플릿을 찾을 수 없는 경우 WordPress는 테마의 기본 페이지 템플릿을 찾아 사용합니다.
  5. singular.php— page.php를 찾을 수 없으면 워드프레스는 게시물 유형에 관계없이 단일 게시물에 사용된 테마의 템플릿을 찾아 사용합니다.
  6. index.php —  특정 페이지 템플릿이 지정되거나 발견되지 않으면 WordPress는 기본적으로 테마의 인덱스 파일을 사용하여 페이지를 렌더링합니다.

 

 

 

실제 코드

/**
 * 상위 페이지가 있는 페이지에 접속시 theme/{상위페이지 Post_name}/page-{$}.php 파일을 사용할 수 있도록 한다
 * page_template 필터를 이용해 어떤 파일을 선택할지 locate_template 함수를 사용한다.
 * URL : https://domain.co.kr/상위 페이지/하위페이지/
 */
function child_templates($template) {
	global $post;

	if ($post->post_parent) {
		// get top level parent page
		$parent = get_post(
		   reset(array_reverse(get_post_ancestors($post->ID)))
		);

		$child_template = locate_template(
			[
				urldecode($parent->post_name) . '/page-' . urldecode($post->post_name) . '.php',
				urldecode($parent->post_name) . '/page-' . $post->ID . '.php',
				urldecode($parent->post_name) . '/page.php',
			]
		);

		if ($child_template) return $child_template;
	}
	return $template;
}
add_filter('page_template', 'child_templates');

1. page-{slug}.php 파일에 대한 존재 유무를 확인하는 것 보다 해당 페이지에 템플릿이 존재하는 지에 대한 여부를 확인하는 것이 우선순위가 더 높습니다.  이때 'page_template'가 발생하므로 filter를 통해 이를 매칭시켜줄 것 입니다.

2. 현재 불러오는 Page에 상위 페이지가 존재하는 경우 상위페이지의 이름을 가져와 디렉토리 명으로 사용합니다.

   => 상위페이지 이름은 URL 인코딩이 되어 있으므로 디코딩해줍니다. (한글과 같은 문자를 사용할 수 있기 때문)

3. 해당 디렉토리 밑에 있는 page-{slug}.php, page-{id}.php, page.php 파일을 탐색해 존재하면 매칭시켜줍니다.

 

 

참고)

  • WP_post에서 'post_name'은 테이블에서 고유한 값으로 Slug로 사용됩니다. 제목과 혼동하여서는 안됩니다. 

 

 

 

 


locate_template( string|array $template_names, bool $load = false, bool $require_once = true, array $args = array() )

https://developer.wordpress.org/reference/functions/locate_template/

 

WordPress Developer Resources | Official WordPress Developer Resources

Official WordPress developer resources including a code reference, handbooks (for APIs, plugin and theme development, block editor), and more.

developer.wordpress.org

 

댓글