如何在前端页面上显示WP_List_Tables

时间:2017-08-01 03:40:20

标签: php mysql wordpress

当前问题: 我已经能够在Dashboard管理区域内的WP的sql数据库中成功创建各种表格列表,并使用WP_LIST_TABLE创建插件但是我遇到了如何在前端显示相同表格的困难我的网站使用短代码。通常我会添加类似的东西:

 add_shortcode('joblist', 'Job_List_Plugin');

然而,在这种情况下它似乎没有起作用。页面没有生成表格,而只是看到你添加到页面的短代码,所以在这种情况下[joblist]

问题: 如何在以下代码中添加一个短代码元素,以便我可以在前端页面上显示此表以供登录的访问者查看?示例/片段将不胜感激。

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

 class Job_List extends WP_List_Table {

    /** Class constructor */
    public function __construct() {
        parent::__construct( [
            'singular' => __( 'Custom List', 'red' ), //singular name of the listed records
            'plural'   => __( 'Custom Lists', 'red' ), //plural name of the listed records
            'ajax'     => false //does this table support ajax?
        ] );
    }


    /**
     * Retrieve members data from the database
     *
     * @param int $per_page
     * @param int $page_number
     *
     * @return mixed
     */
    public static function get_jobs( $per_page = 10, $page_number = 1 ) {

        global $wpdb;
        $query = "SELECT * FROM custom_table ORDER BY PrintOrder";

        if( ! empty( $_REQUEST['s'] ) ){
         $search = esc_sql( $_REQUEST['s'] );
    $query .= " WHERE Description LIKE '%{$search}%'";
    }

        if ( ! empty( $_REQUEST['orderby'] ) ) {
            $query .= ' ORDER BY ' . esc_sql( $_REQUEST['orderby'] );
            $query .= ! empty( $_REQUEST['order'] ) ? ' ' . esc_sql( $_REQUEST['order'] ) : ' ASC';
        }

        $query .= " LIMIT $per_page";
        $query .= ' OFFSET ' . ( $page_number - 1 ) * $per_page;

        $result = $wpdb->get_results( $query, 'ARRAY_A' );

        return $result;
    }

    /**
     * Returns the count of records in the database.
     *
     * @return null|string
     */
    public static function record_count() {
        global $wpdb;

        $query = "SELECT COUNT(*) FROM custom_table";
        if( ! empty( $_REQUEST['s'] ) ){
         $search = esc_sql( $_REQUEST['s'] );
         $query .= " WHERE Description LIKE '%{$search}%'";
        }
        return $wpdb->get_var( $query );
    }

    /** Text displayed when no member data is available */
    public function no_items() {
        _e( 'There is nothing display at this time.', 'red' );
    }

    /**
     * Render a column when no column specific method exist.
     *
     * @param array $item
     * @param string $column_name
     *
     * @return mixed
     */
    public function column_default( $item, $column_name ) {
        switch ( $column_name ) {
        case 'Description':
        case 'Class':
        case 'EmpName':
        case 'StartTime':
            return $item[ $column_name ];
        default:
            return print_r( $item, true ); //Show the whole array for troubleshooting purposes
    }
}


/**
 *  Associative array of columns
 *
 * @return array
 */
function get_columns() {
    $columns = [
        'Description' => __( 'Classification', 'red' ),
        'Class'    => __( 'Class', 'red' ),
        'EmpName'    => __( 'Employer Name', 'red' ),
        'StartTime'    => __( 'Start Time', 'red' )
    ];

    return $columns;
}


/**
 * Columns to make sortable.
 *
 * @return array
 */
public function get_sortable_columns() {
    $sortable_columns = array(
        'Description' => array( 'Classification', true ),
        'Class' => array ( 'Class', true)
    );

    return $sortable_columns;
}
/**
 * Handles data query and filter, sorting, and pagination.
 */
public function prepare_items() {

    $this->_column_headers = $this->get_column_info();

    /** Process bulk action */
    $this->process_bulk_action();

    $per_page     = $this->get_items_per_page( 'jobs_per_page', 7 );
    $current_page = $this->get_pagenum();
    $total_items  = self::record_count();

    $this->set_pagination_args( [
        'total_items' => $total_items, //calculate the total number of items
        'per_page'    => $per_page //determine how many items to show on a page
    ] );

    $this->items = self::get_jobs( $per_page, $current_page );
}




 }

 class Job_List_Plugin {

// class instance
static $instance;

// joblist WP_List_Table object
public $joblist_obj;

// class constructor
public function __construct() {
   add_filter( 'set-screen-option', [ __CLASS__, 'set_screen' ], 10, 3 );
   add_action( 'admin_menu', [ $this, 'plugin_menu' ] );
}


public static function set_screen( $status, $option, $value ) {
    return $value;
}

public function plugin_menu() {

    $hook = add_menu_page(
        'Job List',
        'Job List',
        'manage_options',
        'joblist_viewer',
        [ $this, 'plugin_settings_page' ]
    );

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

}


/**
 * Plugin page
 */
public function plugin_settings_page() {
    ?>
    <style>
      table {display: block;overflow-x: scroll;}
      th {min-width:100px;font-size:10px;}
      p.search-box {float:none;}
      #post-body-content {width:98%;}
    </style>
        <h2>IBEW 353 Member Management Portal</h2>
        <p>To locate a specific Member enter their Card Number in the search field provided.</p>
                <div id="post-body-content">
                    <div class="meta-box-sortables ui-sortable">
                        <form method="post">
   <input type="hidden" name="page" value="joblist_viewer" />
                            <?php
                            $this->joblist_obj->prepare_items();
                            $this->joblist_obj->search_box('Search', 'search');
                            $this->joblist_obj->display(); ?>
                        </form>
                    </div>
                </div>
            <br class="clear">
<?php
}

/**
 * Screen options
 */
public function screen_option() {

    $option = 'per_page';
    $args   = [
        'label'   => 'Jobs Per Page:',
        'default' => 5,
        'option'  => 'jobs_per_page'
    ];

    add_screen_option( $option, $args );

    $this->joblist_obj = new Job_List();
}


/** Singleton instance */
public static function get_instance() {
    if ( ! isset( self::$instance ) ) {
        self::$instance = new self();
    }

    return self::$instance;
}

 }

 add_action( 'plugins_loaded', function () {
    Job_List_Plugin::get_instance();
 } );

