Crearea unui tabel în stilul panoului de administrare?
Care este modalitatea recomandată de a crea o pagină cu un tabel, în stilul tabelelor care afișează articole sau utilizatori în zona de administrare?
Extind plugin-ul Cache Images, și acesta conține un tabel cu domenii și un număr de imagini de pe acel domeniu. Deci nu există un tabel echivalent existent pe care să-l pot folosi ca bază (în prima versiune a acestei întrebări, am întrebat despre un tabel cu articole, dar acolo aș fi putut (poate) extinde tabelul existent de articole).
Ar trebui să mă bazez pe pagina de prezentare generală a articolelor și să încep cu un <table class="widefat">
, sau există funcții mai bune care gestionează acest lucru acum? Cunoașteți un exemplu curat și gol de tabel cu paginare pe care aș putea să-mi bazez munca?

Acesta este ceea ce folosesc în general:
<table class="widefat fixed" cellspacing="0">
<thead>
<tr>
<th id="cb" class="manage-column column-cb check-column" scope="col"></th> // această coloană conține casete de bifare
<th id="columnname" class="manage-column column-columnname" scope="col"></th>
<th id="columnname" class="manage-column column-columnname num" scope="col"></th> // "num" adăugat deoarece coloana conține numere
</tr>
</thead>
<tfoot>
<tr>
<th class="manage-column column-cb check-column" scope="col"></th>
<th class="manage-column column-columnname" scope="col"></th>
<th class="manage-column column-columnname num" scope="col"></th>
</tr>
</tfoot>
<tbody>
<tr class="alternate">
<th class="check-column" scope="row"></th>
<td class="column-columnname"></td>
<td class="column-columnname"></td>
</tr>
<tr>
<th class="check-column" scope="row"></th>
<td class="column-columnname"></td>
<td class="column-columnname"></td>
</tr>
<tr class="alternate" valign="top"> // acest rând conține acțiuni
<th class="check-column" scope="row"></th>
<td class="column-columnname">
<div class="row-actions">
<span><a href="#">Acțiune</a> |</span>
<span><a href="#">Acțiune</a></span>
</div>
</td>
<td class="column-columnname"></td>
</tr>
<tr valign="top"> // acest rând conține acțiuni
<th class="check-column" scope="row"></th>
<td class="column-columnname">
<div class="row-actions">
<span><a href="#">Acțiune</a> |</span>
<span><a href="#">Acțiune</a></span>
</div>
</td>
<td class="column-columnname"></td>
</tr>
</tbody>
</table>
Sper că te ajută.

este posibil să ai paginare automată inserată astfel? (de exemplu, afișând postările 1-20)

@MichielStandaert dacă dorești un rezultat paginat poți folosi paginate_links

Mulțumesc! (Dar tot mă întreb de ce nu au folosit :odd
pentru rânduri în loc să ne lase să adăugăm o clasă la fiecare două rânduri...)

Folosește API-ul Core, nu doar CSS-ul său
În mod normal, folosești doar o instanță a clasei WP_List_Table
.
Ghiduri:
- Mai multe informații în Codex aici.
- Iată și un ghid de la WP Engineer - prea mult pentru a-l copia aici.
- Și un alt ghid pe Smashing Magazine online.
Beneficii?
DA!
Poți adăuga paginare, casete de căutare, acțiuni și orice magie îți poți imagina (și ești capabil să codezi).

Mic indiciu ca link pentru a vedea markup-ul, clasele pentru interfața de administrare, fără alt scop decât crearea de tabele: https://github.com/bueltge/WordPress-Admin-Style

>Accesul la această clasă este marcat ca privat. Asta înseamnă că nu este destinată utilizării de către dezvoltatorii de plugin-uri și teme, deoarece poate fi modificată fără avertizare în orice versiune viitoare a WordPress. Dacă totuși doriți să folosiți clasa, ar trebui să faceți o copie pentru a o utiliza și distribui împreună cu propriul proiect, sau să o folosiți pe propriul risc.

@AustinPray O copie? Nu, te rog nu face asta. Există versiuni beta, RC și alte pre-lansări de WP disponibile. Pur și simplu actualizează implementarea/extensia ta. Dacă chiar trebuie să mergi pe o cale separată, scrie ceva mai bun pe cont propriu. Codul de bază nu este atât de bun.

@kaiser Nu împușca mesagerul, acestea nu sunt cuvintele mele. Am citat din WP Codex. Deși înscrierea ta în teste de regresie perpetue cu fiecare beta și RC nu sună mult mai bine decât copierea clasei. Sunt de acord că scrierea propriei clase simple este o cale mai bună înainte.

