Seleccionar qué posts mostrar en WordPress

22 Mar
2011

wordpress-1

Si estamos creando un tema personalizado en WordPress, quizá queramos mostrar sólo unos posts determinados en una zona concreta. Por ejemplo, podemos necesitar mostrar sólo los posts que consideremos importantes en la portada, o quizá tengamos un apartado lateral donde sólo nos interesan mostrar los posts que hablan de nuestra empresa, etc.

Hay varias soluciones, unas que son más sencillas y otras que, aunque más complejas, tiene mayor flexibilidad. Para que sea más fácil de entender, vamos a centrarnos en cómo hacerlo para los posts generados en el index, aunque es fácil trasladar la solución para un sidebar o cualquier otra sección de la web.

1. Seleccionar posts por categorías

En primer lugar deberíamos añadir una categoría en la que incluiremos los posts que queremos mostrar en la portada. Una vez creada, podemos ver su slug en el listado y su ID en el enlace de edición de la categoría (es el valor del parámetro cat_ID de la url).

La función que Worpdress utiliza para seleccionar los posts para mostrar es query_posts. Como vemos en la referencia de wordpress.org, podemos utilizar varios parámetros para definir la selección. En este caso nos interesa uno de los que filtran por categoría. Existen más parámetros que nos permiten realizar filtrados más complejos, pero para este ejemplo utilizaremos el más sencillo:

category_name (string) – el parámetro indica el slug (ojo, no el nombre) de la categoría cuyos posts queremos obtener.

Por tanto, simplemente modificando la función en el archivo de nuestro tema (el index.php o el archivo que utilicemos como plantilla para la portada):

query_posts('category_name=destacados');

obtendremos solamente los posts que pertenezcan a esta categoría.

Aunque es una solución sencilla, la contra es que puede que estemos utilizando una categoría simplemente para filtrar posts, y no para categorizarlos, con lo que ello conlleva.

2. Seleccionar posts por tags

Si no queremos utilizar una categoría, podremos utilizar un tag o etiqueta para marcar los posts que queremos visualizar. La solución es idéntica a la anterior, simplemente la función quedaría:

query_posts('tag=destacado');

Esta es la opción más sencilla, pero de nuevo podemos ver la referencia de la función respecto a tags si necesitamos utilizar filtrados más complejos. Podemos incluso utilizar un filtrado por categoría y por etiqueta simultáneamente.

E igual que en el anterior caso, la solución es sencilla pero puede que estemos utilizando una etiqueta sólo para filtrar posts en un determinado lugar.

3. Marcar explícitamente los posts a través de un checkbox en el backend

La solución más compleja pero funcional y flexible pasa por añadir un checkbox en el panel de edición del post que sirva para establecer una meta_key de Worpdress en los posts que queramos incluír en la portada.

Crear un checkbox en el backend

El archivo del tema functions.php define la configuración de nuestro tema. Podemos incluír en él acciones definidas por WordPress. En este caso, necesitamos ejecutar una función a través de la acción add_meta_boxes, por lo que en nuestro functions.php añadiremos:

add_action('add_meta_boxes', 'add_checkbox_portada');

Con lo que le indicamos a WordPress que en el momento de añadir meta boxes, se acuerde de nuestra función add_checkbox_portada. ¿Y qué queremos que haga? Pues añadir una meta box:

function add_checkbox_portada() {
	add_meta_box('es_portada', 'En portada', 'print_checkbox_portada', 'post', 'side');
}

Puedes consultar la referencia de esta función para ver los parámetros, aunque básicamente son el id del div que aparecerá en el backend, el título del bloque que se mostrará, la función encargada de imprimir el HTML, el tipo de elementos en el que aparecerá, y el lugar en que se mostrará.

Con lo que el siguiente paso será definir la función print_checkbox_portada que tendrá que imprimir el HTML del checkbox. En resumen, todo el código para crear el checkbox:

WP_seleccionar_posts/anadir_checkbox.php

Perfecto, ya tenemos un checkbox en el backend, pero… por ahora no sirve para nada.

Checkbox portada

Asignar el meta_key

Volvemos a utilizar las actions de Worpress para decirle que queremos que haga algo más cuando guardemos nuestro post. De nuevo incluímos una acción en el functions.php, y una función que se ejecute en esa acción:

WP_seleccionar_posts/save_checkbox_portada.php

Simplemente comentar que el tag debe comenzar por “_” para que Worpress entienda que no debe mostrarlo en el listado de tags (ni en frontend ni en backend).

Filtrar posts por nuestro meta_key