更新 在@Jared Chu的帮助下,我得到了一些进展,但现在却出现了错误。但至少我看到短代码开始起作用了。

这是我编辑的内容。

第203行(类构造)我添加了

// class constructor
public function __construct() {
   add_filter( 'set-screen-option', [ __CLASS__, 'set_screen' ], 10, 3 );
   add_action( 'admin_menu', [ $this, 'plugin_menu' ] );
   add_shortcode('joblist', [ $this, 'plugin_settings_page' ] ); // Added shortcode as per suggestion from @Jared Chu
}

公共功能&#34; plugin_settings_page&#34;包含此代码

 /**
 * Plugin page
 */
public function plugin_settings_page() {
    ?>
    <style>
      table {display: block;overflow-x: scroll;}
      th {min-width:100px;font-size:10px;}
      p.search-box {float:none;}
      #post-body-content {width:98%;}
    </style>
        <h2>IBEW 353 Member Management Portal</h2>
        <p>To locate a specific Member enter their Card Number in the search field provided.</p>
                <div id="post-body-content">
                    <div class="meta-box-sortables ui-sortable">
                        <form method="post">
 <input type="hidden" name="page" value="joblist_viewer" />
                            <?php
                            $this->joblist_obj->prepare_items();
                            $this->joblist_obj->search_box('Search', 'search');
                            $this->joblist_obj->display(); ?>
                        </form>
                    </div>
                </div>
            <br class="clear">
<?php
}

然而,当我查看页面时,我删除了短代码,我收到以下错误:

致命错误:未捕获错误:在第249行的C:\ wamp64 \ www \ dev1 \ wp-content \ plugins \ Job-List-Plugin \ index.php中调用null上的成员函数prepare_items()

2 个答案:

答案 0 :(得分:1)

add_shortcode('joblist', 'Job_List_Plugin');不正确。

add_shortcode第二个ref变量必须是一个函数:

