Obtener lista de años en los que se han publicado posts
Quiero crear una lista de posts de un Custom Post Type y añadir algunos filtros en los que el usuario pueda hacer clic para filtrar la lista.
Añadí filtros para todas las categorías usando la función get_terms(). Ahora quiero añadir filtros por año, así que necesito una forma de recuperar una lista de todos los años en los que se ha publicado al menos un post...
Necesito algo como:
$years = get_all_years_with_posts();
// devuelve array( 2011, 2013, 2014 )
Sé que puedo obtener todos los posts, comprobar su año y construir la lista manualmente, pero ¿no hay algún otro enfoque?
Tu pregunta es bastante antigua, pero quería agregar una solución real a tu consulta. Aquí hay una función que devolverá un array de años en los que has publicado posts. Puedes colocar esta función en functions.php o en un plugin o donde prefieras.
function get_posts_years_array() {
global $wpdb;
$result = array();
$years = $wpdb->get_results(
$wpdb->prepare(
"SELECT YEAR(post_date) FROM {$wpdb->posts} WHERE post_status = 'publish' GROUP BY YEAR(post_date) DESC"
),
ARRAY_N
);
if ( is_array( $years ) && count( $years ) > 0 ) {
foreach ( $years as $year ) {
$result[] = $year[0];
}
}
return $result;
}
Necesitarás modificarla ligeramente para tipos de posts personalizados... solo agrega AND wp_posts.post_type = 'mi_cpt'
en alguna parte de la consulta.

Necesité ajustarlo ligeramente. Creo que prepare() requiere que proporciones al menos un argumento de formato %s (ver https://wordpress.stackexchange.com/a/270970/11914. Pero funcionó y lo voté positivamente.

@idleberg Porque en el momento en que publiqué mi respuesta, la otra persona que respondió malinterpretó la pregunta. Dieron un ejemplo de cómo obtener todas las publicaciones ordenadas por año, pero el OP quería obtener una lista de años que tuvieran publicaciones.

Esto funciona, sin embargo, recupera todas las publicaciones sin tener en cuenta el tipo — asegúrate de aplicar el filtro de tipo de publicación apropiado (WHERE post_type = 'posts') de lo contrario también devolverá publicaciones de páginas.

Recibo un aviso 'El argumento query de wpdb::prepare() debe tener un marcador de posición' con este código cuando el modo de depuración está activado. Por favor edita esta respuesta para incluir marcadores de posición.

Puedes usar esta función para obtener todos los años de los posts en un array, el cual podrías usar para iterar.
$terms_year = array(
'post_type' => array('TU_CPT'),
);
$years = array();
$query_year = new WP_Query( $terms_year );
if ( $query_year->have_posts() ) :
while ( $query_year->have_posts() ) : $query_year->the_post();
$year = get_the_date('Y');
if(!in_array($year, $years)){
$years[] = $year;
}
endwhile;
wp_reset_postdata();
endif;
// Muestra los años donde quieras
echo '<pre>';
print_r($years);
echo '</pre>';

Podrías usar una función de WP y un shortcode de esta manera:
add_shortcode( 'archives', '_get_archived_posts' );
function _get_archived_posts( $atts ) {
$a = shortcode_atts( array(
'type' => 'yearly',
'limit' => '',
'format' => '',
'before' => '',
'after' => '',
'show_post_count' => false,
'echo' => 0,
'order' => 'DESC'
), $atts, 'filter_archives_sc' );
return wp_get_archives($a);
}

// Obtener todos los años de publicación de posts;
function get_posts_years_array($post_type = 'post') {
global $wpdb;
$result = array();
// Preparar consulta SQL para obtener años de posts publicados
$query_prepare = $wpdb->prepare("SELECT YEAR(post_date) FROM ($wpdb->posts) WHERE post_status = 'publish' AND post_type = %s GROUP BY YEAR(post_date) DESC", $post_type);
// Ejecutar consulta
$years = $wpdb->get_results($query_prepare);
// Procesar resultados
if ( is_array( $years ) && count( $years ) > 0 ) {
foreach ( $years as $year ) {
$result[] = json_decode(json_encode($year), true);
}
}
return $result;
}

Tomé la solución de @Gavin y la mejoré para agregar soporte para cualquier tipo de publicación y cualquier estado de publicación:
/**
* Obtiene un array de años disponibles para cualquier tipo de publicación con cualquier estado de publicación
* @see https://wordpress.stackexchange.com/a/273627/18713
*/
private function get_years_with_posts(
string $post_type = 'post',
array $post_stati = ['publish']
): array {
/** @var wpdb $wpdb */
global $wpdb;
/** Convierte el array $post_stati al equivalente MySql IN */
$post_status_in = "('" . implode("', '", array_map('esc_sql', $post_stati)) . "')";
/** Prepara la consulta con el tipo de publicación seleccionado */
$query = $wpdb->prepare(
"SELECT YEAR(post_date)
FROM {$wpdb->posts}
WHERE post_status IN $post_status_in
AND post_type = %s
GROUP BY YEAR(post_date) DESC",
$post_type
);
$years = $wpdb->get_results($query, ARRAY_N);
return array_column($years, 0);
}
Ejemplo de uso: Recuperar todas las publicaciones publicadas y programadas del tipo event
:
$avaliable_years = get_years_with_posts('event', ['publish', 'future']);
