Filtrar posts por categoría con AJAX al hacer clic
Este es mi primer acercamiento a AJAX, he estado combinando fragmentos de código de varios tutoriales lo que probablemente no ha ayudado.
Tengo una lista de categorías en mi página de inicio (index.php) y una lista de los posts más recientes. Cuando un usuario hace clic en una categoría quiero que esta lista de posts se actualice sin refrescar la página. Actualmente cuando hago clic en un filtro todos los posts se cargan en mi contenedor de respuesta (no se filtra por categoría) y el único contenido que se carga es the_content(), aunque mi plantilla (listing-post.php) solicita la imagen destacada, la categoría etc.
Estoy usando Bones como mi tema inicial, por eso wp_localize_script está en este archivo (está funcionando). Solo he incluido código que sé que tiene problemas (sé que el resto del sitio y JS funciona bien).
bones.php
// Agregar ruta AJAX para usar en load-posts.js
$getPath = array('ajaxURL' => admin_url('admin-ajax.php'));
wp_localize_script('main-js', 'pathToFile', $getPath);
functions.php
// Filtro AJAX por Categoría
add_action( 'wp_ajax_load_cat_posts', 'load_cat_posts' );
add_action( 'wp_ajax_nopriv_load_cat_posts', 'load_cat_posts' );
function load_cat_posts () {
$cat_id = $_REQUEST['cat']; // Corregido: obtener directamente el ID de categoría
$args = array (
'cat' => $cat_id,
'posts_per_page' => 10,
'order' => 'DESC'
);
$posts = get_posts($args);
ob_start ();
foreach ( $posts as $post ) {
setup_postdata( $post ); ?>
<?php get_template_part( 'partials/listing', 'post'); ?>
<?php } wp_reset_postdata();
$response = ob_get_contents();
ob_end_clean();
echo $response;
die(1);
}
index.php
<?php $categories = get_categories(); ?>
<ul class="category-filters">
<?php foreach ( $categories as $cat ) { ?>
<li id="cat-<?php echo $cat->term_id; ?>">
<a class="<?php echo $cat->slug; ?> ajax" data-cat="<?php echo $cat->term_id; ?>" href="javascript:void(0)"><?php echo $cat->name; ?></a>
</li>
<?php } ?>
</ul>
listing-post.php
<li class="standard-post">
<article id="<?php echo sanitize_title_with_dashes( get_the_title() ); ?>" <?php post_class(); ?> role="article">
<?php if (has_post_thumbnail()) { ?>
<div class="article-image">
<?php the_post_thumbnail('large'); ?> <!-- Corregido: añadidas comillas -->
</div>
<?php } ?>
<div class="article-left">
<?php foreach((get_the_category()) as $category) { ?>
<span class="article-category"><?php echo $category->cat_name . ' ';?></span>
<?php } ?>
</div>
<div class="article-right">
<header class="article-header">
<h1 class="article-title"><?php the_title(); ?></h1>
<p class="article-time">
<?php printf( __( '<time class="updated" datetime="%1$s" pubdate>%2$s</time>', 'bonestheme' ), get_the_time(), get_the_time(get_option('date_format'))); ?>
</p>
</header>
<section class="entry-content">
<?php the_content(); ?>
</section>
</div>
</article>
</li>
load-posts.js
function cat_ajax_get(currentCat) {
$('a.ajax').removeClass('current');
$('a.ajax').addClass('current');
$('#loading-animation').show();
$.ajax({
type: 'POST',
url: pathToFile.ajaxURL, // Corregido: usar la variable localizada
data: {action: 'load_cat_posts', cat: currentCat },
success: function(response) {
$('.article-listing').html(response);
$('#loading-animation').hide();
return false;
}
});
};
ajaxFilters: function() {
$('.category-filters a').on('click', $.proxy(function(clickEvent) {
$clickTarget = $(clickEvent.currentTarget);
var currentCat = $clickTarget.attr('data-cat');
cat_ajax_get(currentCat);
},this));
}

Esta línea en functions.php
es tu problema:
$cat_id = get_post_meta($_REQUEST['cat']);
Creo que estás malinterpretando el propósito de la función get_post_meta()
. Está diseñada para obtener metadatos de una entrada de WordPress, no datos de una solicitud POST
al sitio. El primer parámetro de la función get_post_meta()
es el $post_id
, pero como estás pasando el ID de categoría en su lugar, obtendrás false
o un array de todos los valores meta si existe una entrada con el mismo ID que ese ID de categoría. En cualquiera de esos casos, el valor de la variable de consulta cat
no será un ID de categoría válido, por lo que esa parte de la consulta será ignorada y se devolverán todas las entradas. Si cambias esa línea por esto, solucionarás el problema y tu código probablemente funcionará:
$cat_id = absint( $_REQUEST['cat'] );
La función absint()
simplemente convierte el valor proporcionado por el usuario en un entero positivo.
