Steamer Lane Studio技術備忘録WordPress

WordPress投稿をクリックドラッグで並び替えその並び順でアーカイブに並べるfunction.php記入コード

wordpress WordPress投稿をクリックドラッグで並び替えその並び順でアーカイブに並べるfunction.php記入コード 最終更新日: 2025年10月1日

表題の必要が生じた案件から、プラグインではなくfunction.php記述するコードを作ってみた。
通常使用しないなが、WPの利用法としてシステム的な利用とした場合はそんな必要も生じるので、マニアックな使い方する場合は使うこともあるかも。

WordPress投稿をクリックドラッグで並び替えその並び順でアーカイブに並べるfunction.php記入コード

で、コード

add_action( 'pre_get_posts', function( $query ) {if ( is_admin() && $query->is_main_query() && $query->get('post_type') === 'post' ) {$query->set( 'orderby', array('menu_order' => 'ASC','date' => 'DESC' // 同順位の場合の補助ソート));}});

// 管理画面:投稿一覧の列を編集(タイトル列の次に「並び順」を追加)add_filter( 'manage_posts_columns', function( $columns ) {$new_columns = array();foreach ( $columns as $key => $value ) {$new_columns[ $key ] = $value;// title の直後に order 列を追加if ( $key === 'title' ) {$new_columns['order'] = '並び順';}}return $new_columns;});

// 「並び順」列にハンドルを表示add_action( 'manage_posts_custom_column', function( $column_name, $post_id ) {if ( $column_name === 'order' ) {echo '<span class="order-handle dashicons dashicons-move"></span>';}}, 10, 2 );

// 並び替え用スクリプトとスタイルを読み込みadd_action( 'admin_enqueue_scripts', function( $hook ) {if ( $hook !== 'edit.php' || ( $_GET['post_type'] ?? 'post' ) !== 'post' ) return;

wp_enqueue_script( 'jquery-ui-sortable' );wp_add_inline_script( 'jquery-ui-sortable', "jQuery(function($){var tbody = $('#the-list');tbody.sortable({handle: '.order-handle',placeholder: 'sortable-placeholder',update: function(){var order = [];tbody.find('tr').each(function(i,el){order.push($(el).attr('id').replace('post-',''));});$.post(ajaxurl,{action: 'save_post_order',order: order,_wpnonce: '".wp_create_nonce('save_post_order')."'});}});});" );

wp_add_inline_style( 'dashicons', ".order-handle{cursor:move;}.sortable-placeholder{background:#f1f1f1;height:50px;border:2px dashed #ccc;}" );});

// 並び順を保存add_action( 'wp_ajax_save_post_order', function() {check_ajax_referer( 'save_post_order' );if ( ! current_user_can( 'edit_posts' ) ) wp_send_json_error();

$order = isset($_POST['order']) ? array_map('intval', $_POST['order']) : [];foreach ( $order as $position => $post_id ) {wp_update_post( array('ID' => $post_id,'menu_order' => $position));}wp_send_json_success();});

(Category)アーカイブテンプレート内のループ部分

<?php$cat_id = get_queried_object_id();

$args = array('post_type' => 'post','category__in' => array( $cat_id ), // cat ではなく category__in'orderby' => 'menu_order','order' => 'DESC','posts_per_page' => -1);

$query = new WP_Query( $args );

こんな感じで指定すれば反映される。

実装したが、自動保存の際にシステムによってはカテゴリーに干渉するので修正。
具体的には、自動保存によりカテゴリーが上書きされる際に、コアのデフォルトカテゴリー割り当て機能に干渉されて勝手にデフォルトかそれに準ずるカテゴリーが強制的に割り当てられた。
カテゴリーを維持したまま自動保存としたが、自動保存の間がやや長いので、UI上変更を行うと保存ボタンが出現しクリックすると保存とした。

add_action( 'pre_get_posts', function( $query ) {if ( is_admin() && $query->is_main_query() && $query->get('post_type') === 'post' ) {$query->set( 'orderby', array('menu_order' => 'ASC','date' => 'DESC' // 同順位の場合の補助ソート));}});

// 管理画面:投稿一覧の列を編集(タイトル列の次に「並び順」を追加)add_filter( 'manage_posts_columns', function( $columns ) {$new_columns = array();foreach ( $columns as $key => $value ) {$new_columns[ $key ] = $value;// title の直後に order 列を追加if ( $key === 'title' ) {$new_columns['order'] = '並び順';}}return $new_columns;});

// 「並び順」列にハンドルを表示add_action( 'manage_posts_custom_column', function( $column_name, $post_id ) {if ( $column_name === 'order' ) {echo '<span class="order-handle dashicons dashicons-move"></span>';}}, 10, 2 );

// 並び替え用スクリプトとスタイルを読み込みadd_action( 'admin_enqueue_scripts', function( $hook ) {if ( $hook !== 'edit.php' || ( $_GET['post_type'] ?? 'post' ) !== 'post' ) return;

wp_enqueue_script( 'jquery-ui-sortable' );wp_add_inline_script( 'jquery-ui-sortable', "jQuery(function($){var tbody = $('#the-list');var saveButton = $('<button type=\"button\" id=\"save-post-order-btn\" class=\"button button-primary\" style=\"display:none; margin-left: 10px;\">並び順を保存</button>');// ボタンを投稿一覧テーブルの上に配置$('.tablenav.top .actions:first').append(saveButton);

tbody.sortable({handle: '.order-handle',placeholder: 'sortable-placeholder',// 変更点: updateイベントから自動保存処理を削除update: function(){// 並び順が変更されたら保存ボタンを表示saveButton.show();}});// 保存ボタンクリック時のAjax処理saveButton.on('click', function(){var order = [];tbody.find('tr').each(function(i,el){order.push($(el).attr('id').replace('post-',''));});

var btn = $(this);btn.text('保存中...').prop('disabled', true); // ボタンを無効化$.post(ajaxurl,{action: 'save_post_order',order: order,_wpnonce: '".wp_create_nonce('save_post_order')."'}).done(function(){// 成功時の処理btn.text('並び順を保存しました').prop('disabled', true).css('background-color', '#4CAF50');// 3秒後にボタンを元に戻し、非表示にするsetTimeout(function(){btn.text('並び順を保存').prop('disabled', false).hide().removeAttr('style');// 画面を再読み込みして表示順を確定させるwindow.location.reload();}, 3000);}).fail(function(){// 失敗時の処理btn.text('保存失敗').prop('disabled', false).css('background-color', '#F44336');});});});" );

wp_add_inline_style( 'dashicons', ".order-handle{cursor:move;}.sortable-placeholder{background:#f1f1f1;height:50px;border:2px dashed #ccc;}" );});

// Ajax処理 (カテゴリー保持の最終修正版を使用)add_action( 'wp_ajax_save_post_order', function() {check_ajax_referer( 'save_post_order' );if ( ! current_user_can( 'edit_posts' ) ) wp_send_json_error();

$order = isset($_POST['order']) ? array_map('intval', $_POST['order']) : [];foreach ( $order as $position => $post_id ) {// 既存のカテゴリーを明示的に取得し、保持する$existing_categories = wp_get_post_terms($post_id,'category',array( 'fields' => 'ids' ));

$update_args = array('ID' => $post_id,'menu_order' => $position,// 既存のカテゴリーIDを明示的に渡すことで、上書きを防ぐ'post_category' => $existing_categories,);

wp_update_post( $update_args );}wp_send_json_success();});

再調整版
ロール追加など面倒なテーマで実装したもの

/* 投稿=ヒートを一覧観ながらクリックドラッグで並び順変えるためのコード*/add_action( 'pre_get_posts', function( $query ) {if ( is_admin() && $query->is_main_query() && $query->get('post_type') === 'post' ) {$query->set( 'orderby', array('menu_order' => 'ASC','date' => 'DESC' // 同順位の場合の補助ソート));}});

// 管理画面:投稿一覧の列を編集(タイトル列の次に「並び順」を追加)add_filter( 'manage_posts_columns', function( $columns ) {$new_columns = array();foreach ( $columns as $key => $value ) {$new_columns[ $key ] = $value;// title の直後に order 列を追加if ( $key === 'title' ) {$new_columns['order'] = '並び順';}}return $new_columns;});

// 「並び順」列にハンドルを表示add_action( 'manage_posts_custom_column', function( $column_name, $post_id ) {if ( $column_name === 'order' ) {echo '<span class="order-handle dashicons dashicons-move"></span>';}}, 10, 2 );

// 並び替え用スクリプトとスタイルを読み込みadd_action( 'admin_enqueue_scripts', function( $hook ) {if ( $hook !== 'edit.php' || ( $_GET['post_type'] ?? 'post' ) !== 'post' ) return;

wp_enqueue_script( 'jquery-ui-sortable' );wp_add_inline_script( 'jquery-ui-sortable', "jQuery(function($){var tbody = $('#the-list');var saveButton = $('<button type=\"button\" id=\"save-post-order-btn\" class=\"button button-primary\" style=\"display:none; margin-left: 10px;\">並び順を保存</button>');// ボタンを投稿一覧テーブルの上に配置$('.tablenav.top .actions:first').append(saveButton);

tbody.sortable({handle: '.order-handle',placeholder: 'sortable-placeholder',// 変更点: updateイベントから自動保存処理を削除update: function(){// 並び順が変更されたら保存ボタンを表示saveButton.show();}});// 保存ボタンクリック時のAjax処理saveButton.on('click', function(){var order = [];tbody.find('tr').each(function(i,el){order.push($(el).attr('id').replace('post-',''));});

var btn = $(this);btn.text('保存中...').prop('disabled', true); // ボタンを無効化$.post(ajaxurl,{action: 'save_post_order',order: order,_wpnonce: '".wp_create_nonce('save_post_order')."'}).done(function(){// 成功時の処理btn.text('並び順を保存しました').prop('disabled', true).css('background-color', '#4CAF50');// 3秒後にボタンを元に戻し、非表示にするsetTimeout(function(){btn.text('並び順を保存').prop('disabled', false).hide().removeAttr('style');// 画面を再読み込みして表示順を確定させるwindow.location.reload();}, 3000);}).fail(function(){// 失敗時の処理btn.text('保存失敗').prop('disabled', false).css('background-color', '#F44336');});});});" );

wp_add_inline_style( 'dashicons', ".order-handle{cursor:move;}.sortable-placeholder{background:#f1f1f1;height:50px;border:2px dashed #ccc;}" );});

// Ajax処理 (カテゴリー保持の最終修正版を使用)add_action( 'wp_ajax_save_post_order', function() {check_ajax_referer( 'save_post_order' );if ( ! current_user_can( 'edit_posts' ) ) wp_send_json_error();

$order = isset($_POST['order']) ? array_map('intval', $_POST['order']) : [];foreach ( $order as $position => $post_id ) {// 既存のカテゴリーを明示的に取得し、保持する$existing_categories = wp_get_post_terms($post_id,'category',array( 'fields' => 'ids' ));

$update_args = array('ID' => $post_id,'menu_order' => $position,// 既存のカテゴリーIDを明示的に渡すことで、上書きを防ぐ'post_category' => $existing_categories,);

wp_update_post( $update_args );}wp_send_json_success();});