Сортировка запроса по дате настраиваемого поля
ИЗМЕНИТЬ: Переформулировал вопрос для большей ясности
Я пытаюсь отсортировать по пользовательским данным метаданных, которые я преобразую в дату с помощью функции strtotime
, но у меня возникли некоторые трудности.
Моей главной проблемой, похоже, является уловка-22 с функцией strtotime
. Если я использую strtotime
внутри цикла (см. Ниже) Я не могу использовать время UNIX для сортировки по дате. Однако, если я обработаю strtotime при сохранении (в functions.php), я сталкиваюсь с кучей проблем с мета-поле обновляется/не анализируется, если пользователь редактирует сообщение или повторно сохраняет.
Есть ли простое решение этой проблемы? Вот код... Я просто хочу упорядочить эти сообщения в порядке возрастания по настраиваемому полю даты (а не по дате публикации).
РЕДАКТИРОВАТЬ: Исправлен массив путем добавления мета-ключа - решение все еще находится на рассмотрении
<!-- The args -->
<?php
$args = array(
"post_type" => "podcasts",
"meta-key" => "_date",
"orderby" => "meta_value",
"order" => "ASC"
);
?>
<!-- The Query -->
<?php $podcasts = new WP_Query( $args ); ?>
<!-- The Loop -->
<?php if ( $podcasts->have_posts() ) : while ( $podcasts->have_posts() ) : $podcasts->the_post(); ?>
<!-- Convert Date to Date Stamp -->
<?php $podcast_date = get_post_meta($post->ID, '_date', true);?>
<?php $fixed_date = strtotime($podcast_date); ?>
<!-- Content -->
РЕДАКТИРОВАТЬ: Добавлен соответствующий код мета-поля (ниже) из functions.php Примечание - Этот код нигде не включает функцию strtotime потому что в настоящее время я использую его в шаблоне страницы. Я мог бы включить его здесь, но я не уверен, что нужно сделать, чтобы позволить пользователю редактировать сообщения/повторно сохранять. Как только функция strtotime запустится при сохранении, не изменит ли она дату мета-бокса на что-то вроде 1327248252? Если это так, это не будет проанализировано при следующем сохранении записи, что создаст проблемы.
// Create podcast Meta boxes
function add_podcast_metaboxes() {
add_meta_box('podcast_info', 'podcast Information', 'podcast_info', 'podcasts', 'normal', 'high');
}
// podcast Meta Box
function podcast_info() {
global $post;
// Noncename needed to verify where the data originated
echo '<input id="podcastmeta_noncename" name="podcastmeta_noncename" type="hidden" value="' . wp_create_nonce( plugin_basename(__FILE__) ) . '" />';
// Get the data if its already been entered
$week = get_post_meta($post->ID, '_week', true);
$date = get_post_meta($post->ID, '_date', true);
$description = get_post_meta($post->ID, '_description', true);
// Echo out the field
echo '<strong>Week</strong><br /><em>What week of the series is this podcast?</em>';
echo '<input class="widefat" name="_week" type="text" value="' . $week . '" />';
echo '<strong>Date</strong><br /><em>Enter the Date the podcast was recorded</em>';
echo '<input class="widefat" name="_date" type="text" value="' . $date . '" />';
echo '<strong>Description</strong><br /><em>Enter the text you would like to display as a description on the media archives list.</em>';
echo '<input class="widefat" name="_description" type="text" value="' . $description . '" />';
}
// Save the podcast Meta box Data
function save_podcast_meta($post_id, $post) {
// verify this came from the our screen and with proper authorization,
// because save_post can be triggered at other times
if ( !wp_verify_nonce( $_POST['podcastmeta_noncename'], plugin_basename(__FILE__) )) {
return $post->ID;
}
// Is the user allowed to edit the post or page?
if ( !current_user_can( 'edit_post', $post->ID ))
return $post->ID;
// OK, we're authenticated: we need to find and save the data
// We'll put it into an array to make it easier to loop though.
$podcast_meta['_week'] = $_POST['_week'];
$podcast_meta['_date'] = $_POST['_date'];
$podcast_meta['_thumbnail'] = $_POST['_thumbnail'];
$podcast_meta['_seriesimg'] = $_POST['_seriesimg'];
$podcast_meta['_description'] = $_POST['_description'];
// Add values of $podcast_meta as custom fields
foreach ($podcast_meta as $key => $value) { // Cycle through the $podcast_meta array!
if( $post->post_type == 'revision' ) return; // Don't store custom data twice
$value = implode(',', (array)$value); // If $value is an array, make it a CSV (unlikely)
if(get_post_meta($post->ID, $key, FALSE)) { // If the custom field already has a value
update_post_meta($post->ID, $key, $value);
} else { // If the custom field doesn't have a value
add_post_meta($post->ID, $key, $value);
}
if(!$value) delete_post_meta($post->ID, $key); // Delete if blank
}
}
add_action('save_post', 'save_podcast_meta', 1, 2); // save the custom fields
4 answers
РЕДАКТИРОВАТЬ: Ваша проблема заключается в следующем:
Когда вы сохраняете свои метаданные, вы хотите, чтобы дата была сохранена как дата strtotime()
, но вы хотите, чтобы она отображала дату в старом формате Y-m-d
. Что вам нужно сделать, это сохранить его как strtotime()
, а затем при отображении текста обратно во вводе вам нужно изменить этот strtotime()
, чтобы он мог отображаться правильно. Вы можете сделать это так:
В вашей функции add_podcasts_metaboxes()
измените строку, в которой указана дата, на эту (предполагая, что дата всегда будет меткой времени UNIX, если есть один набор):
$date = get_post_meta( $post->ID, '_date', true );
if( $date != '' )
$date = date( 'Y-m-d', $date );
И при сохранении меты в save_podcast_meta()
, делайте это так, как вы хотите с strtotime()
:
$podcast_meta['_date'] = strtotime( $_POST['_date'] );
Это превратило бы дату в метку времени UNIX в базе данных, но с помощью функции date()
вы можете превратить эту метку времени UNIX обратно в дату, которую вы можете использовать.
Вам нужно указать мета-ключ, а затем заказать meta_value
примерно так:
<!-- The args -->
<?php
$args = array(
"post_type" => "podcasts",
"meta_key" => "some_meta_key", // Change to the meta key you want to sort by
"orderby" => "meta_value_num", // This stays as 'meta_value' or 'meta_value_num' (str sorting or numeric sorting)
"order" => "ASC"
);
?>
<!-- The Query -->
<?php $podcasts = new WP_Query( $args ); ?>
<!-- The Loop -->
<?php if ( $podcasts->have_posts() ) : while ( $podcasts->have_posts() ) : $podcasts->the_post(); ?>
<!-- Convert Date to Date Stamp -->
<?php $podcast_date = get_post_meta($post->ID, '_date', true);?>
<?php $fixed_date = strtotime($podcast_date); ?>
<!-- Content -->
Смотрите эту страницу кодекса для справки: http://codex.wordpress.org/Class_Reference/WP_Query#Order_.26_Orderby_Parameters
РЕДАКТИРОВАТЬ: Я вижу одну (возможную) проблему с вашим кодом мета-блока, который вы только что добавили. Хотя я не уверен на 100%!
Попробуйте заменить:
echo '<input id="podcastmeta_noncename" name="podcastmeta_noncename" type="hidden" value="' . wp_create_nonce( plugin_basename(__FILE__) ) . '" />';
С помощью:
wp_nonce_field( plugin_basename( __FILE__ ), 'podcastmeta_noncename' );
Я не уверен, решит ли это вашу проблему или сильно изменит ситуацию, но именно так я использую nonce в своих мета-блоках (хотя я считаю, что есть другой способ сделать это там, где это избавится от этого Notice
, если у вас WP_DEBUG
установлено значение true).
Приведенные выше ответы великолепны. Еще одна полезная тактика, которую следует иметь в виду, заключается в том, что если у вас уже есть массив данных, вы можете сортировать данные на стороне сервера (по сравнению с базой данных) с помощью PHP usort
, uasort
и uksort
.
Для этого вы передаете массив в качестве первого аргумента, а в качестве второго даете методу имя функции, которая позже используется в качестве обратного вызова. Вам просто нужно, чтобы эта функция возвращала 1, 0 или -1 для сортировки по любому пользовательскому рецепту.
Вы столкнулись с аналогичной проблемой, с которой столкнулся я, и я пытался проработать /манипулировать предлагаемыми вами решениями без каких-либо результатов.
В итоге я использовал http://tablesorter.com/docs и запрашиваю данные моего мета-блока непосредственно в столбцах таблицы. Это сработало отлично, а также автоматически сортирует даты соответствующим образом.
Надеюсь, это поможет...
Я понимаю, что должен поместить это в свой первоначальный пост, но он становится очень переполненным, и это подходит для ответа.
Я ищу что-то вроде этого:
Http://www.designhammer.com/blog/sorting-events-date-using-wordpress-custom-post-types
Однако я не совсем на том уровне php, где я могу взять то, что он делает, и применить это к моей ситуации. Похоже, он добавляет некоторую логику в functions.php где функция strtotime будет только стреляйте, если время в хорошем формате. Это решило бы мою проблему и позволило бы мне сортировать на переднем конце.
Мысли?