花式 URL 结构、条件内容和搜索 - 使用 CPT、自定义字段和分类法

Fancy URL structure, conditional content, and search - using CPT, custom fields and taxonomies

我们正在为美国、加拿大和墨西哥这 3 个国家/地区的 automotive-related 企业建立目录。

我创建了一个自定义 post 类型 'Listings' 并尝试继续以下操作。

出于各种 SEO 目的,我们需要如下特定的 URL 结构:

1) 个人列表页面

没什么特别的 - domain.com/usa/listing-slug

2) Per-state 档案

没什么特别的 - domain.com/usa/texas

3) Per-city 档案

这个比较有意思,我们需要这样的结构:

第一个是俄亥俄州克利夫兰的存档,另一个是内华达州克利夫兰的存档。

4) Per-ZIP 档案

很平常 - 域。com/usa/05657

5) 混合location-category 档案

6) 以上所有存档页面的自定义内容(模板),ZIP

除外

我们正在尝试模仿 this website

如果您查看俄亥俄州克利夫兰和内华达州克利夫兰的相同示例:http://www.familydaysout.com/kids-things-to-do-usa/cleveland/oh and http://www.familydaysout.com/kids-things-to-do-usa/cleveland/nd您会明白我的意思 - 这些页面在开头具有自定义内容(描述)。

以上是 per-city 自定义内容示例。 per-state http://www.familydaysout.com/kids-things-to-do-usa/ohio 和混合也是如此: http://www.familydaysout.com/kids-things-to-do-usa/ohio/major-theme-parks http://www.familydaysout.com/kids-things-to-do-usa/cleveland/oh/major-theme-parks http://www.familydaysout.com/kids-things-to-do-usa/5601/major-theme-parks

我已经到了添加新列表时可以 auto-populate 位置数据的地步,所以当我粘贴完整地址时,例如“21200 Saint Clair Avenue Euclid, Ohio 44117”并保存我得到这个:

如您所见,国家、州、城市和邮政编码都在那里。类别(汽车零件)也作为列表类别。

现在如何使用这些值来构造 URLs 和 pages/templates 用于存档?我应该自动将自定义字段值转换为自定义分类法并从那里开始吗?我知道我可以用 https://codex.wordpress.org/Plugin_API/Action_Reference/save_post and https://codex.wordpress.org/Function_Reference/wp_set_object_terms

做到这一点

我知道自定义分类法可以有描述,我知道如何输出这些描述。除此之外,分类法可以是分层的,因此我可以将俄亥俄州和内华达州添加为 parents,并将每个克利夫兰添加为 child。

所以我正处于设法收集和存储所有信息位的地步,但不确定如何开始操纵它们以实现上述模型。

Q1:我应该在哪里存储位置数据(国家、州、城市、邮政编码)以便能够如上所述在 URL 中使用它?自定义字段或分类术语?

问题 2:如何按照上述方式构建存档 pages/templates,以便为它们自定义模板?

任何其他有用的提示将不胜感激。

根据您的要求,您可以通过如下所述创建类别来实现此目的:

domain.com/usa/cleveland/oh and domain.com/usa/cleveland/nd

  1. 俄亥俄州克利夫兰 (/usa/cleveland/oh)
  2. 内华达州克利夫兰 (/usa/cleveland/nd)

因此,创建一个父类别 "USA",然后创建子类别 "Cleveland",再在该子类别下创建一个子类别 "Ohio",其子类别 "oh"。

所以层次结构应该是 USA->Cleveland->Ohio 并且在 slugs 中它应该是 usa->cleveland->oh

类似地,USA->Cleveland->Nevada 和 slug 作为 usa->cleveland->nd

现在,要在 URL 显示的帖子:

  1. 域。com/category/usa = 提供它们 "USA" 类别
  2. domain.com/category/usa/cleveland/ = 提供它们 "Cleveland" 类别
  3. domain.com/category/usa/cleveland/oh = 提供它们 "Ohio" 类别

现在您只需要从 URL 中删除 category 。因此,为此在位于根文件夹的 .htaccess 文件中写入以下代码。

RewriteRule . /wordpress/index.php [L]

