WordPress URLs without posts

时间:2014-08-11 作者:Karel Attl

我们正在开发基于WordPress的更大系统,但WordPress只用于“静态”内容,系统的主要部分应该是使用外部API和显示数据。

我的观点是:我是否能够告诉URL重写不要对某些URL使用WordPress内部系统,而使用其他系统?

E、 g。mysite.com/news/news-title 会显示帖子,但是mysite.com/customcontent/anotherlink 将调用某种机制从API加载数据并显示它。

我不知道WordPress是否能做到这一点。。谢谢你的观点。

1 个回复
最合适的回答,由SO网友:gmazzap 整理而成

是的,这是可能的。

WordPress前端工作流可以概括如下:

通过对照所有默认值检查当前url,访问urlcustom rewrite rules url已“转换”为的一组参数WP_Query. 这是由parse_request 的实例的方法WP 类存储在全局$wp 变量WP_Query (保存在$wp_query 全局变量)用于查询数据库并获取与在点#2检索到的参数相关的帖子。这被称为“主查询”

  • 根据查询参数,根据template hierarchy 它被加载并用于显示结果,因此,即使您注册了一组自定义重写规则,它们也将用于查询帖子。

    然而,如果你看看source of parse_request method, 在第一行中,您可以看到:

    if ( ! apply_filters( \'do_parse_request\', true, $this, $extra_query_vars ) )
      return;
    
    因此,通过将回调附加到“do\\u parse\\u request”过滤器,您可以停止WordPress解析过程并执行任何需要的操作。

    有不同的方法来完成这项任务,为了简单起见,这里我将给你一个粗略的例子。

    如前所述,我们需要使自定义url与something,可能是一个回调,用于检索一些数据和显示数据的视图。

    为了使代码可重用,我们可以使用一个通过过滤器接受自定义url设置的类,并使用该自定义url设置来显示我们需要的任何内容,使用回调来获取一些数据,并使用视图来显示它们。

    class MyCustomUrlParser {
    
      private $matched = array();
    
      /**
       * Run a filter to obtain some custom url settings, compare them to the current url
       * and if a match is found the custom callback is fired, the custom view is loaded
       * and request is stopped.
       * Must run on \'do_parse_request\' filter hook.
       */
      public function parse( $result ) {
        if ( current_filter() !== \'do_parse_request\' ) {
          return $result;
        }
        $custom_urls = (array) apply_filters( \'my_custom_urls\', array() );
        if ( $this->match( $custom_urls ) && $this->run() ) {
          exit(); // stop WordPress workflow
        }
        return $result;
      }
    
      private function match( Array $urls = array() ) {
        if ( empty( $urls ) ) {
          return FALSE;
        }
        $current = $this->getCurrentUrl();
        $this->matched = array_key_exists( $current, $urls ) ? $urls[$current] : FALSE;
        return ! empty( $this->matched );
      }
    
      private function run() {
        if (
          is_array( $this->matched )
          && isset( $this->matched[\'callback\'] )
          && is_callable( $this->matched[\'callback\'] )
          && isset( $this->matched[\'view\'] )
          && is_readable( $this->matched[\'view\'] )
        ) {
          $GLOBALS[\'wp\']->send_headers();
          $data = call_user_func( $this->matched[\'callback\'] );
          require_once $this->matched[\'view\'];
          return TRUE;
        }
      }
    
      private function getCurrentUrl() {
        $home_path = rtrim( parse_url( home_url(), PHP_URL_PATH ), \'/\' );
        $path = rtrim( substr( add_query_arg( array() ), strlen( $home_path ) ), \'/\' );
        return ( $path === \'\' ) ? \'/\' : $path;
      }
    
    }
    
    这是一个粗糙的类,允许用户通过过滤器(“my\\u custom\\u url”)设置自定义url设置。自定义url设置必须是一个数组,其中键是相对url,每个值都是一个包含两个键控值的数组:一个键为“callback”,另一个键为“view”。

    回调是可调用的(任何is_callable 返回true),视图是一个文件,用于呈现中的视图文件中可调用和可访问的$data 变量

    下面是一个如何使用该类的示例。

    // first of all let\'s set custom url settings
    add_filter( \'my_custom_urls\', \'set_my_urls\' );
    
    function set_my_urls( $urls = array() ) {
      $my_urls = array(
         \'/customcontent/alink\' => array(
           \'callback\' => \'my_first_content_callback\',
           \'view\'     => get_template_directory() . \'/views/my_first_view.php\'
         ),
         \'/customcontent/anotherlink\' => array(
           \'callback\' => \'my_second_content_callback\',
           \'view\'     => get_template_directory() . \'/views/my_second_view.php\'
         )
      );
      return array_merge( (array) $urls, $my_urls ); 
    }
    
    // require the file that contain the MyCustomUrlParser class
    require \'/path/to/MyCustomUrlParser\';
    
    // attach MyCustomUrlParser::parse() method to \'do_parse_request\' filter hook
    add_filter( \'do_parse_request\', array( new MyCustomUrlParser, \'parse\' ) );
    
    当然,我们需要写my_first_content_callbackmy_second_content_callback 还有my_first_view.phpmy_second_view.php.

    例如,回调如下:

    function my_first_content_callback() {
      $content = get_transient( \'my_first_content\' );
      if ( empty( $content ) ) {
         $api = a_method_to_get_an_external_api_object();
         $json = $api->fetch_some_json_data();
         $content = json_decode( $json );
         // cache content for 1 hour
         set_transient( \'my_first_content\', $content, HOUR_IN_SECONDS );
      }
      return $content;
    }
    
    请注意,回调返回的内容都存储在$data 可在视图中访问变量。事实上,视图文件的显示方式如下:

    <?php get_header(); ?>
    
    <h1>My Content from API</h1>
    
    <div>
       <pre><?php print_r( $data ); ?></pre>
    </div>
    
    <?php get_footer() ?>
    
    这是可行的,并且可以很好地重用,您可以使用\'my_custom_urls\' 滤器

    然而,也有缺点:所有与当前url的匹配都是通过精确匹配完成的,但是使用正则表达式匹配系统,这对于大型项目来说会更好,因为您可以使用url将一些变量传递给回调。

    E、 g.如果您有如下url设置:

    \'/customcontent/alink/page/{page}\' => array(
       \'callback\' => \'my_first_content_callback\',
       \'view\'     => get_template_directory() . \'/views/my_first_view.php\'
    ) 
    
    使用regex系统可以使{page} 部件变量和匹配的值可以传递给回调以检索不同的数据。

    这就是通常所说的routing system, 还有一些有用的PHP库,如FastRoute, PuxSymfony Routing Component 这可以帮助您使用我在这里介绍的工作流,并在WordPress中构建自己的基于regex的路由系统。

    如果您有PHP 5.4+(这是非常推荐的),那么a plugin I wrote called Cortex 它实现了Symfony路由组件,使其在WordPress中既可用于标准WordPress查询(显示帖子),也可用于您需要的自定义内容。

  • 结束

    相关推荐