Gestire un database custom in WordPress con WP_List_Table
da Massimo Della Rovere · pubblicato il 23 aprile, 2015 · modificato il 5 agosto, 2017

Quando programmiamo in WordPress utilizziamo sempre il database SQL messo a disposizione dal CMS, il quale ci permette, tramite dei Custom Post Type o dei Custom Fields, di creare delle strutture di dati complesse anche se non sono state previste dal modulo standard. Purtroppo però esistono dei casi dove questa tecnica non è sufficiente e la soluzione migliore è quella di utilizzare un proprio database MySQL, completamente separato dalle tabelle standard ma integrato nel backend.

Ad esempio, potremmo utilizzare un database personalizzato nello sviluppo di un plugin come quello di un e-commerce. In questa maniera avremo uno sviluppo di codice più complesso ma otterremo sicuramente delle performance migliori. Un’altro caso comune è quando si devono integrare dei database già esistenti, come ad esempio, delle anagrafiche clienti, articoli, fornitori, etc. In questo caso è molto più facile integrare le tabelle in WP con la struttura originale che andarli a convertire.

WordPress & WP_List_Table

Si possono utilizzate diverse tecniche per visualizzare i contenuti di un database nella parte di amministrazione. Il modo migliore è sicuramente quello di usare la classe standard messa a disposizione da WordPress WP_List_Table. Tramite questa classe possiamo creare un’interfaccia molto simile a quella con cui visualizziamo i posts, le pagine e i custom post type. In questa maniera possiamo ottenere un’interfaccia coerente con il resto del pannello di admin e beneficiare di eventuali aggiornamenti.

Per eseguire il tutorial sulla classe WP_List_Table vi dividerò le diverse funzioni in capitoli separati. In questa maniera risulterà più facile la spiegazione generale e il codice potrà essere analizzato con più facilità rispetto alla soluzione con codice completo. I passi che verranno analizzati in questo articolo saranno i seguenti:

  1. Creazione Database.
  2. Creazione Menu dedicato al database.
  3. Creazione Lista con il contenuto del database.
  4. Creazione CSS per output dei campi.
  5. Creazione Navigatore per la paginazione.
  6. Creazione Ricerca per i record del database.
  7. Creazione Azioni da eseguire sui record.

Vi consiglio, oltre a leggere le varie sezioni, di provarle in un’ambiente di prova una alla volta rispettando la sequenza riportata. In questa maniera sarà possibile creare un codice più ordinato e facilmente modificabile in base alle vostre esigenze.

Creazione di un database

Ovviamente la prima cosa che dobbiamo avere è un database. Per rendere più semplice il tutorial ve ne propongo uno che ho già avuto la necessità di integrare in un’installazione recente di WordPress. È un database clienti che appartiene ad un punto vendita di prodotti al dettaglio. Vi lascio qui di seguito il comando per crearlo sul vostro database di prova, in maniera che possiate eseguire tutte le prove.

