自定义Metabox数据在Admin Init上的查询速度较慢

时间:2020-12-01 作者:Silvex

最近,我的数据库在Post和Posteta中都变得非常大,当访问WP admin时,它在init上加载了大约700mb的数据,这会减慢整个后端的速度。我发现大量数据是从自定义metabox init生成的。

我使用以下方法加载带有WP\\U查询获取的数据的自定义Select元数据库:

add_filter( \'rwmb_meta_boxes\', \'Theme2035_register_meta_boxes\' );

function Theme2035_register_meta_boxes( $meta_boxes ) {

 $prefix = \'theme2035_\';
 global $theme_prefix;
 global $meta_boxes;

 $artist_list = array();

 $my_query = new WP_Query(array(
    \'post_type\' => \'artist\',
    \'post_status\'=> \'publish\', 
    \'posts_per_page\' => -1,
    \'orderby\' => \'title\',
    \'order\'   => \'ASC\'
    ));
 while ($my_query->have_posts()) : $my_query->the_post(); 
 $artist_list[get_the_id()] = get_the_title();
 endwhile;  wp_reset_query();

 $album_list = array();
 $my_query = new WP_Query(array(
    \'post_type\' => \'album\',
    \'post_status\'=> \'publish\', 
    \'posts_per_page\' => -1,
    \'orderby\' => \'title\',
    \'order\'   => \'ASC\'
    ));
 while ($my_query->have_posts()) : $my_query->the_post(); 
 $album_list[get_the_id()] = get_the_title();
 endwhile;  wp_reset_query();

 $meta_boxes = array();

 $meta_boxes[] = array(
    \'id\' => \'lyric-metabox\',
    \'title\' => __( \'Lyric Options\', \'muusico\' ),
    \'pages\' => array(\'lyrics\' ),
    \'fields\' => array(                                      
        array(
            \'type\' => \'heading\',
            \'name\' => __( \'Artist Name\', \'muusico\' ),
            \'id\'   => \'fake_id\', // Not used but needed for plugin
        ),          
        array(
            \'name\'     => __( \'Artist Name\', \'muusico\' ),
            \'id\'       => $prefix."artist_name",
            \'type\'     => \'select_advanced\',
            \'options\'  => $artist_list,
            \'multiple\'    => false,
            \'placeholder\' => __( \'Select Artist Name\', \'muusico\' ),
        ),  
        array(
            \'name\'     => __( \'Feat (Second) Artist Name\', \'muusico\' ),
            \'id\'       => $prefix."second_artist_name",
            \'type\'     => \'select_advanced\',
            \'options\'  => $artist_list,
            \'multiple\'    => false,
            \'placeholder\' => __( \'Select Second Artist Name\', \'muusico\' ),
        ),  
        array(
            \'name\'     => __( \'Third Artist Name\', \'muusico\' ),
            \'id\'       => $prefix."third_artist_name",
            \'type\'     => \'select_advanced\',
            \'options\'  => $artist_list,
            \'multiple\'    => false,
            \'placeholder\' => __( \'Select Third Artist Name\', \'muusico\' ),
        ),
        array(
            \'type\' => \'heading\',
            \'name\' => __( \'Album Name\', \'muusico\' ),
            \'id\'   => \'fake_id\', // Not used but needed for plugin
        ),          
        array(
            \'name\'     => __( \'Album Name\', \'muusico\' ),
            \'id\'       => $prefix."album_name",
            \'type\'     => \'select_advanced\',
            \'options\'  => $album_list,
            \'multiple\'    => false,
            \'placeholder\' => __( \'Select Album Name\', \'muusico\' ),
        ),
        array(
            \'type\' => \'heading\',
            \'name\' => __( \'Translate Option\', \'muusico\' ),
            \'id\'   => \'fake_id\', // Not used but needed for plugin
        ),
        array(
            \'name\'      => __(\'Translated Lyric\',"muusico"),
            \'id\'        => $prefix."translated",
            \'desc\'      => __(\'Enter Translated Lyric\',\'muusico\'),
            \'clone\'     => false,
            \'type\'      => \'textarea\',
            \'std\'       => \'\'
        ),
        array(
            \'name\'      => __(\'Lyric Description\',"muusico"),
            \'id\'        => "descrizione",
            \'desc\'      => __(\'Enter Lyric Description\',\'muusico\'),
            \'clone\'     => false,
            \'type\'      => \'textarea\',
            \'std\'       => \'\'
        ),
        array(
            \'type\' => \'heading\',
            \'name\' => __( \'Lyrics Media\', \'muusico\' ),
            \'id\'   => \'fake_id\', // Not used but needed for plugin
        ),
        array(
            \'name\'      => __(\'Video Embed Code\',"muusico"),
            \'id\'        => $prefix."embed",
            \'desc\'      => __(\'Enter Embed Code\',\'muusico\'),
            \'clone\'     => false,
            \'type\'      => \'textarea\',
            \'std\'       => \'\'
        )
    )
 );
   return $meta_boxes;
}
需要明确的是,慢速查询如下所示:

