9

我想更快地向 WordPress API 发出请求。我的 API 在插件中实现(使用 register_rest_route 注册我的路线)。然而,由于这是一个插件,所有东西都被它加载了(子主题和主题)并且基本上对这个 API 的查询需要半秒钟,因为加载了所有这些无用的部分。

WordPress API 不能以其他方式使用吗?由于大多数使用 WP-API 的插件不需要加载任何其他插件,更不用说主题了……我不明白他们怎么会错过。

有没有办法做到这一点?

4

4 回答 4

12

对的,这是可能的。在我的一个插件中,我需要最小的 WordPress 核心(没有插件和主题的数据库),这就是我所做的:

<?php

define('SHORTINIT', true);  // load minimal WordPress

require_once PATH_TO_WORDPRESS . '/wp-load.php'; // WordPress loader

// use $wpdb here, no plugins or themes were loaded

我编造的PATH_TO_WORDPRESS常数;你只需要指出正确的路径。例如,在插件中,它可能看起来像:

require_once dirname(__FILE__) . '/../../../wp-load.php'; // backwards 'plugin-dir/plugins/wp-content'

设置SHORTINITtrue确实对性能有所帮助。

禁用后,WP_DEBUG引导 WordPress 所需的时间如下:

  • 没有SHORTINIT:~0.045 秒
  • 使用 SHORTINIT:~0.0015 秒

如果这适用于您自己的需要性能的站点,您可以通过启用 OpCache(例如,最近版本中的 APC 或 PHP OpCache)来增加这一点。

SHORTINIT但我相信上面定义和要求的 2 行代码wp-load.php就是你要找的。

澄清一下,这个文件是插件的一部分,但它是独立于 WordPress 本身调用的(通过 Ajax 和直接调用)。它永远不会被插件或 WP 本身的任何其他部分包含或使用。

编辑: 由于 OP 实际上与 WP-API 相关,而不是一般的 WordPress,我添加它是为了解决实际问题。我会留下原来的答案内容,以防它可以帮助别人。

我用 WP API 做了进一步的测试,就像@David 在他的回答中说的那样,问题可能是别的。

除了其余的 api 之外,我还加载了 12 个插件,一些相当“大”的插件,我的本地安装安装了大约 25 个主题(当然一个是活动的)。我编辑了 WordPress 的index.php文件并用于microtime(true)记录一切开始的时间,然后编辑了一个 REST 控制器来计算从开始到到达 API 端点所用的时间。

我系统上的结果始终在0.0462-0.0513秒左右(没有 PHP OpCache,也没有其他系统负载)。因此,似乎引导所有 WordPress 对性能几乎没有影响。

如果请求需要半秒钟,那么瓶颈就在其他地方,并且删除插件和主题的影响将很小。至少这是我发现的。

于 2016-04-04T00:45:41.183 回答
4

我认为您可能专注于错误的问题。

加载 php 文件并不像从您的数据库中读取那么慢,这可能是您的 500 毫秒加载时间。无论如何,您实际上应该考虑减少这种情况(缓存 wp-options 等),但我对您的 api 建议是使用 mu-plugin 缓存输出。使用 exit 我们可以从文件加载输出并立即提供。

我们的方法: 1.在wp-content文件夹中创建一个文件mu-plugins夹(可能已经有)

  1. 创建一个名为api-cache.php

  2. 将此代码输入到您的文件中:

    function get_api_cache(){
    
        //dont run if we are calling to cache the file (see later in the code)
        if( isset($_GET['cachecall']) && $_GET['cachecall'] === true)
            return;
    
        $url = "$_SERVER[REQUEST_URI]";
    
        //do a little error checking
    
        $uri= explode('/',$url);
    
        //we have a array (1st key is blank)
        if( $uri[1] !== 'wp-json' || $uri[2] !== 'wp' || $uri[3] !== 'v2'){
            return;
        } 
    
        //lock down the possible endpoints we dont want idiots playing with this...
        $allowed_endpoints= array(
            'posts'
        );
    
        $endpoint= array_pop($uri); // not sure if this is valid or not, is there more structure to some api calls?
    
        if( !in_array( $endpoint, $allowed_endpoints) ){
            return;
        } 
    
        //ok reasonably confident its a api call...
    
        $cache_folder= get_stylesheet_directory().'/api_cache/';
    
        // prob best if not within php server but to get you going
        if(! file_exists ( $cache_folder ) ){
            mkdir($cache_folder); //warning 777!!
        }
    
    
        /*
        * Need to choose a method of control for your cached json files
        * you could clear out the folder on update post/ taxonomies etc
        * or cron clear out hourly/weekly whatever freq you want
        */
    
    
        if( file_exists($cache_folder.$endpoint.'.json') ){
            $json= file_get_contents($cache_folder.$endpoint.'.json');
            header('Content-Type: application/json');
            echo $json;
            exit;// we need nothing else from php exit 
        } else {
            //make sure there will be no errors etc..
            $ch = curl_init();
            $url= "http://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]?cachecall=true";
            $timeout= 5;
            curl_setopt($ch, CURLOPT_URL, $url);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
            curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
            $json = curl_exec($ch);
            curl_close($ch);
            file_put_contents($cache_folder.$endpoint.'.json', $json);  
        }
    
    }
    
    get_api_cache();    
    

