Call to undefined function convert_to_screen()

2019-05-06 06:21发布

I am developing a plugin where i did have to extend the class WP_List_Table. I have extended the class within my plugin-file (I don't know if this is the right way to do this?) and included WP_List_Table like this:

if(!class_exists('WP_List_Table')){
   require_once( ABSPATH . 'wp-admin/includes/class-wp-list-table.php' );
}

Then comes the code for extending the class and then I do create an instance of my table class like this:

<?php

 if ( ! class_exists( 'WP_List_Table' ) ) {
                require_once( ABSPATH . 'wp-admin/includes/class-wp-list-table.php' );
}


 Class Wp_Ban_User extends WP_List_Table
 {

    public function __construct()
    {
             add_action('admin_menu',array($this,'WBU_adminMenu'));
             parent::__construct( array(
                  'singular'=> 'wp_list_text_link', //Singular label
                  'plural' => 'wp_list_test_links', //plural label, also this well be one of the table css class
                  'ajax'   => false //We won't support Ajax for this table
                  ) );      
            $this->prepare_items();
            $this->display();           

    }
     function get_columns() {
        $columns = array(
            'id'    => 'ID',
            'user_login'     => 'User Name',
            'user_email'   => 'User Email'            
        );
        return $columns;
    }


    function column_default( $item, $column_name ) {
        switch( $column_name ) {
            case 'id':
            case 'user_login':
            case 'user_email':

                return $item[ $column_name ];
            default:
                return print_r( $item, true ) ;
        }
    }
    function prepare_items() {

        $example_data = array(
                array(
                        'id'        => 1,
                        'user_login'     => 'vasim',
                        'user_email'    => 'vasim@abc.com'                        
                ),
                array(
                        'id'        => 2,
                        'user_login'     => 'Asma',
                        'user_email'    => 'Asma@abc.com'                        
                ),
                array(
                        'id'        => 3,
                        'user_login'     => 'Nehal',
                        'user_email'    => 'nehal@abc.com'                        
                ),
            );

        $columns = $this->get_columns();
        $hidden = array();
        $sortable = $this->get_sortable_columns();
        $this->_column_headers = array($columns, $hidden, $sortable);
        $this->items = $example_data;
    }

    public function WBU_adminMenu()
    {
            add_menu_page( 'Currently Logged In User', 'Banned User', 'manage_options', 'ban_admin_init', array($this,'ban_admin_init'));
    }
function ban_admin_init(){
        global $wpdb;

        $sql="SELECT * from {$wpdb->prefix}users";
        $sql_result=$wpdb->get_results($sql,'ARRAY_A');
        print_r($sql_result);
        //$this->items=$sql_result;     
    }

}

 global $Obj_Wp_Ban_User;

 $Obj_Wp_Ban_User=new Wp_Ban_User();

But when i do this, i do get this error:

Fatal error: Call to undefined function convert_to_screen() in D:\xampp\htdocs\developplugin\wp-admin\includes\class-wp-list-table.php on line 143

I did some research but did not understand how to fix it.

Does anybody knows how to fix this?

Thanks for your help!

Best regards.

标签: php wordpress
3条回答
Animai°情兽
2楼-- · 2019-05-06 06:41

I have checked your code with my fresh wordpress using this link i think it solved your problem please check this link I want a pagination to my options page of wordpress plugin?

Let me know if you have any confusion.

查看更多
别忘想泡老子
3楼-- · 2019-05-06 06:47

I had a working prototype of a class very similar to yours. I decided to conform to the WordPress best practices structure for my plugin, so I downloaded one of the suggested boilerplates and began adapting my code to the boilerplate class based structure. When I did, I ran into the same problem as you. Since I had a working example that created the admin page extended from WP_List_Table inside a class, I knew the issue wasn't adding the menu page inside the class. The issue is that the constructor

Class Wp_Ban_User extends WP_List_Table {

public function __construct()
{
         add_action('admin_menu',array($this,'WBU_adminMenu'));
         parent::__construct( array(...

is being called be before WordPress has finished initializing. I did some digging to find out what the initialization sequence is and came across this WordPress action_hook sequence list. I tried creating my equivalent to your Wp_Ban_User class using the wp_loaded action hook {This hook is fired once WP, all plugins, and the theme are fully loaded and instantiated.}, but it still crashed. A little further in the sequence is the wp action hook {Fires once the WordPress environment has been set up} and I thought it worked because my plugin didn't crash. But wp isn't a real action hook, so that meant my classes weren't being initialized.

So, my simple code change

function run_admin_page_init() {
    $myAdminPage = new Wp_Ban_User();
}
add_action( 'wp', 'run_admin_page_init' );

rather than having to hack up my class looked promising, but was a red herring.

Still confident that the problem is a sequencing issue during initialization, I finally tracked it down to the following fix (which actually worked). In the class that added my admin menu entry I had:

function __construct() {
    $this->pageTable = new WBU_adminMenu();
    add_action( 'admin_menu', [ $this, 'addAdminMenu' ] );
}
/**
 * Adds the Manage Mailing List label to the WordPress Admin Sidebar Menu
 */
public function addAdminMenu() {
    $hook = add_menu_page(
        'Page Title',
        'Menu Name',
        'manage_options',
        'menu_slug',
        [ $this, 'adminLayout' ] );

    add_action( "load-$hook", [ $this, 'screen_option' ] );
}

but I changed it to:

function __construct() {
    add_action( 'admin_menu', [ $this, 'addAdminMenu' ] );
}

/**
 * Adds the Manage Mailing List label to the WordPress Admin Sidebar Menu
 */
public function addAdminMenu() {
    $this->pageTable = new WBU_adminMenu();
    $hook = add_menu_page(
        'Page Title',
    ...

which deferred creating the child class of WP_LIST_TABLE until after the basic admin panel menu structure is in place.

I'm sure you've moved on to bigger and better projects and the hair you pulled out in frustration trying to track this down mystery has grown back in the two years that have elapsed since you cast your question into the community, but I posted my solution just in case someone else runs into the problem.

查看更多
何必那么认真
4楼-- · 2019-05-06 06:52

Sorry for my bad english, im french.

I have found the problem. Your class corrected (see at the bottom of code):

<?php
/*
Plugin Name: My List Table Example
*/
 if ( ! class_exists( 'WP_List_Table' ) ) {
    require_once( ABSPATH . 'wp-admin/includes/class-wp-list-table.php' );
}


Class Wp_Ban_User extends WP_List_Table
{

    public function __construct()
    {
             parent::__construct( array(
                  'singular'=> 'wp_list_text_link', //Singular label
                  'plural' => 'wp_list_test_links', //plural label, also this well be one of the table css class
                  'ajax'   => false //We won't support Ajax for this table
                  ) );      
            $this->prepare_items();
            $this->display();           

    }

    function get_columns() {
        $columns = array(
            'id'    => 'ID',
            'user_login'     => 'User Name',
            'user_email'   => 'User Email'            
        );
        return $columns;
    }

    function column_default( $item, $column_name ) {
        switch( $column_name ) {
            case 'id':
            case 'user_login':
            case 'user_email':

                return $item[ $column_name ];
            default:
                return print_r( $item, true ) ;
        }
    }

    function prepare_items() {

        $example_data = array(
                array(
                        'id'        => 1,
                        'user_login'     => 'vasim',
                        'user_email'    => 'vasim@abc.com'                        
                ),
                array(
                        'id'        => 2,
                        'user_login'     => 'Asma',
                        'user_email'    => 'Asma@abc.com'                        
                ),
                array(
                        'id'        => 3,
                        'user_login'     => 'Nehal',
                        'user_email'    => 'nehal@abc.com'                        
                ),
            );

        $columns = $this->get_columns();
        $hidden = array();
        $sortable = $this->get_sortable_columns();
        $this->_column_headers = array($columns, $hidden, $sortable);
        $this->items = $example_data;
    }

}


// Render your admin menu outside the class
function WBU_adminMenu()
{
    add_menu_page( 'Currently Logged In User', 'Banned User', 'manage_options', 'render_admin_page', 'render_admin_page');
}

// Create your menu outside the class
add_action('admin_menu','WBU_adminMenu');

// Render your page outside the class
function render_admin_page(){
    global $wpdb;

    $Obj_Wp_Ban_User=new Wp_Ban_User();
    $Obj_Wp_Ban_User->prepare_items();

    $sql="SELECT * from {$wpdb->prefix}users";
    $sql_result=$wpdb->get_results($sql,'ARRAY_A');
    print_r($sql_result);    
}

This simple : For resolve the error Call to undefined function convert_to_screen() you need to :

  • Add the menu outside the class
  • Add the admin_menu action outside the class
  • Render your admin page outside the class

After 3 days, it's work for me !

查看更多
登录 后发表回答