$my_query = new WP_Query(array(
    \'post_type\' => \'artist\',
    \'post_status\'=> \'publish\', 
    \'posts_per_page\' => -1,
    \'orderby\' => \'title\',
    \'order\'   => \'ASC\'
    ));
 while ($my_query->have_posts()) : $my_query->the_post(); 
 $artist_list[get_the_id()] = get_the_title();
 endwhile;  wp_reset_query();

 $album_list = array();
 $my_query = new WP_Query(array(
    \'post_type\' => \'album\',
    \'post_status\'=> \'publish\', 
    \'posts_per_page\' => -1,
    \'orderby\' => \'title\',
    \'order\'   => \'ASC\'
    ));
 while ($my_query->have_posts()) : $my_query->the_post(); 
 $album_list[get_the_id()] = get_the_title();
 endwhile;  wp_reset_query();
如果删除上面的两个查询,后端将从14s加载到<;1s但在编辑页面中,选择元框为空,我无法找到一种方法来正确填充这些选择,而不依赖这两个缓慢而沉重的WP\\U查询。

如何以更快的方式加载metabox数据?一个可能的解决方案是,只有在编辑页面或添加新的帖子页面时,才将metabox数据发送到init,但如何在不使其在init上运行的情况下实现这一点,从而使管理面板不重700mb?

谢谢

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

我通过使用基于Ajax的select搜索更改第三方插件的metabox类型来解决这个问题。

在下面的例子中,我不再使用标题来过滤选择,而是直接插入我需要的帖子的URL(在这种情况下是艺术家/专辑)。

我知道这是一个解决方法,但它对我的情况有效,希望它能帮助其他人,代码如下:

在里面metabox.php

\'fields\' => array(                                                  
        array(
            \'name\'     => __( \'Artist URL\', \'theme\' ),
            \'id\'       => $prefix."artist_name",
            \'type\'     => \'autocomplete\',
            \'options\'  => admin_url( \'admin-ajax.php?action=artist_list\' ),
        ), 
        ...
然后在functions.php

function get_ajax_artist_list() {
  $s = $_REQUEST[ \'term\' ];
  $post_name = str_replace(\'https://www.example.com/artist/\', \'\', $s);    
  $post_name = substr($post_name, 0, -1);
  $args = array(
    \'name\'        => $post_name,
    \'post_type\'   => \'artist\',
    \'post_status\' => \'publish\',
    \'numberposts\' => 1
  );
  $my_posts = get_posts($args);
  $response = array(
    array( \'value\' => $my_posts[0]->ID, \'label\' => $my_posts[0]->post_title ),
  );
  echo wp_json_encode( $response );
  die;
}
add_action( \'wp_ajax_artist_list\', \'get_ajax_artist_list\');
感谢@Tom J Nowell的支持。