我仍在努力满足确切的需求,但如果我理解正确,我认为如果您使用我在下面提供的代码,然后执行以下操作,您可以实现您的目标:
为您的每个服务创建一个页面(听起来您已经这样做了):/service1/
, /service2/
, 等
创建一个“基本”服务页面,URL为/base-service/
; 别担心,没有人会在网站外部看到这一点。
分配/base-service/
作为每个服务下要复制的所有“虚拟共享”子页面的父页面(或祖父母页面)。
创建您可能想要的任何特定于服务的页面,并将其分配到适当的页面(例如“服务2”)
创建page template in your theme 为您的服务致电page-service.php
并确保您的每个服务页面都使用该页面模板(这是必需的,以便我们可以确定您的哪些页面是服务页面)。
这是我调用的类的代码Yoursite_SharedChildPages
可以存储在主题的functions.php
文件,或在.php
您可能正在为站点编写的插件文件:
if (!class_exists(\'Yoursite_SharedChildPages\')) {
class Yoursite_SharedChildPages {
// If wanted we could enhance to allow these values to be defined in an \'init\' hook
static $PAGE_TEMPLATE = \'page-service.php\';
static $ABSTRACT_ROOT = \'base-service\';
static function on_load() {
// Hook \'request\' to route the request correctly
add_filter(\'request\',array(__CLASS__,\'request\'));
// Hook \'page_link\' to compose URLs correctly
add_filter(\'page_link\',array(__CLASS__,\'page_link\'));
}
static function request($query_vars) {
if (!empty($query_vars[\'pagename\'])) {
// If the page URL rewrite matched meaning WordPress thinks it\'s a Page
// Split the URL path by path segments (i.e. by slashes)
$pagename = explode(\'/\',$query_vars[\'pagename\']);
if ($pagename[0] == self::$ABSTRACT_ROOT) {
// If the first path segment is the abstract root we care about
if (count($pagename)==1) {
// Don\'t allow anyone to visit this abstract root page
$pagename = array(\'#\'); // An invalid page name, so it will 404
} else {
// If it is a child page in which case redirect to the first service
// This is important so the user can view the page after they edit it
$pages = self::get_page_ids_by_template(self::$PAGE_TEMPLATE);
if (isset($pages[0]) && $page = get_post($pages[0])) {
// Assuming we have at least one page with the page template
$pagename[0] = $page->post_name;
// then redirect to it the first service found.
wp_safe_redirect(\'/\'.implode(\'/\',$pagename).\'/\');
exit;
}
}
} else if (count($pagename)>1) {
// If there are child pages
if (get_page_by_path($query_vars[\'pagename\'])) {
// If it is an actual child page then just let it pass thru
} else {
// If a virtual child page then see if parent has the template
$parent = get_page_by_path($pagename[0]);
$pages = self::get_page_ids_by_template(self::$PAGE_TEMPLATE);
if (in_array($parent->ID,$pages)) {
// If virtual child of a service page, change parent to the abstract root
$pagename[0] = self::$ABSTRACT_ROOT;
$query_vars[\'pagename\'] = implode(\'/\',$pagename);
// The URL doesn\'t match a virtual page, will appropriately get a 404
}
}
} else {
$pagename = false;
}
}
if (is_array($pagename))
$query_vars[\'pagename\'] = implode(\'/\',$pagename);
return $query_vars;
}
static function get_page_ids_by_template($template) {
// This can be performance optimized but I wouldn\'t worry about it
// until there is a performance issue
global $wpdb;
$sql = "SELECT post_id FROM {$wpdb->postmeta} " .
"WHERE meta_key=\'_wp_page_template\' AND meta_value=\'%s\'";
return $wpdb->get_col($wpdb->prepare($sql,$template));
}
static function page_link($link) {
$parts = explode(\'/\',$link);
if ($parts[3]==self::$ABSTRACT_ROOT) {
// This is really only useful for links in the admin.
if (!is_admin()) {
global $wp_query;
if (!empty($wp_query->query_vars[\'pagename\'])) {
$pagename = explode(\'/\',$wp_query->query_vars[\'pagename\']);
}
} else {
// If we get a URL that uses the abstract root, assign it the first service.
$pages = self::get_page_ids_by_template(self::$PAGE_TEMPLATE);
if (isset($pages[0]) && $page = get_post($pages[0])) {
// Assuming we have at least one page with the page template
$parts[3] = $page->post_name;
// then redirect to it the first service found.
$link = implode(\'/\',$parts);
} else {
$link = preg_replace(\'#^(https?://[^/]+)(/.*)$#\',\'$1\',$link);
}
}
}
return $link;
}
}
Yoursite_SharedChildPages::on_load();
}
下面是一些屏幕截图,可以说明上述步骤:
如果这不是您想要的,和/或除了我编写的代码之外,如果您遇到了此解决方案需要解决的问题,请告诉我。祝你好运