# 1. Standard usage
add_shortcode('shortcode_name', 'shortcode_func');

function shortcode_func()
{
 // Contents of this function will execute when the blogger
// uses the [shortcode_name] shortcode.
}

# 2. With PHP 5.3, we can pass an anonymous function.
add_shortcode('shortcode_name', function() {
   // Contents of this function will execute when the blogger
  // uses the [shortcode_name] shortcode.
});

#3. Within a class
class YourPluginClass {
    public function __construct()
    {
        add_shortcode('your_short_code_name', array($this, 'shortcode'));
    }

    public function shortcode()
    {
           // Contents of this function will execute when the blogger
          // uses the [shortcode_name] shortcode.
    }
}

因此,在您的情况下,我们将使用#3。

答案 1 :(得分:0)

当我尝试在前端显示WP_List_Table时,我自己遇到了这个问题。我已经有一个正确定义的简码,并在类外的admin中呈现了菜单页面。不过,在使用简码在前端呈现列表时仍然出现此错误。

经过两天的研究和搜索,我终于弄清楚了。我需要其他类才能使其在前端工作。我的猜测是这些类包含在wp-admin模式中,但不包含在前端模式中,因此这就是为什么我们需要在子类中要求它们。

我在这里找到某人的答案,该人要求无关的内容,但具有我需要的正确代码:https://wordpress.stackexchange.com/questions/350839/wp-list-table-in-frontend-how-to-style-with-bootstrap4

这些是您需要包括的类和文件:

        require_once(ABSPATH . 'wp-admin/includes/class-wp-list-table.php');
        require_once(ABSPATH . 'wp-admin/includes/screen.php');
        require_once(ABSPATH . 'wp-admin/includes/class-wp-screen.php');
        require_once(ABSPATH . 'wp-admin/includes/template.php');

即使这个问题已经有了答案,但如果有人遇到同样的问题,我会在这里发布。

编辑:忘记添加我如何在前端显示表格。我只是在需要呈现表的页面模板中创建该类的新实例。像这样:

 <main id="dashboard content">
   <?php
   $list = new LB_WP_Table();
   ?>
 </main>

我已使用此答案中的代码作为起点:https://stackoverflow.com/a/18933069

这是我目前的完整代码:

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


  require_once(ABSPATH . 'wp-admin/includes/screen.php');
  require_once(ABSPATH . 'wp-admin/includes/class-wp-screen.php');
  require_once(ABSPATH . 'wp-admin/includes/template.php');