现在您应该注意到第二次加载时加载时间的显着差异(这是第一次缓存输出)。

一些免责声明:

  1. 你应该阅读代码中的注释
  2. 你需要卷曲
  3. 你需要知道缓存文件夹是 777,我强烈建议你把它从你的主题文件夹中移开,最好放在你的 http 可访问文件之外。
  4. 没有捕获所有挂钩来捕获要缓存的数据,因此我使用 curl 来抓取内容,这可能会在未来发生变化,并且挂钩/过滤器会在创建缓存文件时稍微缩短处理时间。
  5. 我没有包含更新缓存文件的方法。你需要决定你想要更新的频率,一个每天有很多帖子和很多访问的网站,你可能会做一个 cron 工作来删除文件(例如,每天 3 次,每小时,每 10 分钟等——更新时间的合理权衡是什么?)或添加一个挂钩来保存帖子以仅在您的帖子更改时更新等。
  6. 将您的端点添加到数组中(您可以删除 if 语句以允许所有端点,但是您可能会遇到缓存 404 的情况!)
于 2016-04-05T23:27:11.693 回答
1

你应该试试 这个。它是一个插件,允许您为帖子类型、页面和其他情况启用/禁用某些插件。

对于主题部分,如果您编写了它,很容易在 function.php 中添加一些内容,以防止它在 API 请求的情况下附加任何挂钩或过滤器。

作为旁注,您不能直接查询 de DB 吗?

于 2016-04-03T23:47:17.143 回答
0

如果这对您有帮助,请原谅我糟糕的英语。

将插件文件夹放在根 wordpress 安装中。

/public_html/my-plugin/my-plugin.php

and include wordpress main file.

    require dirname( dirname( __FILE__ ) ).'/wp-load.php';

或者在插件文件夹中直接访问

/public_html/wp-content/plugins/my-plugin/my-plugin.php
require_once dirname(__FILE__) . '/../../../wp-load.php';

在检查 wp-load.php 文件是否正确包含并工作之前。

wp-settings.php 文件加载整个核心、插件和主题文件。wordpress 是加载第一个 mu-plugins 文件 (wp-content/mu-plugins/) 并在操作后提供挂钩muplugins_loaded。触发此操作以退出加载的所有其他文件。您还可以在muplugins_loaded之前找到提供了哪个操作挂钩并停止其他文件和脚本执行。

如果在包含 wp-load.php 之前定义常量 SHORTINIT,则它包含一些提供数据库、插件或基本功能的文件。当我们想要更多的加载核心文件而不是只想加载插件和主题文件时,这种方式找到了解决方案。

// file my-plugin.php
//call before include file wp-load.php
global $wp_filter;
$wp_filter = array( 
    // pass wp hook where to want exit extra wp loaded
    'muplugins_loaded' => array(
     // prority
         1 => array(
            // callback function register
            'wp_extra_loaded_exit' => array( 

              'function' => 'wp_extra_loaded_exit',

              'accepted_args' => 1

              )
         ) 
   )
);



function wp_extra_loaded_exit(){
  exit; 

}
require dirname( dirname( __FILE__ ) ).'/wp-load.php';
// plugin code here.

我们检查muplugins_loaded钩子是否提前定义了 wordpress,您还可以找到在muplugins_loaded之前定义的钩子,然后在加载更多 wordpress 文件后停止该点。-

当你想测试你的脚本打开文件 wp-settings.php 并找到字符串 muplugins_loaded 然后回显语句来检查。

echo "Wordpress loaded in this point before"; 

do_action( 'muplugins_loaded' );

echo "After this wordpress not loading"; // Output fail bcz we exit 
于 2016-04-09T08:58:43.843 回答