自定义WP_LIST_TABLE显示空白行

时间:2020-03-14 作者:chrispytoes

我在试着定制WP_List_Table 扩展以显示自定义帖子类型。

下面是表和DOM的外观。您可以看到,它正在将表行呈现为空,并且没有标题。应该有两个职位,这样才能发挥更多的作用。

enter image description here

以下是页面代码:

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

  class CustomerList extends WP_List_Table {
    public function __construct() {
      parent::__construct([
        \'singular\' => __(\'Customer\', \'text-domain\'),
        \'plural\' => __(\'Customers\', \'text-domain\'),
        \'ajax\' => false
      ]);
    }

    public static function get_customers() {
      $query = new WP_Query(array(
        \'post_type\' => \'customer\'
      ));

      $customer_posts = $query->posts;
      $customers = array();

      foreach($customer_posts as $customer_post) {
        $new_customer = array();
        $new_customer[\'postId\'] = $customer_post->ID;
        $new_customer[\'firstName\'] = get_post_meta($customer_post->ID, \'lws-first-name\', true);
        $new_customer[\'lastName\'] = get_post_meta($customer_post->ID, \'lws-last-name\', true);
        $new_customer[\'notes\'] = get_post_meta($customer_post->ID, \'lws-notes\', true);
        $new_customer[\'customerId\'] = get_post_meta($customer_post->ID, \'lws-customer-id\', true);
        $new_customer[\'email\'] = get_post_meta($customer_post->ID, \'lws-email\', true);
        $new_customer[\'phone\'] = get_post_meta($customer_post->ID, \'lws-phone\', true);
        $new_customer[\'mobile\'] = get_post_meta($customer_post->ID, \'lws-mobile\', true);
        $new_customer[\'emailNotifications\'] = get_post_meta($customer_post->ID, \'lws-email-notifications\', true);
        $new_customer[\'acceptChecks\'] = get_post_meta($customer_post->ID, \'lws-accept-checks\', true);
        $new_customer[\'altContact\'] = get_post_meta($customer_post->ID, \'lws-alt-contact\', true);
        $new_customer[\'altPhone\'] = get_post_meta($customer_post->ID, \'lws-alt-phone\', true);
        $new_customer[\'street\'] = get_post_meta($customer_post->ID, \'lws-street\', true);
        $new_customer[\'city\'] = get_post_meta($customer_post->ID, \'lws-city\', true);
        $new_customer[\'state\'] = get_post_meta($customer_post->ID, \'lws-state\', true);
        $new_customer[\'zip\'] = get_post_meta($customer_post->ID, \'lws-zip\', true);
        $new_customer[\'pets\'] = json_decode(get_post_meta($customer_post->ID, \'lws-pets\', true));
        array_push($customers, $new_customer);
      }

      return $customers;
    }

    public static function delete_customer($id) {
      wp_delete_post($id);
    }

    public static function record_count() {
      return wp_count_posts(\'customer\')->draft;
    }

    public function no_items() {
      _e(\'No customers to display\', \'text-domain\');
    }

    function column_name($customer) {
      $delete_nonce = wp_create_nonce(\'lws-delete-customer\');
      $title = \'<strong>\' . $customer[\'firstName\'] . \' \' . $customer[\'lastName\'] . \'</strong>\';
      $actions = [
        \'delete\' => sprintf(\'<a href="?page=%s&action=%s&customer=%s&_wpnonce=%s">Delete</a>\', esc_attr($_REQUEST[\'page\']), \'delete\', absint($customer[\'postId\']), $delete_nonce)
      ];
      return $title . $this->row_actions($actions);
    }

    function column_default($customer, $column_name) {
      return $customer[$column_name];
    }

    function column_cb($customer) {
      return sprintf(
        \'<input type="checkbox" name="bulk-delete[]" value="%s"/>\', $customer[\'postId\']
      );
    }

    function get_columns() {
      return [
        \'cb\' => \'<input type="checkbox" />\',
        \'customerId\' => __(\'Customer ID\', \'text-domain\'),
        \'name\' => __(\'Name\', \'text-domain\'),
        \'email\' => __(\'E-Mail\', \'text-doamin\'),
        \'phone\' => __(\'Phone #\', \'text-domain\')
      ];
    }

    public function get_sortable_columns() {
      return [
        \'customerId\' => [\'customerId\', true],
        \'name\' => [\'name\', false],
        \'email\' => [\'emial\', false],
        \'phone\' => [\'phone\', false]
      ];
    }

    public function get_bulk_actions() {
      return [
        \'bulk-delete\' => \'Delete\'
      ];
    }

    public function prepare_items() {
      $this->_column_headers = $this->get_column_info();

      $this->process_bulk_actions();

      $per_page = $this->get_items_per_page(\'customers_per_page\', 20);
      $current_page = $this->get_pagenum();
      $total_items = self::record_count();

      $this->set_pagination_args([
        \'total_items\' => $total_items,
        \'per_page\' => $per_page
      ]);

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

    public function process_bulk_action() {
      if($this->current_action() === \'delete\') {
        $nonce = esc_attr($_REQUEST[\'_wpnonce\']);
        if(!wp_verify_nonce($nonce, \'lws-delete-customer\')) {
          die(\'What the heck\');
        }
        else {
          self::delete_customer(absint($_GET[\'customer\']));
          wp_redirect(esc_url(add_query_arg()));
          exit;
        }
      }
      if(
        (isset($_POST[\'action\']) && $_POST[\'action\'] == \'bulk-delete\') ||
        (isset($_POST[\'action2\']) && $_POST[\'action2\'] == \'bulk-delete\')
      ) {
        $delete_ids = esc_sql($_POST[\'bulk-delete\']);
        foreach($delete_ids as $id) {
          self::delete_customer($id);
        }
        wp_redirect(esc_url(add_query_arg()));
        exit;
      }
    }
  }

  $customers_table = new CustomerList();
  ?>
    <div class="wrap">
      <h2>Customers</h2>
      <form method="post">
        <?php
          $customers_table->prepare_items();
          $customers_table->display();
        ?>
      </form>
    </div>
  <?php
}
?>
我无法从调试中找出答案。据我所知,一切都与我所遵循的几乎一模一样here.

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

因为列标题是registered late. 您应该在页面上呈现管理通知之前,即WordPress触发钩子之前,注册标题(即初始化列表表类实例)admin_notices.

但是你的customer_list_page() 函数,我相信它是add_menu_page()add_submenu_page(), 只有在显示管理通知(和其他内容)后才会调用,因此get_column_headers() (由使用WP_List_Table::get_column_info()) 无法识别列表的列标题。那是因为get_column_headers() 将列标题存储在静态变量/数组中,一旦设置,将不再修改,因此下次为屏幕/页面调用该函数时,该函数将返回“旧”列标题。

更具体地说,您的类实例($customers_table = new CustomerList()) 应在之前初始化WP_Screen::render_screen_meta() 已调用wp-admin/admin-header.php. 如果你看WP_List_Table::single_row_columns() 由以下人员使用(尽管不是直接使用)WP_List_Table::display(), 只有在列表表中注册了有效的列标题时,才会显示正文/内容行。因此,这就解释了为什么列标题对于要显示的内容行是必需的。就像人类没有脑袋就活不下去一样。。。(:D)

如果在呈现管理通知之前无法初始化类实例。。。您可以手动设置$_column_headers

中的Soprepare_items() 方法,只需替换此:

$this->_column_headers = $this->get_column_info();
使用此选项:

$this->_column_headers = [
    $this->get_columns(),
    [], // hidden columns
    $this->get_sortable_columns(),
    $this->get_primary_column_name(),
];

但尝试始终“按时”初始化它:)

下面是一个使用load-<page hook> hook:

class My_Plugin {
    private $list_table;

    public function __construct() {
        add_action( \'admin_menu\', [ $this, \'add_admin_menus\' ] );
    }

    public function add_admin_menus() {
        $hook_name = add_menu_page( \'Customers\', \'Customers\',
            \'edit_posts\', \'my-page\', [ $this, \'render_admin_page\' ] );

        // Initialize the list table instance when the page is loaded.
        add_action( "load-$hook_name", [ $this, \'init_list_table\' ] );
    }

    public function init_list_table() {
        $this->list_table = new CustomerList;
    }

    public function render_admin_page() {
        ?>
            <div class="wrap my-plugin">
                <h1>Customers</h1>
                <?php $this->list_table->prepare_items(); ?>
                <?php $this->list_table->display(); ?>
            </div>
        <?php
    }
}

if ( is_admin() ) {
    new My_Plugin;
}
这只是一个温和的提醒,要仔细检查emial 在您的get_sortable_columns()... =) 快乐的编码!

相关推荐

迁移到其他位置后无法访问wp-admin

我一直在我的博客上工作。昨天我做了所有备份(文件和数据库),我更改了wp配置。php和新用户、DB名称和密码,我在我的实际URL上发布了所有内容。http://agenciamoka.com我的测试URL是http://mokaweb.com.br/Moka/嗯,在我决定访问wp admin之前,一切都很好。当我尝试访问wordpress面板时,它会更改为旧的URL。直截了当:每个链接都指向旧URL。有人知道我要做什么吗?