class LB_WP_Table extends WP_List_Table {
private $order;
private $orderby;
private $posts_per_page = 5;

public function __construct() {
    parent:: __construct( array(
        'singular' => 'table example',
        'plural'   => 'table examples',
        'ajax'     => true
    ) );

    add_filter( 'get_list_instance', [$this, 'get_instance']);
    add_shortcode('render_list', array($this, 'render_list_table'));
    $this->set_order();
    $this->set_orderby();
    $this->prepare_items();
    $this->display();

}


public function get_instance(){
  return $this;
}

public function render_list_table(){
  $this->set_order();
  $this->set_orderby();
  $this->prepare_items();
  $this->display();
}

private function get_sql_results()
{
    global $wpdb;
    $args = array( 'ID', 'post_title', 'post_date', 'post_content', 'post_type' );
    $sql_select = implode( ', ', $args );
    $sql_results = $wpdb->get_results("
            SELECT $sql_select
                FROM $wpdb->posts
            WHERE post_status = 'publish'
            ORDER BY $this->orderby $this->order "
    );
    return $sql_results;
}

public function set_order()
{
    $order = 'DESC';
    if ( isset( $_GET['order'] ) AND $_GET['order'] )
        $order = $_GET['order'];
    $this->order = esc_sql( $order );
}

public function set_orderby()
{
    $orderby = 'post_date';
    if ( isset( $_GET['orderby'] ) AND $_GET['orderby'] )
        $orderby = $_GET['orderby'];
    $this->orderby = esc_sql( $orderby );
}

/**
 * @see WP_List_Table::ajax_user_can()
 */
public function ajax_user_can()
{
    return current_user_can( 'edit_posts' );
}

/**
 * @see WP_List_Table::no_items()
 */
public function no_items()
{
    _e( 'No posts found.' );
}

/**
 * @see WP_List_Table::get_views()
 */
public function get_views()
{
    return array();
}

/**
 * @see WP_List_Table::get_columns()
 */
public function get_columns()
{
    $columns = array(
        'ID'         => __( 'ID' ),
        'post_title' => __( 'Title' ),
        'post_date'  => __( 'Date' ),
        'post_type'  => __( 'Type' )
    );
    return $columns;
}

/**
 * @see WP_List_Table::get_sortable_columns()
 */
public function get_sortable_columns()
{
    $sortable = array(
        'ID'         => array( 'ID', true ),
        'post_title' => array( 'post_title', true ),
        'post_date'  => array( 'post_date', true )
    );
    return $sortable;
}

/**
 * Prepare data for display
 * @see WP_List_Table::prepare_items()
 */
public function prepare_items()
{
    $columns  = $this->get_columns();
    $hidden   = array();
    $sortable = $this->get_sortable_columns();
    $this->_column_headers = array(
        $columns,
        $hidden,
        $sortable
    );

    // SQL results
    $posts = $this->get_sql_results();
    empty( $posts ) AND $posts = array();

    # >>>> Pagination
    $per_page     = $this->posts_per_page;
    $current_page = $this->get_pagenum();
    $total_items  = count( $posts );
    $this->set_pagination_args( array (
        'total_items' => $total_items,
        'per_page'    => $per_page,
        'total_pages' => ceil( $total_items / $per_page )
    ) );
    $last_post = $current_page * $per_page;
    $first_post = $last_post - $per_page + 1;
    $last_post > $total_items AND $last_post = $total_items;

    // Setup the range of keys/indizes that contain
    // the posts on the currently displayed page(d).
    // Flip keys with values as the range outputs the range in the values.
    $range = array_flip( range( $first_post - 1, $last_post - 1, 1 ) );

    // Filter out the posts we're not displaying on the current page.
    $posts_array = array_intersect_key( $posts, $range );
    # <<<< Pagination

    // Prepare the data
    $permalink = __( 'Edit:' );
    foreach ( $posts_array as $key => $post )
    {
        $link     = get_edit_post_link( $post->ID );
        $no_title = __( 'No title set' );
        $title    = ! $post->post_title ? "<em>{$no_title}</em>" : $post->post_title;
        $posts[ $key ]->post_title = "<a title='{$permalink} {$title}' href='{$link}'>{$title}</a>";
    }
    $this->items = $posts_array;
}

/**
 * A single column
 */
public function column_default( $item, $column_name )
{
    return $item->$column_name;
}

/**
 * Override of table nav to avoid breaking with bulk actions & according nonce field
 */
public function display_tablenav( $which ) {
    ?>
    <div class="tablenav <?php echo esc_attr( $which ); ?>">
        <!--
        <div class="alignleft actions">
            <?php # $this->bulk_actions( $which ); ?>
        </div>
         -->
        <?php
        $this->extra_tablenav( $which );
        $this->pagination( $which );
        ?>
        <br class="clear" />
    </div>
    <?php
}

/**
 * Disables the views for 'side' context as there's not enough free space in the UI
 * Only displays them on screen/browser refresh. Else we'd have to do this via an AJAX DB update.
 *
 * @see WP_List_Table::extra_tablenav()
 */
public function extra_tablenav( $which )
{
    global $wp_meta_boxes;
    $views = $this->get_views();
    if ( empty( $views ) )
        return;

    $this->views();
}
} // class

if (!is_admin()){ // Only do this in frontend
  $list = new LB_WP_Table(); 
}


add_action('admin_menu', function()
{
    add_menu_page(
        'TE',
        '<span style="color:#e57300;">Table Example</span>',
        'edit_pages',
        'table-example',
        function() {
            echo '<div class="wrap">';
            screen_icon('edit');
            echo '<h2>Table Example</h2>';
            new LB_WP_Table();
            echo '</div>';
        },
    'http://sstatic.net/stackexchange/img/favicon.ico',
        1  // create before Dashboard menu item
    );
});