Simplemente nos falta indicar a WordPress que sólo queremos obtener los posts que tengan ese meta_key, por lo que, como en los anteriores apartados, cambiamos la función query_posts:

query_posts('meta_key=_portada');

Pero puede que no queramos utilizarlo en nuestro loop principal, y además, si no tenemos ningún post marcado como “portada”, quizá queramos obtener los últimos, en vez de no poner ninguno. Para ello podemos utilizar las funciones get_posts o crea un nuevo objeto WP_query, para no interferir con el loop principal. Personalmente me es más cómoda la segunda opción, por lo que podríamos crear una nueva función:

WP_seleccionar_posts/get_posts_portada.php

que luego llamaríamos en nuestra plantilla, donde quisiéramos que apareciesen esos posts.:q

En resumen, podemos añadir en nuestro functions.php:

WP_seleccionar_posts/seleccionar_posts.php

Would like to share? These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Digg
  • del.icio.us
  • Reddit
  • Facebook
  • Google Bookmarks
  • Ma.gnolia
  • TwitThis
  • LinkedIn

33 Responses to Seleccionar qué posts mostrar en WordPress

Avatar

Xavi

March 25th, 2012 at 19:11

Muy buen artículo, justo lo que necesitaba pero tengo una duda que me impide realizar ninguna de las tres opciones.
Mi theme es el de TwentyTen de wordpress, modificado. En el index.php no encuentro donde poner lo de “query_posts(‘meta_key=_portada’);”
ni en el archivo de loop tampoco, ¿sabrias decirme donde o como tengo que añadirlo? Muchas gracias,
saludos

Avatar

Félix Horro Pita

March 26th, 2012 at 10:30

Hola, Xavi.

Eso de tener un “TwentyTen modificado” quizá no sea muy buena idea. Date cuenta que una actualización del tema podría borrar los cambios que hayas hecho. Lo más recomendable es un tema hijo, que herede del TwentyTen, y que puedas modificar. Te recomiendo echar un vistazo a http://codex.wordpress.org/Child_Themes

Respondiendo a tu pregunta, tal y como dices el index.php del TwentyTen no define ninguna búsqueda específica, por lo que obtendrá la búsqueda por defecto, es decir, los últimos posts. Puedes modificarla con la función query_posts, antes de llamar al loop.

En el caso concreto que me planteas, en el index.php de tu tema hijo (o directamente del TwentyTen, aunque como decía no es recomendable), puedes indicar, antes del get_template_part: query_posts(‘meta_key=_portada’).

Un saludo.

Avatar

Xavi

March 31st, 2012 at 21:37

Hola, gracias por la respuesta.

He conseguido hacerlo funcionar! de las 2 formas, usando una categoría y con el checkbox de “En Portada”. Personalmente prefiero usar el checkbox, lo veo mas claro y funcional, lo que pasa que me gustaría que cuando el post ha sido seleccionado para mostrarse en portada y guardado, si vuelvo a entrar a editar el post debería ver el checkbox marcado, porque sinó no recuerdo si lo está o no, quiero decir que wordpress lo marca pero el checkbox no guarda el estado de checked cuando vuelves al backend para editar de nuevo ese post y no sabes si lo marcaste o no y eso despista.
¿hay forma de arreglarlo? con ese ajuste quedaría fino fino…

Este es el código completo que tengo ahora en functions.php (por si alguien más le interesa) con esto ya funciona pero sin dejar marcado visualmente el checkbox cuando vuelves a editar el post…

// FEATURED

add_action(‘add_meta_boxes’, ‘add_checkbox_featured’);

function add_checkbox_featured() {
add_meta_box(‘is_featured’, ‘Featured’, ‘print_checkbox_featured’, ‘post’, ‘side’);
}

function print_checkbox_featured() {
global $post;
$checked = get_post_meta($post->ID, ‘_featured’, true) ? ‘checked=”checked”‘ : ”;
echo ‘Show at front page ‘;
}

add_action(‘save_post’, ‘save_checkbox_featured’);

function save_checkbox_featured($post_id){
if (defined(‘DOING_AUTOSAVE’) && DOING_AUTOSAVE) return $post_id;

if ( !current_user_can( ‘edit_post’, $post_id ) )
return $post_id;

if ($_POST[‘is_featured’]){
add_post_meta($post_id, ‘_featured’, ‘1’);
}else{
delete_post_meta($post_id, ‘_featured’);
}
}

He cambiado la palabra “portada” por un “featured”, soy así de freaky… espero que nos importe!

Gracias y saludos ;)

Avatar

Xavi

March 31st, 2012 at 22:00

Bueno y ahora que lo pienso, también debería poder desmarcarlo, por si algun dia quiero que deje de aparecer ese post en la home.
Pero con el código que tengo ahora no se puede desmarcar…

