我想更快地向WordPress API发出请求。我的API是在一个插件中实现的(使用register_rest_route注册我的路由)。然而,由于这是一个插件,所有的东西都加载了它(子元素和主题),基本上对这个API的查询需要半秒钟的时间,因为加载了所有这些无用的部分。
难道WordPress API不能以另一种方式使用吗?由于大多数使用WP-API的插件不需要加载任何其他插件,更不用说主题了。。。我不明白他们怎么会错过。
有办法这样做吗?
是的,这是可能的。在我的一个插件中,我需要最小的WordPress核心(没有插件和主题的DB),我做的是:
<?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'
将SHORTINIT
设置为true
确实对性能有所帮助。
禁用WP_DEBUG
后,引导WordPress所需的时间如下:
- 无短路:约0.045秒
- SHORTINIT:约0.0015秒
如果这是针对您自己需要性能的网站,您可能可以通过启用OpCache(例如,最近版本中的APC或PHP OpCache)来提高性能。
但我相信上面定义SHORTINIT
和需要wp-load.php
的两行代码就是您想要的。
为了澄清,这个文件是插件的一部分,但它是独立于WordPress本身调用的(通过Ajax和直接调用)。它从未被插件或WP本身的任何其他部分包含或使用。
编辑:由于OP实际上与WP-API有关,而不是一般的WordPress,因此我添加此内容以解决实际问题。我会保留原来的答案内容,以防对其他人有帮助。
我用WP API做了进一步的测试,就像@David在回答中所说的那样,问题可能是其他问题。
除了rest api之外,我还加载了12个插件,一些相当"大"的插件,我的本地安装大约安装了25个主题(当然有一个是活动的)。我编辑了WordPress的index.php
文件,并使用microtime(true)
记录一切何时开始,然后编辑了其中一个REST控制器,以计算从开始到到达API端点所需的时间。
在我的系统上,结果始终在0.0462
-0.0513
秒左右(没有PHP OpCache,也没有其他系统负载)。因此,似乎所有WordPress的自举对性能几乎没有影响。
如果请求需要半秒钟的时间,那么瓶颈就在其他地方,去掉插件和主题的影响微乎其微。至少这是我的发现。
我认为您可能关注的问题不对。
加载php文件并不像从数据库中读取那么慢,这可能是500毫秒的加载时间。实际上,你应该考虑减少这种情况(缓存wp选项等),但我建议你使用api缓存输出。使用exit,我们可以从文件加载输出并立即提供。
我们的方法:1.在wp内容文件夹(可能已经存在)中创建一个名为mu-plugins
的文件夹
-
创建一个名为
api-cache.php
的文件 -
将此代码输入您的文件:
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();
现在,您应该注意到第二次加载(这是第一次缓存输出)时的加载时间有显著差异。
一些免责声明:
- 你应该阅读代码中的注释
- 你需要卷曲
- 你需要知道缓存文件夹是777,我强烈建议你把它从你的主题文件夹中移走,最好是在你的http可访问文件之外
- 没有捕获要缓存的数据的catch-all钩子,因此我使用curl来捕获内容,这在未来可能会改变,钩子/过滤器将在创建缓存文件时稍微缩短处理时间
- 我还没有包含更新缓存文件的方法。你需要决定更新的频率,一个每天有很多帖子和大量访问的网站,你可以做一个cron工作来删除文件(例如,每天3次,每小时3次,每隔10分钟一次,等等——在更新时间上有什么合理的折衷?)或者添加一个钩子来保存帖子,只在帖子更改时更新,等等
- 将端点添加到它们的数组中(可以删除if语句以允许所有端点,但可能会出现缓存404的情况!)
你应该试试这个。它是一个插件,允许您为帖子类型、页面和其他情况启用/禁用某些插件。
对于主题部分,如果您编写了它,则可以很容易地在function.php中添加一些内容,以防止它在API请求的情况下附加任何挂钩或过滤器。
顺便说一句,你不能直接查询de DB吗?
如果这对你有帮助,很抱歉我的英语不好。
将插件文件夹放在根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-pluins/),并提供操作后挂钩muplugins_loaded。触发此操作可退出已加载的所有其他文件。您还可以在muplugins_loaded之前找到提供的操作挂钩,并停止其他文件和脚本执行。
如果在include wp-load.php之前定义常量SHORTINIT,则其includes一些文件提供DB、插件或基本功能。当我们想要更多的加载核心文件,而不仅仅是以这种方式加载插件和主题文件时,我们找到了一个解决方案。
// 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_lloaded 当你想测试你的脚本时,打开文件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