@AustinPray Fără supărare :) Codex este scris de oameni ca tine și mine. De fapt, poți merge acum și să anulezi acea afirmație, iar oamenii o vor cita.

Din păcate, ambele ghiduri sunt foarte învechite, începând cu WordPress 5, lucru pe care l-am descoperit pe pielea mea în timp ce stricam lucruri (De asemenea, cel de la Smashing Magazine are erori de sintaxă evidente - cineva nu a reușit să stăpânească copy&paste). Nu am găsit o alternativă actualizată (custom-list-table-example
este doar puțin mai bun), iar Codex lipsește multe lucruri. Am reușit să scriu o implementare simplă uitându-mă la WordPress însuși, în special la class-wp-users-list-table.php
, care este aproape complet funcțională, dar mai simplă decât alte clase WP.

@Guss Răspunsul este din 2012. S-ar putea să dorești să adaugi propriul răspuns pentru a oferi o soluție mai actualizată :)

Folosiți acest exemplu (scris ca un plugin) pentru a vă crea tabelele de administrare:
http://wordpress.org/extend/plugins/custom-list-table-example/
Acesta utilizează clasa încorporată WP_List_Table.

Cred că acesta ar trebui să fie răspunsul acceptat. De asemenea, consultați acest articol din Smashing Magazine care prezintă o abordare similară: http://wp.smashingmagazine.com/2011/11/03/native-admin-tables-wordpress/

De asemenea, puteți folosi acest mic plugin pentru a vizualiza posibilitățile backend-ului în WordPress: https://github.com/bueltge/WordPress-Admin-Style

Există multe opțiuni bune aici. Dar nu există una rapidă și simplă:
<table class="widefat striped fixed">
<thead>
<tr>
<th>Antet1</th>
<th>Antet2</th>
<th>Antet3</th>
</tr>
</thead>
<tbody>
<tr>
<td>Conținut1</td>
<td>Conținut2</td>
<td>Conținut3</td>
</tr>
</tbody>
<tfoot>
<tr>
<th>Subsol1</th>
<th>Subsol2</th>
<th>Subsol3</th>
</tr>
</tfoot>
</table>
Explicație
- Clasa
widefat
este folosită decommon.css
, încărcat în administrație, pentru a face tabelul să arate ca un tabel WordPress. - Clasa
striped
îl face dungat (ce surpriză). - Clasa
fixed
adaugă CSS-ul:table-layout: fixed;