Avatar

Xavi

March 31st, 2012 at 22:05

Bueno, lo siento por comentar antes de tiempo. Si que se puede desmarcar, checkeando y des-chekeando el checkbox. :)
Ahora solo faltaría que guarde el estado del checkbox visualmente, para saber si esta seleccionado para aprecer en la home o no,

Saludos!

Avatar

Félix Horro Pita

April 3rd, 2012 at 09:45

Hola, Xavi.

Tal y como defines la función que imprime la checkbox :

function print_checkbox_featured() {
global $post;
$checked = get_post_meta($post->ID, ‘_featured’, true) ? ‘checked=”checked”‘ : ”;
echo ‘Show at front page ‘;
}

no va a funcionar. En primer lugar, y supongo que será porque estabas en proceso de debug, eso no dibuja un checkbox, sino la frase “Show at front page”. La tercera línea debería ser:
echo ‘Mostrar en portada ‘;

En segundo lugar, ojo con las comillas al determinar si el ítem debe estar marcado o no. Me refiero a que la segunda línea dentro de la función debería ser:
$checked = get_post_meta($post->ID, ‘_featured’, true) ? ‘checked=”checked”‘ : ”;

Básicamente lo que hago ahí es asignar a la variable $checked el valor checked=”checked” si el post tiene el tag _featured, y en caso contrario asignarle un string vacío: ” (dos comillas simples).

Si este es el error, debería aparecer algo en el log de tu servidor cuando está mal.

Avatar

Xavi

April 3rd, 2012 at 22:39

Hola Félix, gracias por la ayuda :)
pero uso tu código y no me acaba de funcionar. Las comillas las tengo bien, no se porque no se publicó el trozo de código que imprime el checkbox.
Pero como te digo el checkbox funciona y los post se muestran correctamente solo los que tocan, es decir que funciona el asunto, el único problema es que el checkbox no se queda marcado como te expliqué, los marcas y funciona el asunto pero luego si vuelves a editar el post no aparecen chequeados visualmente y si que lo estan…

este es el código:

add_action(‘add_meta_boxes’, ‘add_checkbox_featured’);

function add_checkbox_featured() {
add_meta_box(‘is_featured’, ‘Featured’, ‘print_checkbox_featured’, ‘post’, ‘side’);
}

function print_checkbox_featured() {
global $post;
$checked = get_post_meta($post->ID, ‘_featured’, true) ? ‘checked=”checked”‘ : ”;
echo ‘Show at front page ‘;
}

add_action(‘save_post’, ‘save_checkbox_featured’);

function save_checkbox_featured($post_id){
// Si la llamada es un autosave, no queremos hacer nada
if (defined(‘DOING_AUTOSAVE’) && DOING_AUTOSAVE) return $post_id;

// Comprobamos los permisos del usuario
if ( !current_user_can( ‘edit_post’, $post_id ) )
return $post_id;

if ($_POST[‘is_featured’]){
// Si el checkbox está marcado, añadimos el meta key
add_post_meta($post_id, ‘_featured’, ‘1’);
}else{
// Si no está marcado, borramos el meta key
delete_post_meta($post_id, ‘_featured’);
}
}

Avatar

Xavi

April 3rd, 2012 at 22:40

He separado las palabras porque no publica la segunda parte de echo

function print_checkbox_featured() {
global $post;
$checked = get_post_meta($post->ID, ‘_featured’, true) ? ‘checked=”checked”‘ : ”;
echo ‘Show at front page ‘;
}

Avatar

Xavi

April 3rd, 2012 at 22:40

jolin…

‘Show at front page ‘

Avatar

Xavi

April 3rd, 2012 at 22:41

label for=”checkbox_is_featured”>Show at front page <input id="checkbox_is_featured" name="is_featured" type="checkbox" value="1"

Avatar

Xavi

April 3rd, 2012 at 22:44

y lo que abre y cierra label e input lo tengo bien… es que sinó no se posteaba el comentario,
disculpas

Avatar

Xavi

April 3rd, 2012 at 22:50

Vale, lo he conseguido, que bien!!
faltaba esto: ‘.$checked.’
es que copié el código de la primera parte de la explicación supongo…
muy contento, mil gracias, super buen aporte.

Saludos

Avatar

Félix Horro Pita

April 4th, 2012 at 09:34

Ok, Xavi, efectivamente primero determino si el checkbox tiene que estar marcado, y guardo el ‘checked=”checked”‘ en la variable $checked.
Después hay que pintar esa variable con el input.

Me alegro que te haya resultado útil.

