【问题标题】:How can I in Wordpress use page template file dynamically?如何在 Wordpress 中动态使用页面模板文件?
【发布时间】:2021-04-28 17:18:10
【问题描述】:

是否可以在 Wordpress 中有一个模板页面,可以动态用于不同的页面?

例如,我有一个页面模板cars.php,我想将它用于不同类型汽车的子页面,例如: 豪华轿车, 轿跑车, 越野车, 面包车。

我想要这样的页面层次结构:

cars ─┬─limousine
      │
      ├─coupe
      │
      ├─suv
      │
      └─van
 

使用此链接:

example.com/cars/limousine/
example.com/cars/coupe/
example.com/cars/suv/
example.com/cars/van/

这些类型的汽车来自一个数据库,我们可以在其中添加一种新类型的汽车,比如蜘蛛。

我知道如何手动执行此操作,即制作页面 limousine、coupe、suv、van 和 spider 使用 Wordpress 编辑器创建它们,我会选择 car.php 作为模板。

因此,如果用户单击example.com/cars/limousine/ 链接,我将在我的cars.php 页面模板中获取例如豪华轿车类型的数据。我应该如何使用我的cars.php 页面模板才能获得具有指定层次结构的页面?如果我没有明确创建每个页面(豪华轿车、双门轿车、SUV、面包车和蜘蛛),Wordpress 将如何识别链接,有关特定页面的信息如何传递给cars.php

最好的问候,

伊戈尔

【问题讨论】:

    标签: php wordpress


    【解决方案1】:

    已编辑帖子

    我已经删除了我原来的回复,因为它妨碍了我。

    WordPress(以及许多/最现代的 CMS)的工作方式是,它们告诉 Apache、Nginx 或 IIS 等服务器执行其正常工作,但如果服务器产生有效的 404,则将该结果传递给CMS 在已知点 (index.php) 进行进一步处理。

    服务器级别

    您可以挂钩的第一个地方是使用 .htaccess 文件之类的服务器级别。你可以有一个规则将/cars/* 映射到/cars/?car_type=*。不重定向,只是映射。该地图应在服务器级别产生有效的 404,这意味着 WordPress 使用已知 URL 和可以忽略的查询字符串启动。 (我 95% 确信这会起作用,但我现在没有可用于测试的 Apache 服务器。)您可以注册查询参数,或者您可以只使用 $_GET 并执行逻辑。

    但我不是编辑服务器配置文件的忠实粉丝,尤其是如果这需要更加动态,或者由习惯这样做的人管理。

    WordPress 级别

    所以下一站是在 WordPress 中以某种方式处理事情。坏消息是,无论您做什么,WordPress 都会将此视为 404。但好消息是,您可以根据需要重新路由 404。

    我将继续使用/cars/limo 路径,但您可以根据需要进行调整。

    前两个步骤是可选的,但更接近于“官方”的做事方式,我鼓励你这样做,但我稍后会解释如何跳过它们。

    首先,我们需要在 WordPress 中注册一个我们感兴趣的模式。第一个参数是一个正则表达式,第二个是一个映射,最后一个说我们基本上想要胜过其他规则。 添加此代码或对其进行任何更改时,您需要刷新 WordPress 永久链接。此外,如果您在本地开发并且根本没有启用重写,则需要打开它们。

    add_action(
        'init',
        static function () {
            add_rewrite_rule('cars/(.+)[/]?$', 'index.php?car_type=$matches[1]', 'top');
        }
    );
    

    然而,前面的事情并没有做很多事情,所以我们还需要告诉 WordPress 我们对某些查询字符串感兴趣。这个查询字符串在前面和后面的函数之间应该是相同的。

    add_filter(
        'query_vars',
        static function ($query_vars) {
            $query_vars[] = 'car_type';
            return $query_vars;
        }
    );
    

    最后一步是使用神奇的template_include 过滤器和get_query_var。此过滤器在每个非管理页面上调用,因此请小心处理,并确保仅在保证处于特定场景时才更改返回。 get_query_var 能够提取出我们在第二步中注册的查询字符串。

    add_filter(
        'template_include',
        static function ($template) {
            $car_type = get_query_var('car_type');
            if ($car_type) {
                // The path must be absolute
                return __DIR__ . '/cars.php';
            }
    
            return $template;
        }
    );
    

    对于if 逻辑,您可能需要执行其他操作,例如检查数组以查看它是否在已知类型的集合中。如果可能的话,您真的应该避免在此处进行数据库调用,因为请记住,这是在每个页面上调用的。

    跳过前两步

    如果确实说过您可以跳过前两个步骤,虽然我不推荐这样做,但我想向您展示如何做到这一点。我们仍将使用template_include 钩子,但现在我们将手动查看 URL 并使用它进行操作。这不能保证在不同的服务器环境中存活,并且您可能会遇到一些时髦的场景,所以我说跳过它。我也不打算包含计算页面本身的逻辑,这也应该很容易。

    add_filter(
        'template_include',
        static function ($template) {
            $url = wp_parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
            if( YOUR LOGIC FOR PARSING URL HERE ){
                return 'cars.php';
            }
    
            return $template;
        }
    );
    

    【讨论】:

    • 谢谢@Chris Haas。你显然在这里摇滚!但我不知道我是否清楚。我有cars.php 页面模板。我想动态创建子页面。如果用户单击 example.com/cars/van/,我希望它是即时创建的,而不需要制作 van page。我简化了这一点——我们不卖汽车,我们卖灯,所以产品种类更多。我想避免在汽车模板页面下方的级别中制作 30 多个页面。我想使用父级别的页面模板动态生成这些页面。也许我应该把模板放在子级——我不知道,我在问。
    • @IgorBeuermann,我想我现在明白了,我已经更新了我的答案,希望能奏效。我假设一旦你进入cars.php,你就会去你自己的桌子或做一些其他的逻辑来区分这些 URL。上面的代码会加载你的模板,剩下的交给你,祝你好运!
    • @IgorBeuermann,为了清楚起见,在template_include 过滤器中,您唯一应该做的就是返回磁盘上要使用的模板。除非您正在调试某些东西,否则您不应该执行任何echoinclude 或任何其他可能改变该过滤器流程的操作。那是你在做什么吗?另外,为了确保在您更改重写规则后,您是否刷新了永久链接?
    • @IgorBeuermann,我在上面做了一个更新,并使用return __DIR__ . '/cars.php'; 将模板更改为绝对模板(假设此代码位于functions.php)。如果您在template_include 内部进行调试,请始终发出die,因为您会看到之后发生的“其他事情”可能会使实际发生的事情变得混乱。我创建了一个快速演示站点,创建了一个 URL 为 /products/ 的页面,然后创建了另一个页面作为它的子页面,其 URL 为 /products/car,更新了重写,刷新并访问了 /products/car/limo/,一切正常。
    • 很高兴它正在工作!如果您将 Yoast 用于面包屑并卡住,请查看过滤器 wpseo_breadcrumb_links 并在您有问题时发布。如果你愿意,你可以在这个线程中标记我作为提醒
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-01-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多