CREATE TABLE `wp_PVCLI00F` (
`tessera` char(13) NOT NULL,
`nome` char(15) DEFAULT NULL,
`cognome` char(20) DEFAULT NULL,
`datadinascita` date DEFAULT NULL,
`luogodinascita` char(25) DEFAULT NULL,
`provinciadinascita` char(25) DEFAULT NULL,
`nazione` char(25) DEFAULT NULL,
`indirizzo` char(35) DEFAULT NULL,
`localita` char(25) DEFAULT NULL,
`provincia` char(2) DEFAULT NULL,
`cap` char(9) DEFAULT NULL,
`tipotessera` char(3) DEFAULT NULL,
`categoria` char(3) DEFAULT NULL,
`sesso` char(1) DEFAULT NULL,
`partitaiva` char(11) DEFAULT NULL,
`codicefiscale` char(16) DEFAULT NULL,
`telefono` char(20) DEFAULT NULL,
`cellulare` char(20) DEFAULT NULL,
`email` char(50) DEFAULT NULL,
`dataprimoacquisto` date DEFAULT NULL,
`dataultimoacquisto` date DEFAULT NULL,
`spesatotale` decimal(10,2) DEFAULT NULL,
`totalescontrini` int(11) DEFAULT NULL,
`totalearticoli` int(11) DEFAULT NULL,
`totalepunti` int(11) DEFAULT NULL,
`puntiattuali` int(11) DEFAULT NULL,
PRIMARY KEY (`tessera`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Database Clienti';

Una volta creato il database cercate di popolarlo con qualche record, in modo da avere qualche contenuto da visualizzare nel pannello admin. Se volete potete anche scaricare questo file (PVCLI00F) che contiene già dei record di prova. Basta eseguire il download del file e utilizzarlo con la funzione di ripristino presente su MySQL.

Il database presente nel download contiene nomi e dati anagrafici non reali, è stato creato solo a scopo di prova per avere dei dati da visualizzare. Notate anche che nel codice indico il prefisso “wp_”, ma in realtà voi dovrete utilizzare il vostro prefisso.

Adesso che abbiamo il database possiamo creare un menu nel pannello di Admin, dedicato alla visualizzazione dei record presenti nel database. Per eseguire questo passo possiamo utilizzare le funzioni add_menu_page()add_submenu_page(). Vi allego qui di seguito il codice PHP con la spiegazione delle funzioni e delle opzioni.

// Aggiungere il menu nel pannello di amministrazione
// che riguarda il nostro database personalizzato

function my_custom_table_admin_menu()
{
  add_menu_page(
    'Anagrafiche',         // Titolo di pagina
    'Anagrafiche',         // Titolo di menu
    'publish_posts',       // Autorizzazione
    'anagrafiche',         // Menu slug
    'my_custom_table',     // Nome funzione
    'dashicons-list-view', // Icona
    25                     // Posizione menu
  );

  add_submenu_page(
    'anagrafiche',         // Parent slug
    'Clienti',             // Titolo di pagina
    'Clienti',             // Titolo di menu
    'publish_posts',       // Autorizzazione
    'anagrafiche',         // Menu Slug
    'my_custom_table'      // Nome funzione
  );
}

// Aggiungere una azione alla fase di admin_menu per
// eseguire la funzione definita precedentemente
 
add_action('admin_menu','my_custom_table_admin_menu');

// Creazione Tabella per visualizzare i records
// che sono stati memorizzati nel database PVCLI00F

function my_custom_table() {
  echo "QUI DOBBIAMO INSERIRE IL CODICE PER LA LISTA"; // Vediamo dopo
}

Se abbiamo eseguito correttamente questo codice dovremmo vedere nel nostro pannello di amministrazione un nuovo menu chiamato “Anagrafiche”, il quale una volta selezionato dovrebbe presentare una pagina vuota con il testo “QUI DOBBIAMO…” etc.

Wordpress Menu

Vi consiglio di non caricare questo codice sul file “function.php“, infatti in questo modo sarebbe caricato anche durante la visualizzazione del frontend rubando delle preziose risorse di RAM e CPU che non servono. Cercate di fare un file PHP aggiuntivo che richiamate solo quando siete sul pannello di amministrazione con is_admin().

Creazione della Lista

In questa fase andiamo a sviluppare la funzione my_custom_table() definita nel codice precedente, la quale emetteva solo una semplice stringa tramite echo(). Il codice sarà suddiviso in due parti, la prima riguarda la composizione della pagina HTML che dovrà essere visualizzata, la seconda sarà la definizione della classe WP_List_Table.

// Creazione Tabella per visualizzare i records
// che sono stati memorizzati nel database PVCLI00F

function my_custom_table()
{
  $table = new AdminTableClienti(); // Il codice della classe a seguire
  $table->prepare_items(); // Metodo per elenco campi

  // Definizione variabili per contenere i valori
  // di paginazione e il nome della pagina visualizzata

  $page  = filter_input(INPUT_GET,'page' ,FILTER_SANITIZE_STRIPPED);
  $paged = filter_input(INPUT_GET,'paged',FILTER_SANITIZE_NUMBER_INT);

  echo '<div class="wrap">';
  echo '<h2>Clienti</h2>';

  // Form per contenere la tabella con elenco records
  // presenti nel database e campi definiti nella classe

  echo '<form id="persons-table" method="GET">';
  echo '<input type="hidden" name="paged" value="'.$paged.'"/>';
    $table->display(); // Metodo per visualizzare elenco records
  echo '</form>';

  echo '</div>';
}

In fase di produzione vi conviene copiare il codice a seguire su un file dedicato e usare le funzioni di Autoloader in PHP. In questa maniera il codice sarà caricato solo quando la pagina del database sarà richiesta e ignorato nelle altre parti di admin. Adesso potete anche usarlo a seguire della funzione my_custom_table() per fare la prova.

// Se non esiste la classe eseguo il caricamento
// del file di wordpress necessario all'esecuzione

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

// Definizione Classe per il nostro database e aggiunta
// dei metodi necessari alla visualizzazione delle informazioni

class AdminTableClienti extends WP_List_Table
{
  function __construct() {
    parent::__construct(array('singular'=>'Cliente','plural'=>'Clienti'));
  }

  // Funzione per la preparazione dei campi da visualizzare
  // e la query SQL principale che deve essere eseguita 

  function prepare_items()
  {
    global $wpdb;
    $table_name = $wpdb->prefix.'PVCLI00F';
    $per_page = 25; // Numero dei record presenti in una pagina

    // Calcolo elenco de dei campi per le differenti
    // sezioni e memorizzo tutto in array separati

    $columns  = $this->get_columns();
    $hidden   = $this->get_columns_hidden();
    $sortable = $this->get_columns_sortable();

    // Bisogna memorizzare tre array che devono contenere i campi da 
    // visualizzare, quelli nascosti e quelli per eseguire l'ordinamento

    $this->_column_headers = array($columns,$hidden,$sortable);

    // Preparazione delle variabili che devono essere utilizzate
    // nella preparazione della query con gli ordinamenti e la posizione

    if (!isset($_REQUEST['paged'])) $paged = 0;
      else $paged = max(0,(intval($_REQUEST['paged'])-1)*25);

    if (isset($_REQUEST['orderby'])
        and in_array($_REQUEST['orderby'],array_keys($sortable)))
    $orderby = $_REQUEST['orderby']; else $orderby = 'tessera';

    if (isset($_REQUEST['order'])
        and in_array($_REQUEST['order'],array('asc','desc')))
    $order = $_REQUEST['order']; else $order = 'asc';

    // Calcolo le variabili che contengono il numero dei record totali
    // e l'elenco dei record da visualizzare per una singola pagina

    $total_items = $wpdb->get_var(
      "SELECT COUNT(tessera) FROM $table_name");

    $this->items = $wpdb->get_results($wpdb->prepare(
            "SELECT * FROM $table_name ".
            "ORDER BY $orderby $order ".
            "LIMIT %d OFFSET %d",$per_page, $paged), ARRAY_A);
  }

  // Funzione per la definizione dei campi che devono
  // essere visualizzati nella lista da visualizzare

  function get_columns()
  {
    $columns = array(
      'tessera'            => 'Tessera',
      'cognome'            => 'Nominativo',
      'datadinascita'      => 'Nato il',
      'indirizzo'          => 'Indirizzo',
      'localita'           => 'Località',
      'provincia'          => 'PR',
      'spesatotale'        => 'Totale',
      'totalescontrini'    => 'Scontrini',
      'spesamedia'         => 'Media',
      'puntiattuali'       => 'Punti',
      'dataprimoacquisto'  => 'Acquisto',
      'dataultimoacquisto' => 'Ultimo',
    );
    return $columns;
  }

  // Funzione per la definizione dei campi che possono
  // essere utilizzati per eseguire la funzione di ordinamento

  function get_columns_sortable()
  {
    $sortable_columns = array(
      'tessera'       => array('tessera',true),
      'cognome'       => array('cognome',true),
      'datadinascita' => array('datadinascita',false),
      'spesatotale'   => array('spesatotale',false),
      'puntiattuali'  => array('puntiattuali',false),
    );
    return $sortable_columns;
  }

  // Funzione per la definizione dei campi che devono 
  // essere calcolati dalla query ma non visualizzati

  function get_columns_hidden() {
    return array();
  }

  // Funzione per reperire il valore di un campo in
  // maniera standard senza una personalizzazione di output

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

  // Dato che alcuni campi hanno bisogno di output 
  // personalizzato bisogna creare una funzione per campo

  function column_cognome($item) { 
    return $item['cognome'].' '.$item['nome']; 
  }
 
  function column_datadinascita($item) {
    return $this->get_date_format($item['datadinascita']);
  }
 
  function column_totalescontrini($item) { 
    return number_format($item['totalescontrini'],0,',','.'); 
  }

  function column_spesatotale($item) { 
    return number_format($item['spesatotale'],2,',','.').' €'; 
  }

  function column_spesamedia($item) 
  {
    if (is_numeric($item['spesatotale']) 
        and is_numeric($item['totalescontrini'])) {

      $spesatotale = (double) $item['spesatotale'];
      $totalescontrini = (double) $item['totalescontrini'];

      if ($totalescontrini > 0) {
        return number_format($spesatotale/$totalescontrini,2,',','.').' €';
      }
    }
    return '0 €'; 
  }

  function column_puntiattuali($item) { 
    return number_format($item['puntiattuali'],0,',','.');
  }

  function column_dataprimoacquisto($item) { 
    return $this->get_date_format($item['dataprimoacquisto']);
  }

  function column_dataultimoacquisto($item) { 
    return $this->get_date_format($item['dataultimoacquisto']);
  }

  function get_date_format($date) { 
    list($year,$month,$day) = explode("-",$date);
    return "$day/$month/$year";
  }
}

A questo punto se abbiamo implementato correttamente il codice dovremmo essere in grado di visualizzare una tabella con i dati memorizzati nel nostro database. Vi allego la schermata ottenuta nel mio ambiente di prova con il codice PHP riportato e i dati presenti del database che vi ho allegato come file da scaricare nel capitolo precedente.

Demo WP table

Oltre a controllare che i dati visualizzati siano corretti, provate anche l’ordinamento dei record selezionando e cliccando sulla colonna interessata. Facendo più clic sulla colonna dovreste passare da un’ordinamento ascendente ad uno discendente.

Creazione delle regole CSS

Se vedete la schermata ottenuta è possibile notare che le colonne della lista sono tutte della stessa dimensione e i numeri sono allineati come se fossero testo. Per fare in modo che la lista abbia un’aspetto più gradevole e funzionale bisogna aggiungere un file CSS nel pannello di amministrazione e indicare le regole di visualizzazione.

// Caricamento file CSS personalizzato solo per
// quanto riguarda i componenti di amministrazione

function my_theme_load_admin_styles() {
  wp_enqueue_style ('my_admin_css_theme',
      get_template_directory_uri().'/style-admin.css',false,'1.0.0');
}

add_action('admin_enqueue_scripts','my_theme_load_admin_styles');

Con questo codice si indica a WordPress di caricare il file style-admin.css che dovrà essere presente nella directory del vostro tema. In questo file potete indicare tutte le regole CSS che volete, facendo riferimento al fatto che WP identificherà con una classe ogni colonna e chiamandola con la stringa “column-” + il nome della colonna.

table.wp-list-table.clienti {
  table-layout: auto;
}

/* DEFINIZIONE COLONNE PER TABELLA */
/* COLLEGATA AD ANAGRAFICA CLIENTI */

th.column-tessera,
td.column-tessera {
  width:8em;
}

th.column-datadinascita,
td.column-datadinascita {
  width:6em;
}

th.column-provincia,
td.column-provincia {
  width:2em;
}

th.column-totalescontrini,
td.column-totalescontrini {
  width:4em;
  text-align: right;
}

th.column-spesatotale,
td.column-spesatotale {
  width:6em;
  text-align: right;
}

th.column-spesamedia,
td.column-spesamedia {
  width:5em;
  text-align: right;
}

th.column-puntiattuali,
td.column-puntiattuali {
  width:5em;
  text-align:right;
}

th.column-dataprimoacquisto,
td.column-dataprimoacquisto {
  width:6em;
}

th.column-dataultimoacquisto,
td.column-dataultimoacquisto {
  width:6em;
}

th.column-spesatotale.sorted a span,
th.column-spesatotale.sortable a span,
th.column-puntiattuali.sorted a span,
th.column-puntiattuali.sortable a span {
  float:right;
  margin-left:10px;
}

td.column-tessera,
td.column-puntiattuali {
  font-weight:bold;
}

Vi riporto qui di seguito il risultato finale, dove possiamo notare che con poche regole CSS abbiamo ottenuto un’aspetto più gradevole rispetto al precedente. Ovviamente se avete una buona preparazione grafica potete ottenere dei risultati migliori. Io sono molto minimalista nei layout e non mi avventuro in cose strane perché farei disastri :)

WP Table

Volendo è possibile anche inserire le regole CSS in modalità inline solo nella pagina in cui viene richiesto, evitando in questa maniera di caricare un file esterno. Dato che non esiste una documentazione sulle classi, se avete la necessità di fare delle modifiche più precise usate lo strumento di sviluppo del browser per scoprire le classi utilizzate.

Sono sicuro che molti voi si sono accorti che l’elenco dei clienti che abbiamo sviluppato non prevede una cosa molto importante, la paginazione. Infatti viene visualizzata solo la prima pagina dei risultati e non è presente il navigatore per scorrere le altre pagine. Per aggiungere questo componente basta richiamare un metodo della classe passando il totale dei record, i record per pagina e il totale delle pagine.

// Aggiungete il codice del navigatore alla funzione esistente
// prepare_items() che abbiamo definito nella classe precedente

function prepare_items() {
  [....]

  $this->set_pagination_args(array(
    'total_items' => $total_items,
    'per_page'    => $per_page,
    'total_pages' => ceil($total_items/$per_page)
  ));

  [....]
}

Una volta effettuata questa modifica alla funzione eseguiamo il refresh della pagina in cui viene visualizzato il database e controlliamo se è stato aggiunta la paginazione. Vi elenco qui di seguito la schermata che ho ottenuto nel mio ambiente di prova.

WP table

Usando il database che vi ho fornito dovreste ottenere circa 72 elementi e 3 pagine totali per la navigazione, in quanto abbiamo impostato nel programma un valore di 25 records per pagina. Potete cambiare questo valore e controllare i calcoli sul navigatore.

Creazione di una Ricerca

Un’altro componente interessante e da aggiungere alla tabella è il campo per la ricerca che troviamo nell’elenco dei post/pagine. Per sviluppare questa funzione bisogna definire un form di sottomissione con il campo di ricerca e poi gestire la richiesta sempre tramite la nostra funzione prepare_items() che dovrà tenere conto di questo nuovo parametro prima di eseguire le query SQL che abbiamo già definito nella classe.

// Creazione Tabella per visualizzare i records
// che sono stati memorizzati nel database PVCLI00F

function my_custom_table()
{
  $table = new AdminTableClienti(); // Il codice della classe a seguire
  $table->prepare_items(); // Metodo per elenco campi

  // Definizione variabili per contenere i valori
  // di paginazione e il nome della pagina visualizzata

  $page = filter_input(INPUT_GET,'page' ,FILTER_SANITIZE_STRIPPED);
  $paged = filter_input(INPUT_GET,'paged',FILTER_SANITIZE_NUMBER_INT);

  echo '<div class="wrap">';
  echo '<h2>Clienti</h2>';

  // Form di ricerca da aggiungere prima della tabella
  // indicare i campi hidden che si vogliono conservare

  echo '<form method="get">';
  echo '<input type="hidden" name="page" value="'.$page. '"/>';
    $table->search_box('Ricerca','search_id');
  echo '</form>';

  // Form per contenere la tabella con elenco records
  // presenti nel database e campi definiti nella classe

  echo '<form id="persons-table" method="GET">';
  echo '<input type="hidden" name="paged" value="'.$paged.'"/>';
    $table->display(); // Metodo per visualizzare elenco records
  echo '</form>';

  echo '</div>';
}

Se sostituite la funzione my_custom_table() definita in precedenza con questo codice, verrà aggiunto un nuovo campo per eseguire la ricerca, il quale verrà posizionato prima della tabella dei dati del database. Ovviamente la ricerca ancora non sarà funzionante, in quanto dovremmo ancora modificare la funzione prepare_items() per gestire la variabile di ricerca e cambiare la query che attualmente legge tutto il database.

WP table

Se analizzate la funzione prepare_items() che abbiamo sviluppato fino a questo momento, trovate due righe in cui calcoliamo le variabili $total_items e $this->items con una query particolare, questo codice deve essere modificato per aggiungere un WHERE quando viene eseguita una ricerca e quindi esiste il parametro “s”.

// Aggiungete il codice del navigatore alla funzione esistente
// prepare_items() che abbiamo definito nella classe precedente

function prepare_items() {
  [....]

  // Calcolo le variabili che contengono il numero dei record totali
  // e l'elenco dei record da visualizzare per una singola pagina
 
  if (isset($_REQUEST['s']) and !empty($_REQUEST['s'])) 
  {
    $WHERE = $wpdb->prepare(
      "WHERE cognome LIKE '%%%s%%' OR nome LIKE '%%%s%%'",
      $_REQUEST['s'],$_REQUEST['s']
    );

    $total_items = $wpdb->get_var(
      "SELECT COUNT(tessera) FROM $table_name $WHERE");

    $this->items = $wpdb->get_results($wpdb->prepare(
      "SELECT * FROM $table_name ".
      "WHERE `cognome` LIKE '%%%s%%' OR `nome` LIKE '%%%s%%' ".
      "ORDER BY $orderby $order ".
      "LIMIT %d OFFSET %d",
      $_REQUEST['s'],$_REQUEST['s'],$per_page,$paged),ARRAY_A);

  } else {

    $total_items = $wpdb->get_var(
      "SELECT COUNT(tessera) FROM $table_name");

    $this->items = $wpdb->get_results($wpdb->prepare(
      "SELECT * FROM $table_name ".
      "ORDER BY $orderby $order ".
      "LIMIT %d OFFSET %d",$per_page,$paged),ARRAY_A);
  }

  [....]
}

Adesso che abbiamo implementato il codice possiamo provare una ricerca di test per controllare se abbiamo eseguito correttamente tutti i passaggi. Vi lascio una nuova schermata sui cui ho eseguito la ricerca con il termine “PAOLA”, il quale verrà ricercato nei campi del database “nome e cognome”. Ovviamente potete personalizzare come volete questo comportamento, basta modificare la composizione di WHERE.

WP table

NB: Ogni volta che eseguite una ricerca verranno selezionati i record con la nuova query e verrà reimpostato l’ordinamento per tessera. Se volete cambiare questo metodo basta indicare nel form i campi che si vogliono preservare, ad esempio se indichiamo il valore di orderby corrente la ricerca manterrà l’ultimo ordinamento attivo.

Definizione delle Azioni

Per aggiungere delle opzioni in stile standard di WP, dobbiamo definire una nuova funzione per il primo campo della tabella e aggiungere le azioni permesse. Nel nostro caso il campo è il numero della tessera, quindi definiamo nella nostra classe un nuovo metodo che andiamo a chiamare column_tessera() e aggiungiamo il seguente codice:

// Funzione per la personalizzazione output del numero
// di tessera del cliente e le azioni permesse sul record

function column_tessera($item)
{
  // Definizioni azioni che devo comparire sotto la 
  // tessera quando andiamo in hover con il mouse

  $actions = array(
    'edit'   => 
      sprintf('<a href="?page=%s&action=%s&cliente=%s">Edit</a>',
         $_REQUEST['page'],'edit',$item['tessera']),

    'delete' => 
      sprintf('<a href="?page=%s&action=%s&cliente=%s">Delete</a>',
         $_REQUEST['page'],'delete',$item['tessera']),
  );

  // Ritorno  il valore della colonna tessera e
  // richiamo il metodo row_actions per le azioni 

  return sprintf('%1$s %2$s',$item['tessera'],
    $this->row_actions($actions));
}

Una volta implementato il codice aggiorniamo la pagina della tabella del database e posizioniamo il cursore sul campo tessera. Ci dovrebbe comparire quanto segue:

WP table

Possiamo anche associare una azione tramite la casella di spunta e la selezione da un menu a tendina seguendo lo stile standard di WordPress. Per fare questo dobbiamo creare una colonna che contiene il campo di spunta e definire una nuova funzione nella nostra classe che deve essere chiamata get_bulk_actions().

// Definire la nuova funzione per indicare le
// azioni che devo essere presenti sul menu a tendina

function get_bulk_actions() {
  return array('delete' => 'Delete');
}

// Funzione per la prima colonna che non sarà più il 
// numero di tessera ma un campo di checkbox per la selezione

function column_cb($item) {
  return sprintf(
    '<input type="checkbox" name="tessera[]" value="%s"/>',$item['tessera']);
}

// Funzione dei campi da visualizzare dove va aggiunto il 
// nuovo campo di checkbox prima di tutti gli altri, per
// comodità vi riscrivo tutta la funzione completa da sostituire

function get_columns()
{
  $columns = array(
    'cb'                 => '<input type="checkbox"/>',
    'tessera'            => 'Tessera',
    'cognome'            => 'Nominativo',
    'datadinascita'      => 'Nato il',
    'indirizzo'          => 'Indirizzo',
    'localita'           => 'Località',
    'provincia'          => 'PR',
    'spesatotale'        => 'Totale',
    'totalescontrini'    => 'Scontrini',
    'spesamedia'         => 'Media',
    'puntiattuali'       => 'Punti',
    'dataprimoacquisto'  => 'Acquisto',
    'dataultimoacquisto' => 'Ultimo',
  );
  return $columns;
}

Finalmente siamo arrivati all’ultimo passo, non ci resta che controllare ancora una volta il risultato finale e verificare le modifiche apportate alla classe. Vi elenco qui di seguito l’ultima schermata di questo tutorial con le azioni in formato tendina:

WP table

Ovviamente per ogni azione bisognerebbe sviluppare una pagina con tutti i campi da modificare in base alle informazioni del database. Questa operazione si deve eseguire utilizzando i metabox e i custom fields, non riporterò nessun esempio su questa fase in quanto andremmo fuori tema con argomenti differenti dallo scopo del tutorial.

22 Commenti

  1. Ho trovato questo tutorial per caso e dopo averlo letto mi è venuta la seguente domanda: Chi ti lo ha fatto fare di perdere così tanto tempo a scrivere? Voglio dire. Come post non presenta alcun tipo di utilità se non un modo, direi confusionario, per mostrare come WordPress implementa (in modo altrettanto confusionario) un pattern ORM. Molte parole ma pochi contenuti; ti limiti a visualizzare i dati in una tabella e fare una ricerca. Se è vero che questa è la base di qualsiasi tutorial è altrettanto vero che ti sei dilungato troppo per delle funzionalità che tutto sommato sono molto semplici. Hai chiuso il post dicendo: "Ovviamente per ogni azione bisognerebbe sviluppare una pagina con tutti i campi da modificare in base alle informazioni del database. Questa operazione si deve eseguire utilizzando i metabox e i custom fields, non riporterò nessun esempio su questa fase in quanto andremmo fuori tema con argomenti differenti dallo scopo del tutorial." Non è assolutamente vero che per ogni azione dovresti usare metabox e campi personalizzati. Pensa ad esempio a un ipotetica scheda anagrafica dei tuoi clienti. Sei sicuro di voler utilizzare metabox e campi personalizzati? Per fartene cosa ? Giusta la scelta di appoggiarsi alle caratteristiche di WordPress per implementare la tabella riassuntiva (risparmi tempo e vai sul sicuro) ma il resto è lasciato alla pura fantasia di chi vuole poi implementare un layout ad hoc. Forse, anzi sicuramente, il tutto era fattibile utilizzando molti meno campi (12 campi nel database solo per un tutorial sono decisamente troppi e aprono le porte a molte problematiche...le stesse che portano a dire che andare oltre esula dagli scopi del tutorial) ma completando il crud dato in entrambi i casi le funzioni in se sono abbastanza semplici. Nel caso della cancellazione la più grezza e basilare forma consiste nel passare l'id corrispondente all'elemento da cancellare e così pure per la modifica in quanto estrarre i dati da un database e visualizzarli in una tabella o in un campo (es: un input) è solo questione di passare il valore di quel campo all'attributo. Niente di complesso o fantascientifico. Pessimo e tempo di lettura buttato dalla finestra. Adriano

  2. Ciao Massimo, innanzitutto grazie mille per questo tutorial, molto chiaro e ben spiegato! Ho seguito passo passo le tue istruzioni e funziona tutto, ora però avrei bisogno di capire come implementare le funzioni di EDIT. Hai già scritto al riguardo? sai dove indirizzarmi? Grazie mille! E complimenti ancora!

  3. Ciao! Complimenti per la guida, è fantastica! Una domanda... Sapresti dirmi come potrei fare per usare questa cosa con il database di wp? Sto cercando in pratica di interagire con una tabella di un plugin che contiene dei dati che vorrei visualizzare in backend nel modo che hai utilizzato qui sopra.

  4. Ciao Massimo, grazie del tutorial. Mi funziona praticamente tutto, l'unica cosa che non riesco a fare apparire è il menu (edit|delete) che si dovrebbe mostrare con il mouse over...cosa avrò sbagliato? Posso incollarti qui il mio codice?

  5. Ciao Carla, il problema dovrebbe essere il fatto che quando indichi i campi sulla funzione get_columns() il secondo campo lo definisci come (aznrea) che non richiamerá la funzione column_Nrea($item) in quanto ha un nome diverso, o cambi il nome del campo o il nome della funzione in column_aznrea($item). Spero che funzioni... non ho provato :D

  6. Purtroppo non funziona lo stesso :-(

  7. Ciao Massimo, anche io ho seguito il tuo tutorial con molto interesse e in un ambiente di prova sul mio pc windows con il tema twenty sixteen non ho avuto nessun problema. Quando poi ho cercato di portarlo su un sito che sto provando a gestire con il tema formation pro non ha funzionato. Ho provato a modificare il functions.php del tema ma il risultato è praticamente nullo cioè non riesco nemmeno ad inserire la nuova voce di menu. Mi sai dare qualche suggerimento? Grazie

  8. Ciao Stefano, purtroppo non avendo esperienza con il tema che indichi non posso aiutarti più di tanto. Io negli esempi uso delle chiamate standard di WordPress che dovrebbero funzionare su qualsiasi tema, sempre che quest'ultimo rispetti la sequenza dei filtri scritti da altri e non cancelli o crei conflitto con quelli del tema. Putroppo però molte volte non è così e danno attenzione solo al loro tema :D

  9. Ciao, mi chiamo Massimo ti faccio i complimenti per l'articolo. Alla parte di gestione dei clienti avrei bisogno di collegare tre funzioni: - una registrazione dell'utente, una specie di profilazione, che plug in mi consigli? - la possibilità di vedere di poter far accedere 4 diversi profili al back end e quindi vedere i propri clienti in base all'autorizzazioni: SuperAdmin - Admin (che vede unicamente i clienti collegati a lui) - User top (che vede gli user collegati solo a lui) e gli user normali che vedono solo i loro profili. MI puoi dare qualche consiglio? grazie

  10. Ciao Massimo, come sempre semplice, preciso ed esaustivo. Complimenti davvero. Ovviamente ho sperimentato subito il tutorial e tutto funziona. Ma per creare la pagina edit-post? Potresti indicarmi qualche altro tutorial? Ci sto provando ma credo proprio mi manchi un passaggio. Grazie mille e ancora complimenti per il tuo lavoro.

  11. Ciao Stefano, sono contento che l'articolo ti sia servito, con questa tecnica puoi migliorare veramente di tanto le operazioni che puoi fare sul backend. Per fare la funzione di edit devi creare una pagina "opzioni" a cui devi passare su URL il post che vuoi modificare e il codice è custom.

    https://codex.wordpress.org/index.php?title=Creating_Options_Pages
    https://wptavern.com/wp-settings-generator-quickly-create-a-custom-options-page-using-the-wordpress-settings-api

  12. Ottima guida. Chiara ed istruttiva. Complimenti.

    Esiste qualcosa del genere per il frontend? Mi spiego meglio. Il metodo che utilizzo non è certamente il più professionale ma funziona abbastanza bene e purtroppo non sono un grande programmatore php etc.. Ho un db in MSaccess che crea dei post collegati tra loro tramite i permalink. In sostanza, dopo l’inserimento dei dati base, ottengo un bel file csv con tutti i dati necessari a far funzionare WordPress importando il csv stesso. Eseguita l’importazione in wp tutto funziona perfettamente, Categorie, ricerca e listati dei post funzionano benissimo.

    Ho fatto solo alcune personalizzazioni ad un tema base. Sto parlando di almeno 1000/2000 post (e dovrei arrivare ad oltre 10.000) con post_id, categorie, post_content, permalink, post_type, status… etc. Il file csv ha per ogni riga un post univoco (post_id). Il problema sorge quando devo aggiungere dei nuovi post su wp.

    Wordpress assegna un post_id ad ogni foto/pagina nuova inserita e i nuovi post importati da csv (creati da access per ovvi motivi gestionali …e lo uso da troppi anni) vanno in conflitto se il post_id è già presente costringendomi di volta in volta a rimappare i post creati con access.

    Per questo motivo mi sono imbattuto in questa guida in cui si crea una nuova tabella sul db di wordpress (per me questa tabella sarebbe il file csv ottenuto da access) e sto cercando il modo di poter visualizzare questo tabellone con la stessa modalità dei post/categorie di wp ma senza andare a toccare post e categorie esistenti (proprio perchè wp assegna post_id automaticamente).

    Concludendo mi servirebbe qualcosa di simile a quanto visto in questa guida, ma potendo visualizzare sul frontend i dati di tale tabella con i vari link tra post, permalink etc. Spero di essermi spiegato e sopratutto di non essere uscito troppo dall’argomento trattato.

    Grazie a tutti ed ancora complimenti
    Ho sviluppato il tutto e funziona meravigliosamente.

  13. Ciao Umby e grazie mille per i complimenti, spero che il post ti sia stato utile per i tuoi progetti. Per quanto riguarda ID di un post, wordpress usa un autoincrement presente in MySQL. Quello che ti conviene fare è portare questo valore molto alto tipo 500.000 con il comando SQL

    ALTER TABLE wp_posts AUTO_INCREMENT = value;

    In questo modo wordpress inserirà le sue cose dopo questo valore e tu puoi inserire nuovi record proseguendo con la tua sequenza che assegni secondo il criterio del tuo applicativo.

  14. Ho letto per caso questo consiglio su AUTO INCREMENT mi sembra una buona idea anche se mi sembra strano che possa funzionare, perché cosi vuol dire che io posso aggiungere un numero ID che voglio e non rispettare la sequenza che il database dovrebbe gestire da solo?

  15. Ciao Bruno, dato che mi hai creato un dubbio non da poco sono andato a verificare su una tabella di prova copiata da wp_term, ho messo autoincrement alto e inserito alcuni record senza specificare un valore ID e altri forzando un valore, mi sembra che funzioni tutto correttamente.

    ► Screenshot: https://goo.gl/uJlWxH

  16. I miei più vivi complimenti. Sono rimasto a bocca aperta per come è stata illustrata la lezione. Meglio di un qualsiasi libro o post in rete. Grazie per quello mi hai insegnato. Spero anch'io di proseguire a leggere il continuo di questa "lezione" per imparare e capire come portare i dati lato front-end (come chiesto anche da Pietro) e terminare il codice per implementazione edit e delete (come chiesto da Franco).

    Grazie ancora e attendo con ansia.

  17. Ciao Daniele, grazie per i complimenti e dato che le richieste sono diverse se trovo un pò di tempo cerco di scrivere un nuovo tutorial che vi spieghi come implementare le funzioni di "EDIT".

  18. Ciao ho seguito con attenzione tutto il tuo tutorial e devo farti i complimenti. Volevo sviluppare la parte relativa all'azione "Edit" ma mi sono un pò incartato, tu dici che è possibile un aiuto? Ciao e buon lavoro

  19. Ciao Franco, per la parte di "Edit" devi cercare in internet le tecniche di programmazione che trattano i metabox e pagine delle opzioni personalizzate. Ci sono diverse risorse. Fammi sapere.

  20. Ciao e complimenti per questo tutorial davvero interessante. Anche io come l'altro utente Pietro, sono interessato ora alla parte relativa al front-end... cioè come possiamo fare a visualizzare i dati per il semplice visitatore del sito. Grazie ancora!

  21. Ciao il tutorial è molto interessante ma volevo chiederti se questa procedura si può fare nel front-end. Volevo realizzare una WebApp gestionale ma i campi, le table le volevo visualizzare sull'interfaccia Front-end cosi l'utente non deve entrare nel Back-end di Wordpress si puo fare? se si come?

  22. Ciao Pietro, le funzioni indicate sono valide solo per il backend, per quanto riguarda la tua richiesta penso che devi usare un plugin o utilizzare un tema che sia predisposto a questa funzionalità.

condividi