Un saludo.

Avatar

Xavi

April 15th, 2012 at 12:45

Hola de nuevo,
tengo otra duda. He creado tipos de post personalizado (custom post type) con una herramienta online, que va de maravilla por cierto
se llaman “projects” y el singular “project”

Pues ahora no consigo hacer que los post que se muestren en la home no sean “posts” sinó “projects”
Sabrias decirme como?

muchas gracias!
Saludos

Avatar

Félix Horro Pita

April 16th, 2012 at 13:46

Hola, Xavi.

Siento no poder ayudarte, pero no conozco esa herramienta. Hay varias formas de hacer lo que me comentas, por lo que en este caso es difícil orientarte.

Espero que lo resuelvas.

Un saludo.

Avatar

Carolina

June 12th, 2012 at 03:20

Justo lo que necesitaba, muchas gracias por tu ayuda!

Avatar

jhosh petrovich

October 5th, 2012 at 10:58

primero qu e todo agradezco la atención a mi pregunta que tiene que ver con el tema que estan tratando por acá

la cuesti´lon es que quisiera que en vez de post en mi index, aparecieran paginas, como hago ese cambio?

Avatar

Félix Horro Pita

October 8th, 2012 at 10:02

Hola, Jhosh.

Lo que comentas se puede hacer tal y como explican en el manual:

http://codex.wordpress.org/Creating_a_Static_Front_Page

Un saludo.

Avatar

Bruno L.

November 23rd, 2012 at 13:46

Capo. Llevaba 5 horas dándole vueltas al tema. Lo rondaba, casi lo tenía, pero hasta que no he llegado a tu artículo no lo he comprendido…

¡Muchas gracias!

Avatar

Enrique

May 26th, 2013 at 14:14

Gracias por el artículo. Es estupendo.
Tengo un problema. Estoy utilizando un meta key para seleccionar entradas de la portada. Funciona bien, pero cuando pulso anteriores me sale las mismas entradas, es decir no pagina.
¿Podéis ayudarme?

Avatar

Félix Horro Pita

June 17th, 2013 at 13:55

Hola, Enrique.

Te recomiendo echar un vistazo a la referencia: http://codex.wordpress.org/Class_Reference/WP_Query#Pagination_Parameters

Básicamente, habría que comprobar el campo de paginación al crear el WP_Query. Quedaría algo como:

$paged = get_query_var(‘paged’) ? get_query_var(‘paged’) : 1;
$args = array(
‘meta_key’ => ‘_portada’,
‘paged’ => $paged
);

$portada = new WP_query($args);

El código lo escribo de memoria y sin comprobar el funcionamiento, puedes utilizar la referencia para comprobar los errores (si hay).

Espero que te sirva.

Avatar

Mike

August 29th, 2013 at 02:11

Buenas…he seguido el manual y he ido pegando el código que Félix ha indicado y va todo bien, pero cuando pego el código de la seccion get_posts_portada

have_posts()) {
$portada = new WP_query();
}

while ( $portada->have_posts() ) : $portada->the_post();
?>

<a href="” title=””>

<a href="” title=””>Leer entrada

no me funciona la página….hay algún error en este código?
Gracias

Avatar

Mike

August 29th, 2013 at 02:14

Bueno….ha salido un churro de código y no se ve bien…¿cómo puedo mandar el archivo functions.php para que lo reviséis.?

Avatar

Mike

August 29th, 2013 at 02:29

Avatar

Mike

August 30th, 2013 at 07:48

ya he visto el error de sintexis:
if (defined(‘DOING_AUTOSAVE’) && DOING_AUTOSAVE) return $post_id; esta es la correcta

Por otro lado decir que ahora no da error pero el check box no hace nada….da igual que esté marcada o no….todos los posts se publican en la portada.
Uso el Theme Rapido

Avatar

Mike

September 12th, 2013 at 23:05

bueno ya he conseguido que funcione pero hay un problema……no pagina!!, quiero decir que siempre salen los mismos mensajes . En la paginación me indica que tengo 5 páginas pero en todas me salen siempre los mismos post. Ideas?

Avatar

Félix Horro Pita

September 19th, 2013 at 17:50

Hola, Mike.

Gracias por comentar. Respecto al paginado, es necesario comprobar el paginado de WP. Lo explicaba muy brevemente en un comentario anterior:

http://blog.corunet.com/seleccionar-que-posts-mostrar-en-wordpress/#comment-2181

Espero que te sirva.

Avatar

Mike

September 25th, 2013 at 15:15

