web-dev-qa-db-fra.com

WP_list_table bulk_action get edit et delete

Apparemment, je ne reçois apparemment pas de documentation à ce sujet. Même les autres échanges de piles à ce sujet ne m'éclairent pas vraiment. Je pense que c'est parce que je ne comprends tout simplement pas comment cela fonctionne.

Donc, je crée une page d'administrateur et je lis la table de base de données que j'ai créée. Je ne comprends tout simplement pas comment je peux effectuer des suppressions simples (et des modifications) et des suppressions en bloc (et des modifications) pour fonctionner dans le cadre Wordpress.

Alors voici le code:

class Designit_Countries_Table extends Designit_List_Table
{

    private $order;
    private $orderby;
    private $posts_per_page = 25;

    public function __construct()
    {
        global $status, $page;

        parent :: __construct(array(
            'singular' => "country",
            'plural' => "countries",
            'ajax' => true
        ));

        $this->set_order();
        $this->set_orderby();
    }

    private function get_sql_results()
    {
        global $wpdb;
        $args = array('id', 'name', 'title', 'country', 'image', 'time');
        $sql_select = implode(', ', $args);
        $sql_results = $wpdb->get_results("SELECT " . $sql_select . " FROM " . $wpdb->prefix . "designitcountries ORDER BY $this->orderby $this->order ");
        return $sql_results;
    }

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

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

    public function ajax_user_can()
    {
        return current_user_can('edit_posts');
    }

    public function no_items()
    {
        _e('No countries found.');
    }

    public function get_views()
    {
        return array();
    }

    public function get_columns()
    {
        $columns = array(
            'cb' => '<input type="checkbox" />',
            'name' => __('Name'),
            'title' => __('Title'),
            'country' => __('Country'),
            'image' => __('Image'),
            'time' => __('Created on'),
            'id' => __('id')
        );
        return $columns;
    }