我认为有两种方法可以解决您的问题 第一个是使用 mod_rewrite 将您建议的格式化 URL 传输到关联模板 php 文件,并在那里按照您想要的方式处理您的请求。 为此,以下 link 可能会有所帮助。 Google 更多 https://www.addedbytes.com/articles/for-beginners/url-rewriting-for-beginners/

第二种方法是遵循 wordpress 页面模板层次结构并相应地创建模板页面并在模板中处理类似的请求 php。详细解释参考https://www.smashingmagazine.com/2015/06/wordpress-custom-page-templates/

以及一个快速的页面模板层次结构,以了解哪个页面模板将针对特定 url 执行,请参阅 https://media-mediatemple.netdna-ssl.com/wp-content/uploads/2015/05/01-wp-template-hierarchy-opt.jpg

经过四处寻找,我想我现在可以帮到你了。

1。注册 location 分类法以创建基本存档 slug:

function wpso36667674_register_location_taxonomy() {
    $labels = [
        'name'          => _x('Locations', 'Taxonomy General Name', 'wpso'),
        'singular_name' => _x('Location', 'Taxonomy Singular Name', 'wpso'),
        'all_items'     => __('All Locations', 'wpso'),
    ];
    $args = [
        'labels'        => $labels,
        'public'        => true,
        'hierarchical'  => true,
        'rewrite'       => ['hierarchical' => true],
    ];
    register_taxonomy('location', 'listing', $args);
}
add_action('init', 'wpso36667674_register_location_taxonomy', 0);

我们必须将 WordPress 自动生成的术语 slug 更改为经过清理的术语名称,以便 URL 的结构看起来如您所愿:

function wpso36667674_filter_term_link($term_link, $term, $taxonomy) {
    $term_link = rtrim($term_link, '/');
    $pos = strrpos($term_link, '/');
    $term_link = substr($term_link, 0, $pos + 1) . sanitize_title($term->name);
    return $term_link;
}
add_filter('term_link', 'wpso36667674_filter_term_link', 0, 3);

注意:添加新词条时不要手动输入词条,让WordPress为我们生成,否则我们将无法查询词条post内容正确。原因是这两个 URL:location/usa/ohio/clevelandlocation/usa/idaho/cleveland 给我们相同的 posts 因为 WordPress 只使用 cleveland 作为查询 posts 内容的术语而不关心父术语。

2。注册 listing post 输入如下:

function wpso36667674_register_listing_post_type() {
    $labels = [
        'name'          => _x('Listings', 'Taxonomy General Name', 'wpso'),
        'singular_name' => _x('Listing', 'Taxonomy Singular Name', 'wpso'),
        'all_items'     => __('All Listings', 'wpse'),
    ];
    $args = [
        'labels'        => $labels,
        'public'        => true,
        'menu_icon'     => 'dashicons-location-alt',
        'menu_position' => 6,
        'supports'      => ['title', 'editor', 'thumbnail', 'custom-fields'],
        'taxonomies'    => ['location'],
        'rewrite'       => ['slug' => '%country%/%state%/%city%/%zip%'],
    ];
    register_post_type('listing', $args);
}
add_action('init', 'wpso36667674_register_listing_post_type', 0);

我们不确定房源是否有 state|city|zip,所以我们必须使用替代品 (%country%/%state%/%city%/%zip%)。然后用每个列表元数据替换它(根据我使用 WordPress 的经验,您应该在每个列表中存储位置数据):

function wpso36667674_filter_post_link($post_link, $post, $leave_name = false, $sample = false) {
    $zip = get_post_meta($post->ID, 'geolocation_postcode', true);
    $city = get_post_meta($post->ID, 'geolocation_city_short', true);
    $state = get_post_meta($post->ID, 'geolocation_state_short', true);
    $country = get_post_meta($post->ID, 'geolocation_country_short', true);
    $post_link = str_replace('%zip%', $zip, $post_link);
    $post_link = str_replace('%city%', $city, $post_link);
    $post_link = str_replace('%state%', $state, $post_link);
    $post_link = str_replace('%country%', $country, $post_link);
    $post_link = preg_replace('/[^:](\/{2,})/', '/', $post_link);  // Remove multiple forward slashes except http://.
    return $post_link;
}
add_filter('post_type_link', 'wpso36667674_filter_post_link', 0, 4);

注意:如果您使用大写短名称,则在修改 URL 结构时必须将其转换为小写。

3。添加重写规则以使我们的自定义 URL 正常工作。

