Message d'origine: Interrogation entre les dates à l'aide des champs du sélecteur de date
J'avais initialement publié un article l'année dernière sur le même sujet, mais il semble que la mise à jour de WP v4.2.1 ait cassé mon filtre. En résumé, j'utilise ACF et le plug-in du sélecteur de date dans un type de publication personnalisé Events. J'essaie d'interroger des événements entre une date de début et une date de fin. J'ai aussi des événements qui peuvent s'étendre sur plusieurs mois. Par exemple, un événement peut commencer en avril mais se terminer en juin. Je veux que cet événement soit affiché en avril, mai et juin.
J'ai eu ce travail en utilisant un filtre lorsque sur v3.9 de wordpress. J'essaie de mettre WordPress à jour sur tous mes sites Web, mais ce filtre se casse après la mise à jour vers la v4.2.1. Cela s'est cassé après la mise à jour de WP 4.2.1 et également après la mise à jour de ACF vers la dernière version de 4. J'ai depuis mis à jour vers ACF PRO v5.2.3
Est-ce que quelqu'un sait d'un correctif?
Voici le code qui a bien fonctionné sous WP v3.9.
Mon modèle de gabarit d'événement:
<?php
/* Template Name: Events Widget */
$today = date('Ymd');
if (isset($_GET['_m'])) {
$current_month = str_pad($_GET['_m'], 2, '0', STR_PAD_LEFT);
$current_day = "01"; // day one
$current_year = $_GET['_y'];
$get_last_day = $current_year.$current_month.$current_day;
$lastday = date("t", strtotime($get_last_day));
$tempstartday = $current_year.$current_month.$current_day;
$tempendday = $current_year.$current_month.$lastday;
$startday = date('Ymd', strtotime($tempstartday));
$endday = date('Ymd', strtotime($tempendday));
} else {
$current_month = str_pad(date('m'), 2, '0', STR_PAD_LEFT);
$current_day = "01"; // day one
$current_year = date('Y');
$get_last_day = $current_year.$current_month.$current_day;
$lastday = date("t", strtotime($get_last_day));
$tempstartday = $current_year.$current_month.$current_day;
$tempendday = $current_year.$current_month.$lastday;
$startday = date('Ymd', strtotime($tempstartday));
$endday = date('Ymd', strtotime($tempendday));
}
add_filter( 'get_meta_sql', 'get_meta_sql_date', 10, 2 );
$qryevents = array(
'post_type' => 'events',
'posts_per_page' => 50,
'status' => 'published',
'meta_key' => 'event_start_date',
'orderby' => 'meta_value',
'order' => 'ASC',
// produces meta join and where clauses for the query
// which will be filtered in functions.php
'meta_query' => array(
'relation' => 'AND',
array(
'key' => 'event_start_date',
'compare' => '>=',
'value' => $startday,
'type' => 'DATE'
),
array(
'key' => 'event_end_date',
'compare' => '<=',
'value' => $endday,
'type' => 'DATE'
)
)
);
$loop = new WP_Query( $qryevents );
remove_filter( 'get_meta_sql', 'get_meta_sql_date', 10, 2 );
if ( $loop->have_posts() ) :
while ( $loop->have_posts() ) : $loop->the_post();
// Let's format the dates
$get_start_date = get_field('event_start_date');
$get_end_date = get_field('event_end_date');
$event_start_date = DateTime::createFromFormat('Ymd', $get_start_date);
$event_end_date = DateTime::createFromFormat('Ymd', $get_end_date);
// End of date definitions
// Let's get the event start and end times
$get_start_time = get_field('event_start_time');
$get_end_time = get_field('event_end_time');
// end of times
// Let's get the times of the events now
$specify_event_time = "";
$show_event_times = get_field('specify_event_times');
if($show_event_times){
foreach($show_event_times as $specify_event_time){
// Do nothing; this puts the yes value into the varible for us to later on the page.
// echo $specify_event_time;
}
}
// End of the specify times
$event_month_spans = get_field('event_month_span');
?>
<div class="<?php echo (++$j % 2 == 0) ? 'full row' : 'full row alt'; ?>">
<p><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></p>
<?php if($specify_event_time == "yes"): ?>
<p class="event-date"><a href="<?php the_permalink(); ?>"><?php echo $event_start_date->format('M d, Y'); ?> <?php echo $get_start_time; ?> - <?php echo $event_end_date->format('M d, Y'); ?> <?php echo $get_end_time; ?></a></p>
<?php else: ?>
<p class="event-date"><a href="<?php the_permalink(); ?>"><?php echo $event_start_date->format('M d, Y'); ?> - <?php echo $event_end_date->format('M d, Y'); ?></a></p>
<?php endif; ?>
</div>
<?php
endwhile;
else:
?>
<p>No scheduled events.</p>
<?php endif; wp_reset_query(); ?>
Dans mon fichier functions.php, j'ai cette fonction:
function get_meta_sql_date( $pieces, $queries ) {
global $wpdb;
// get start and end date from query
foreach ( $queries as $q ) {
if ( !isset( $q['key'] ) ) {
return $pieces;
}
if ( 'event_start_date' === $q['key'] ) {
$start_date = isset( $q['value'] ) ? $q['value'] : '';
}
if ( 'event_end_date' === $q['key'] ) {
$end_date = isset( $q['value'] ) ? $q['value'] : '';
}
}
if ( ( '' === $start_date ) || ( '' === $end_date ) ) {
return $pieces;
}
$query = "";
// after start date AND before end date
$_query = " AND (
( $wpdb->postmeta.meta_key = 'event_start_date' AND ( CAST($wpdb->postmeta.meta_value AS DATE) >= %s) )
AND ( mt1.meta_key = 'event_end_date' AND ( CAST(mt1.meta_value AS DATE) <= %s) )
)";
$query .= $wpdb->prepare( $_query, $start_date, $end_date );
// OR before start date AND after end date
$_query = " OR (
( $wpdb->postmeta.meta_key = 'event_start_date' AND ( CAST($wpdb->postmeta.meta_value AS DATE) <= %s) )
AND ( mt1.meta_key = 'event_end_date' AND ( CAST(mt1.meta_value AS DATE) >= %s) )
)";
$query .= $wpdb->prepare( $_query, $start_date, $end_date );
// OR before start date AND (before end date AND end date after start date)
$_query = " OR (
( $wpdb->postmeta.meta_key = 'event_start_date' AND ( CAST($wpdb->postmeta.meta_value AS DATE) <= %s) )
AND ( mt1.meta_key = 'event_end_date'
AND ( CAST(mt1.meta_value AS DATE) <= %s )
AND ( CAST(mt1.meta_value AS DATE) >= %s )
)
)";
$query .= $wpdb->prepare( $_query, $start_date, $end_date, $start_date );
// OR after end date AND (after start date AND start date before end date) )
$_query = "OR (
( mt1.meta_key = 'event_end_date' AND ( CAST(mt1.meta_value AS DATE) >= %s ) )
AND ( $wpdb->postmeta.meta_key = 'event_start_date'
AND ( CAST($wpdb->postmeta.meta_value AS DATE) >= %s )
AND ( CAST($wpdb->postmeta.meta_value AS DATE) <= %s )
)
)";
$query .= $wpdb->prepare( $_query, $end_date, $start_date, $end_date );
$pieces['where'] = $query;
return $pieces;
}
Le filtre méta SQL personnalisé n’est pas nécessaire - l’intérêt de stocker des dates au format Ymd
réside dans le fait que vous pouvez les traiter numériquement et que MySQL pourra toujours trouver des événements dans une "plage" donnée et les trier par ordre croissant/décroissant.
Je l'ai fait récemment sur un autre site en utilisant ACF comme date de début/fin:
if ( ! empty( $_GET['_y'] ) )
$year = absint( $_GET['_y'] );
else
$year = date( 'Y ');
if ( ! empty( $_GET['_m'] ) && in_array( $month = absint( $_GET['_m'] ), range( 1, 12 ) ) )
$month = zeroise( $month, 2 );
else
$month = date( 'm' );
$qryevents = array(
'post_type' => 'events',
'posts_per_page' => 50,
'post_status' => 'publish',
'orderby' => 'meta_value_num', // Ensure order is numerically based
'order' => 'ASC',
'meta_query' => array(
'relation' => 'AND',
array(
'key' => 'event_start_date',
'compare' => '>=',
'value' => "{$year}{$month}01",
'type' => 'NUMERIC',
),
array(
'key' => 'event_end_date',
'compare' => '<=',
'value' => "{$year}{$month}31", // Doesn't matter if there aren't 31 days in this month, will still work,
'type' => 'NUMERIC',
)
)
);
Pas besoin de calculs de chaîne de date trop complexes, ni de filtre.
Les utilitaires Date et heure utilisent un détachement des modèles de date et heure. L’utilitaire date ()
revisite la date dans ce modèle: ‘AAAA-MM-JJ’.