    function get_bulk_actions() {
        $actions = array(
            'delete'    => 'Delete'
        );
        return $actions;
    }
    public function get_sortable_columns()
    {
        $sortable = array(
            'id' => array('id', true),
            'title' => array('Title', true),
            'name' => array('Name', true),
            'country' => array('Country', true),
            'image' => array('Image', true),
            'time' => array('Created on', true),
        );
        return $sortable;
    }

    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_name = __('No name set');
            $name = !$post->name ? "<em>{$no_name}</em>" : $post->name;
            $posts[$key]->name = "{$name}";
        }
        $this->items = $posts_array;

        $this->process_bulk_action();

    }

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


    /**
     * 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();
    }

    //edit buttons

    function column_name(){
        global $wpdb;
        $args = array('id', 'name');
        $sql_select = implode(', ', $args);
        $sql_results = $wpdb->get_results("SELECT " . $sql_select . " FROM " . $wpdb->prefix . "designitcountries ORDER BY $this->orderby $this->order ");

        foreach ($sql_results as $sql_result) {
            $name = $sql_result->name;
            $id = $sql_result->id;
            $actions = array(
                'edit' => sprintf('<a href="?page=%s&action=%s&name=%s">Edit</a>', $_REQUEST['page'], 'edit', $id),
                'delete' => sprintf('<a href="?page=%s&action=%s&name=%s">Delete</a>', $_REQUEST['page'], 'delete', $id),
            );
            return sprintf('%1$s %2$s', $name, $this->row_actions($actions));
        }
    }

    function column_cb($item) {
            return sprintf(
                '<input type="checkbox" name="book[]" value="%s" />',
                $this->_args['singular'],
                $item->id
            );
        }

    public function process_bulk_action() {

        // security check!
        if ( isset( $_POST['_wpnonce'] ) && ! empty( $_POST['_wpnonce'] ) ) {

            $nonce  = filter_input( INPUT_POST, '_wpnonce', FILTER_SANITIZE_STRING );
            $action = 'bulk-' . $this->_args['plural'];

            if ( ! wp_verify_nonce( $nonce, $action ) )
                wp_die( 'Nope! Security check failed!' );

        }

        $action = $this->current_action();

        switch ( $action ) {

            case 'delete':
                foreach($_GET['country'] as $country) {



                }

                wp_die( 'You have deleted this succesfully' );
                break;

            case 'edit':
                wp_die( 'This is the edit page.' );
                break;

            default:
                // do nothing or something else
                return;
                break;
        }

        return;
    }

}

Il y a beaucoup de code à parcourir, alors laissez-moi couper en morceaux pour mon problème.

Les résultats montrent ceci:  Countries admin page 

_ {Ceci affiche la page du pays que j'ai créée avec les actions que j'ai en place et les cases à cocher} _

Donc, j'implémente les cases à cocher comme ceci:

public function get_columns()
{
    $columns = array(
        'cb' => '<input type="checkbox" />',
        'name' => __('Name'),
        'title' => __('Title'),
        'country' => __('Country'),
        'image' => __('Image'),
        'time' => __('Created on'),
        'id' => __('id')
    );
    return $columns;
}
    function column_cb($item) {
        return sprintf(
            '<input type="checkbox" name="book[]" value="%s" />',
            $this->_args['singular'],
            $item->id
        );
    }

Ensuite, j'ai aussi les boutons simples d'édition et de suppression:

function column_name(){
    global $wpdb;
    $args = array('id', 'name');
    $sql_select = implode(', ', $args);
    $sql_results = $wpdb->get_results("SELECT " . $sql_select . " FROM " . $wpdb->prefix . "designitcountries ORDER BY $this->orderby $this->order ");

    foreach ($sql_results as $sql_result) {
        $name = $sql_result->name;
        $id = $sql_result->id;
        $actions = array(
            'edit' => sprintf('<a href="?page=%s&action=%s&name=%s">Edit</a>', $_REQUEST['page'], 'edit', $id),
            'delete' => sprintf('<a href="?page=%s&action=%s&name=%s">Delete</a>', $_REQUEST['page'], 'delete', $id),
        );
        return sprintf('%1$s %2$s', $name, $this->row_actions($actions));
    }
}

et l'action en bloc et le traitement de cela:

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

public function process_bulk_action() {

        // security check!
        if ( isset( $_POST['_wpnonce'] ) && ! empty( $_POST['_wpnonce'] ) ) {

            $nonce  = filter_input( INPUT_POST, '_wpnonce', FILTER_SANITIZE_STRING );
            $action = 'bulk-' . $this->_args['plural'];

            if ( ! wp_verify_nonce( $nonce, $action ) )
                wp_die( 'Nope! Security check failed!' );

        }

        $action = $this->current_action();

        switch ( $action ) {

            case 'delete':
                foreach($_GET['country'] as $country) {



                }

                wp_die( 'You have deleted this succesfully' );
                break;

            case 'edit':
                wp_die( 'This is the edit page.' );
                break;

            default:
                // do nothing or something else
                return;
                break;
        }

        return;
    }

Maintenant où je ne l'obtiens pas

Je comprends que je dois effectuer la suppression dans le cas "supprimer" et la modification dans le cas "modifier". Mais je ne comprends pas comment je peux sélectionner la ligne sélectionnée avec les cases à cocher pour qu'elle soit réellement supprimée. Ou si vous utilisez le bouton "Supprimer" et non l'action en bloc, seule cette ligne est supprimée et le fonctionnement général de la fonction d'édition.

Je n'arrive pas à trouver les exemples appropriés, alors j'espère que l'un de vous pourra m'aider!

La page que je vois quand j'appuie sur 'supprimer':  enter image description here 

Mise à jour

Donc, je l'ai fait fonctionner en donnant à tout son propre identifiant (ce qui est logique)

function column_cb($item) {
    return sprintf(
        '<input type="checkbox" name="country[]" value="%s" />',
        $item->id
    );
}
function column_name($item){
    $item_json = json_decode(json_encode($item), true);
    $actions = array(
        'edit' => sprintf('<a href="?page=%s&action=%s&id=%s">Edit</a>', $_REQUEST['page'], 'edit', $item_json['id']),
        'delete' => sprintf('<a href="?page=%s&action=%s&id=%s">Delete</a>', $_REQUEST['page'], 'delete', $item_json['id']),
    );
    return '<em>' . sprintf('%s %s', $item_json['name'], $this->row_actions($actions)) . '</em>';
}

Et ensuite, utilisez cette référence pour supprimer les tables avec une requête SQL:

 case 'delete':
                global $wpdb;
                $table_name = $wpdb->prefix . 'designitcountries';
                $ids = isset($_REQUEST['id']) ? $_REQUEST['id'] : array();
                var_dump($ids);
                    if (is_array($ids)) $ids = implode(',', $ids);
                    if (!empty($ids)) {
                        $wpdb->query("DELETE FROM $table_name WHERE id IN($ids)");
                }

                wp_die( 'You have deleted this succesfully' );
                break;

MAIS

Cela fonctionne lorsque j’utilise le bouton de suppression mais cela ne fonctionne pas lorsque je supprime une action en bloc (même si je sélectionne 1)

Je donne l'identifiant dans l'URL du Href du bouton 'delete'. Aucune idée de comment je suis censé faire cela avec les cases à cocher pour agir de la même manière

3
CompactCode

Donc, j'ai trouvé le problème.

Tout d'abord, je ne sélectionnais pas les bonnes ID sur ma case à cocher ou mes boutons, j'ai donc changé en code pour le faire:

function column_name($item){
    $item_json = json_decode(json_encode($item), true);
    $actions = array(
        'edit' => sprintf('<a href="?page=%s&action=%s&id=%s">Edit</a>', $_REQUEST['page'], 'edit', $item_json['id']),
        'delete' => sprintf('<a href="?page=%s&action=%s&id=%s">Delete</a>', $_REQUEST['page'], 'delete', $item_json['id']),
    );
    return '<em>' . sprintf('%s %s', $item_json['name'], $this->row_actions($actions)) . '</em>';
}

Notez ici que j'ai maintenant $items qui obtiendra toutes les données nécessaires. Je vais faire un décodage et un encodage JSON pour le transformer en tableau et ensuite je peux appeler le tableau JSON id ou name dans la sprinttf() où j'en ai besoin.

Idem pour les cases à cocher (sans le JSON):

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

Après cela, j'ai ajouté ceci à mon cas 'delete':

case 'delete':
                global $wpdb;
                $table_name = $wpdb->prefix . 'designitcountries';

                if ('delete' === $this->current_action()) {
                    $ids = isset($_REQUEST['id']) ? $_REQUEST['id'] : array();
                    if (is_array($ids)) $ids = implode(',', $ids);

                    if (!empty($ids)) {
                        $wpdb->query("DELETE FROM $table_name WHERE id IN($ids)");
                    }
                }

                wp_die( 'You have deleted this succesfully' );
                break;

Maintenant, j'ai une méthode de travail pour supprimer des boutons et des cases à cocher.

2
CompactCode