// Add rewrite rules for location taxonomy.
function wpso36667674_add_location_rewrite_rules() {
    add_rewrite_rule('^location/([^/]+)/?$', 'index.php?taxonomy=location&term=$matches[1]', 'top');
    add_rewrite_rule('^location/([^/]+)/([^/]+)/?$', 'index.php?taxonomy=location&term=$matches[2]', 'top');
    add_rewrite_rule('^location/([^/]+)/([^/]+)/([^/]+)/?$', 'index.php?taxonomy=location&term=$matches[3]', 'top');
}
add_action('init', 'wpso36667674_add_location_rewrite_rules', 0);

// Add rewrite rules for listings.
function wpso36667674_add_listing_rewrite_rules() {
    add_rewrite_rule('^usa/([^/]+)/?$', 'index.php?post_type=listing&name=$matches[1]', 'top');
    add_rewrite_rule('^usa/([^/]+)/([^/]+)/?$', 'index.php?post_type=listing&name=$matches[2]', 'top');
    add_rewrite_rule('^usa/([^/]+)/([^/]+)/([^/]+)/?$', 'index.php?post_type=listing&name=$matches[3]', 'top');
    add_rewrite_rule('^usa/([^/]+)/([^/]+)/([^/]+)/([^/]+)/?$', 'index.php?post_type=listing&name=$matches[4]', 'top');
    add_rewrite_rule('^mexico/([^/]+)/?$', 'index.php?post_type=listing&name=$matches[1]', 'top');
    add_rewrite_rule('^mexico/([^/]+)/([^/]+)/?$', 'index.php?post_type=listing&name=$matches[2]', 'top');
    add_rewrite_rule('^mexico/([^/]+)/([^/]+)/([^/]+)/?$', 'index.php?post_type=listing&name=$matches[3]', 'top');
    add_rewrite_rule('^mexico/([^/]+)/([^/]+)/([^/]+)/([^/]+)/?$', 'index.php?post_type=listing&name=$matches[4]', 'top');
    add_rewrite_rule('^canada/([^/]+)/?$', 'index.php?post_type=listing&name=$matches[1]', 'top');
    add_rewrite_rule('^canada/([^/]+)/([^/]+)/?$', 'index.php?post_type=listing&name=$matches[2]', 'top');
    add_rewrite_rule('^canada/([^/]+)/([^/]+)/([^/]+)/?$', 'index.php?post_type=listing&name=$matches[3]', 'top');
    add_rewrite_rule('^canada/([^/]+)/([^/]+)/([^/]+)/([^/]+)/?$', 'index.php?post_type=listing&name=$matches[4]', 'top');    
}
add_action('init', 'wpso36667674_add_listing_rewrite_rules', 0);

4。 Return 返回正确的词条:

正如我所说,通过将永久链接中的 usa/idaho/cleveland-idaho 更改为 usa/idaho/clevelandusa/idaho/cleveland 的查询 post 与 usa/ohio/cleveland 相同。因此,我们必须帮助 WordPress 了解用于查询 posts' 内容的正确术语 slug 是什么:

function wpso36667674_modify_requested_url($query) {
    if ( $query->query_vars['taxonomy'] === 'location' ) {
        $slugs = array_filter( explode('/', $query->request) );
        $term = array_pop($slugs) . '-' . array_pop($slugs);
        if ( get_term_by('slug', $term, 'location') ) {
            $query->query_vars['term'] = $term;
        }
    }
}
add_action('parse_request', 'wpso36667674_modify_requested_url');

感谢 @Jevuska 建议使用 parse_request

5。为每个存档位置创建自定义模板:

感谢WordPress Template Hierarchy,我们可以轻松做到。

示例:

对于 location/usa/ohio,模板将是 taxonomy-location-ohio.php

但请记住,我们必须使用 WordPress 生成的实际术语段,而不是我们在 URL 中修改的段段。

示例:

如果在爱达荷州的克利夫兰之前添加俄亥俄州的克利夫兰,则第一个术语 slug 是 cleveland,第二个将是 cleveland-idaho

那么,第一个的模板是taxonomy-location-cleveland.php,第二个是taxonomy-location-cleveland-idaho.php

就是这样!您可以直接将所有代码放入 functions.php 文件中。记住也要刷新永久链接设置。