Pentru cei care doresc să implementeze WP_List_Table
, vă rugăm să rețineți că toate ghidurile pe care le-am găsit sunt depășite și fie vă vor cere să scrieți cod redundant, fie vă vor cere să faceți lucruri care nu mai funcționează.
Iată un exemplu minimal care funcționează într-o oarecare măsură. Ar trebui să fie ușor de înțeles fără un "ghid" și vă va ajuta să începeți.
Include:
- filtre rapide (vizualizări)
- caseta de căutare
- acțiuni pe rând
Lipsesc:
- configurarea dimensiunii paginii (de fapt, nu am văzut nicio pagină WordPress care să folosească această funcționalitate)
- acțiuni în masă
- filtre dropdown
class My_List_Table extends WP_List_Table {
function __construct() {
parent::__construct([
'singular' => 'angajat',
'plural' => 'angajati',
]);
}
function get_columns() {
return [
'name' => __('Nume'),
'employer' => __('Angajator'),
'rank' => __('Grad'),
'phone' => __('Telefon'),
'joined' => __('Data Angajării'),
];
}
/* Opțional - fără acesta niciun coloană nu este sortabilă */
public function get_sortable_columns() {
return [
// cheile sunt "nume_coloană" ca mai sus
// valorile sunt nume de câmpuri pentru "order" conform nevoilor modelului tău de date
'name' => 'name',
'employer' => 'employer',
'rank' => 'rank',
'joined' => 'joined',
];
}
public function prepare_items() {
// suport pentru caseta de căutare
$search = @$_REQUEST['s'] ? wp_unslash(trim($_REQUEST['s']))) : '';
// obține numărul de înregistrări pe pagină din stocarea opțiunilor
$per_page = $this->get_items_per_page('my_list_table_per_page');
// umple array-ul de date cu elementele modelului tău. În implementarea mea acestea
// sunt instanțe StdClass cu diverse câmpuri, dar poate fi orice
// vom vedea imediat cum.
$this->items = get_model_items([
'offset' => ($this->get_pagenum()-1)*$per_page,
'count' => $per_page,
'orderby' => @$_GET["orderby"] ?: 'id', // câmpul implicit de ordonare, dacă nu este specificat
'order' => @$_GET["order"] ?: 'ASC', // direcția implicită de ordonare
'search' => $search, // trece câmpul de căutare dacă este setat
'status' => @$_REQUEST['status'] // trece filtrul de vizualizare, dacă este setat [vezi get_views()]
);
$this->set_pagination_args([
"total_items" => get_model_item_count(),
"per_page" => $per_page,
]);
// `get_model_item_count` ar trebui să fie numărul total de înregistrări după
// filtrare (vizualizări și căutare) dar înainte de paginare. Acest lucru poate fi greu/ineficient
// de realizat cu MySQL. Dacă doriți să puneți rezultatele `COUNT(*)` aici,
// nimeni nu vă va învinui.
}
public function column_default($item, $column_name) {
// prezentarea implicită a coloanei
// Majoritatea câmpurilor obiectului meu sunt afișabile așa cum sunt, așa că avem o metodă
// generică pentru a gestiona acest lucru.
return $item->$column_name;
}
/* Opțional, cu excepția cazului în care aveți date care necesită formatare specială */
public function column_joined($item) {
// Câmpul 'joined' este un obiect DateTime și nu poate fi convertit implicit
// la string de către logica încorporată, așa că va trebui să facem acest lucru manual
return $item->joined->format("Y-m-d");
}
/* Opțional - afișează filtre rapide deasupra tabelului */
public function get_views() {
$makelink = function($filter_val, $name) { // unealtă pentru a evita repetiția în crearea vizualizărilor
$filter_name = 'status';
return '<a href="'
. esc_url(add_query_arg($filter_name, $filter_val)) . '" ' .
(@$_REQUEST[$filter_name]==$filter_val ?
'class="current" aria-current="page"' : ''). ">" .
$name . "</a>";
};
return [
'all' => $makelink(false, __('Toți')),
'green' => $makelink('green', __('Începători')),
'pros' => $makelink('pro', __('Experți')),
'bofh' => $makelink('veteran', __('Veterani')),
];
}
/* Opțional: acțiuni pe rând */
public function handle_row_actions($item, $column_name, $primary) {
$out = parent::handle_row_actions($item, $column_name, $primary);
if ($column_name === $primary)
$out .= $this->row_actions([
'edit' => sprintf('<a href="%s">%s</a>',
add_query_arg('employee_id', $item->id, admin_url('admin.php?page=edit-employee')),
__("Editează")),
'delete' => sprintf('<a href="%s">%s</a>',
add_query_arg('employee_id', $item->id, admin_url('admin.php?page=delete-employee')),
__("Șterge")),
]);
return $out;
}
}
Apoi funcția paginii de administrare (pentru add_menu_page
/add_submenu_page
) poate arăta astfel:
function drawAdminPage() {
$my_list_table = new My_List_Table();
$my_list_table->prepare_items();
?>
<div class="wrap">
<h1 class="wp-heading-inline"><?php _e('Titlul Paginii de Administrare')?></h1>
<hr class="wp-header-end">
<?php $my_list_table->views() ?>
<form id="employee-filter" method="get">
<input type="hidden" name="page" value="<?php echo $_REQUEST['page']?>">
<?php $my_list_table->search_box(__('Caută'), 'employee') ?>
<?php $my_list_table->display(); ?>
</form>
</div>
<?php
}

Ai putea dori să adaugi un filtru la lista de postări personalizate în administrare? Răspunsul legat mai jos arată cum să faci asta cu o taxonomie, dar ai putea folosi și alte criterii în hook-ul tău restrict_manage_posts
:
Spune-mi dacă ai mai multe întrebări.

Îmi cer scuze pentru întrebarea neclară. În primul meu exemplu era un tabel de articole, și într-adevăr, aș putea încerca să folosesc tabelul existent de articole pentru asta (chiar dacă vreau doar să afișez titlurile articolelor și apoi toate coloanele personalizate?). Dar acum am editat întrebarea mea cu un exemplu concret: am un tabel de domenii, deci nu există un tabel echivalent existent pe care să-l pot extinde.

@Jan: Ah. Da, cred că ai descoperit adevărul, că nu există o modalitate bună și încapsulată de a face asta în afară de a scrie HTML (duplicat). Am avut des aceeași problemă. Poate creează un tichet pe trac cerând această îmbunătățire și postează link-ul/numărul tichetului aici ca să-l putem susține.