Gracias por la respuesta y por el código que va de cine. Eso va perfecto para un blog nuevo ya que cada vez que creas una entrada decides, marcando el checkbox, si quieres que aparezca en la portada o no…. pero el problema lo tengo en mi blog wordpress al cual he aplicado tu código ya que tengo mas de 1200 entradas y todas ellas no tienen el checkbox marcado ni el meta_key=”_portada” al ser anteriores a la inclusión del codigo. Ahora he de ir editando las entradas una a una para marcar el checkbox ya que quiero que todas las entradas antigüas salgan en la portada paginadas. Es un trabajo de chinos. Se te ocurre alguna forma de añadir el meta_key=”_portada”a todas las entradas de una vez sin tener que ir una a una marcando la casilla?. Gracias

Avatar

Mike

September 25th, 2013 at 15:17

Por cierto, he hecho la misma pregunta en los forosdelweb.com pegando tu código para que vean de lo que hablo. He puesto que tú eras el autor del mismo……al César lo que es del César ;-)

http://www.forosdelweb.com/f118/seleccionar-cual-entrada-ira-pagina-principal-cual-no-como-997740/#post4492803

Avatar

Félix Horro Pita

September 25th, 2013 at 17:10

Hola, Mike, y gracias por compartir.

Quizá en tu caso lo mejor sea invertir la funcionalidad, es decir, que el check no sea para indicar que se quiere el post en portada, sino para indicar que no se quiere en portada.
Así, por defecto los posts aparecerían en portada, y sólo los que marcases no aparecerían.

Para esto, deberías cambiar los textos del checkbox, y en vez de “Mostrar en portada” debería decir “No mostrar en portada”, y quizá sería bueno cambiar el meta, en vez de “_portada”, que fuese “_noportada” o similar.

Por último, la función get_posts_portada() debería cambiar la creación de la WP_Query, de forma que seleccione los posts que no tengan ese meta:

$portada = new WP_Query( array( ‘meta_key’ => ‘_noportada’, ‘meta_value’ => ‘1’, ‘meta_compare’ => ‘NOT EXISTS’ ) );

Ojo que NOT EXISTS sólo existe a partir de la versión 3.5 de WordPress.

Tiene la referencia aquí: http://codex.wordpress.org/Class_Reference/WP_Query#Custom_Field_Parameters

Si de todas formas quieres mantener la funcionalidad original (marcar el check para que sí aparezcan en portada), tendrías que crear un script que para cada post de la tabla wp_posts (suponiendo wp_ tu prefijo de tablas), cree una entrada en wp_posts_meta, si aún no existe. Por ejemplo, para un post con id 123, sería:

INSERT INTO wp_posts_meta(post_id, meta_key, meta_value) VALUES
(123, ‘_portada’, 1);

Espero que te sirva.

Avatar

Mike

September 26th, 2013 at 03:18

ok, esa opcion de revertir la funcion del checkbox la habia pensado pero no sabia como hacerlo. En el caso de que opte por esa solucion, la linea de codigo que puse en el index.php de mi theme la he de dejar tal cual o he de cambiar algo query_posts(‘meta_key=_portada’); ?.
Y si optara por la segunda opcion….¿cómo se crea ese script y cómo se usa o activa?. gracias

Avatar

Félix Horro Pita

September 26th, 2013 at 17:48

Hola, Mike.

Como decía en el comentario anterior, los argumentos para la query quedarían:
query_posts(array( ‘meta_key’ => ‘_noportada’, ‘meta_value’ => ’1′, ‘meta_compare’ => ‘NOT EXISTS’ ) );

Respecto a la creación del script, podría ser atacando directamente la base de datos o incluso mediante funciones WordPress, pero entiendo que la formulación del mismo escapa del alcance de este post.

Un saludo.

Avatar

Mike

September 30th, 2013 at 02:13

Buenas, ya he conseguido la solución para meter el meta_key a todos los artículos a la vez usando tu código:
INSERT INTO wp_postsmeta(post_id, meta_key, meta_value) VALUES (123, ‘_portada’, 1); que fue la clave….

Modificado por un usuario de forosdelweb.com llamado quimfv:
INSERT INTO wp_postmeta(post_id, meta_key, meta_value) SELECT ID, ‘_portada’, 1 FROM wp_posts;

Gracias a los dos por vuestra ayuda, ya tengo los 1200 articulos con el checkbox “mostrar en portada” marcado y con todos los artículos en portada paginados, que por cierto he conseguido paginar con el siguiente código (por si le interesa a alguien) metido en el index.php del theme.

$paged = (get_query_var(‘paged’)) ? get_query_var(‘paged’) : 1;
query_posts(‘meta_key=_portada&paged=’ . $paged);

Comment Form

top