Estas en: Home > index

Entradas etiquetadas con index

Cron Job WordPress

WordPress 3.x para desarrolladores: Temas y plantillas, index.php y content.php

0

Con el anterior post os dejé un poco colgados con el tutorial, expliqué las plantillas más básicas y la creación de las plantillas de la cabecera y el pie, además de la explicación del código de cada una. Pero aun falta la parte más importante de todas, el contenido.

 

EL BUCLE ( THE LOOP )

Bueno, vamos al lío y explico esto del bucle. En el archivo index.php añadimos el siguiente código entre wp_head() y wp_footer().

 

  1. <div id="primary">
  2. <div id="content" role="main">
  3.  
  4. <?php if ( have_posts() ) : ?>
  5.  
  6. <?php newtheme_content_nav( 'nav-above' ); ?>
  7.  
  8. <?php /* Start the Loop */ ?>
  9. <?php while ( have_posts() ) : the_post(); ?>
  10.  
  11. <?php get_template_part( 'content', get_post_format() ); ?>
  12.  
  13. <?php endwhile; ?>
  14.  
  15. <?php newtheme_content_nav( 'nav-below' ); ?>
  16.  
  17. <?php else : ?>
  18.  
  19. <article id="post-0" class="post no-results not-found">
  20. <header class="entry-header">
  21. <h1 class="entry-title"><?php _e( 'Nothing Found', 'newtheme' ); ?></h1>
  22. </header><!-- .entry-header -->
  23.  
  24. <div class="entry-content">
  25. <p><?php _e( 'Apologies, but no results were found for the requested archive. Perhaps searching will help find a related post.', 'newtheme' ); ?></p>
  26. </div><!-- .entry-content -->
  27. </article><!-- #post-0 -->
  28.  
  29. <?php endif; ?>
  30.  
  31. </div><!-- #content -->
  32. </div><!-- #primary -->
  33.  
  34. <?php get_sidebar(); ?>

 

Lo primero que hacemos es crear dos capas con id primary y content, ambas contendrán el contenido que se muestre en la página.

Seguidamente tenemos un condicional que comprueba si hay posts para mostrar en la página.

Si es que sí hay posts, WordPress procesará las cinco siguientes líneas de código y dentro de estas nuestro bucle o The Loop.

Antes y después del bucle se hace una llamada a la función newtheme_content_nav(), este es un hook para crear el paginador de post en el caso de que haya más que las que pueden entrar en una página. Esta función la crearemos más adelante en el archivo functions.php.

El bucle while se ejecutará mientras have_posts() sea true, y los datos del post se obtienen de the_post(), que serán procesados en la plantilla correspondiente utilizando get_template_part( ‘content’, get_post_format() ). Esta función (get_template_part()) llama a la plantilla content para procesarla y generar el código html correspondiente.

Si no hay posts entonces se muestra un mensaje al usuario indicando esto mismo.

Cerramos las etiquetas div. Por último nos encontramos con la función get_sidebar(), que nos generará la barra lateral con los widgets de nuestro blog. De hecho ya vimos esta función en la plantilla del pie (footer.php) en ella nos encontramos con la función get_sidebar( ‘footer’ ). La razón de que una función tenga argumento y otra no, radica en la plantilla a usar. En el caso del sidebar del pie, se utilizará sidebar-footer.php y para el sidebar del index.php usaremos la genérica: sidebar.php.

Si ejecutásemos ahora la página principal de nuestro WordPress no veríamos contenido, la razón es que aun no hemos creado la plantilla que muestra el contenido, así que vamos a ello.

 

CONTENT.PHP

Este archivo es el encargado de mostrar el contenido de los posts y maquetarlo en html. Para ello vamos a crear el archivo content.php y añadir las siguientes líneas de código:

 

  1. <article id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
  2. <header class="entry-header">
  3. <?php if ( is_sticky() ) : ?>
  4. <hgroup>
  5. <h2 class="entry-title"><a href="<?php the_permalink(); ?>" title="<?php printf( esc_attr__( 'Permalink to %s', 'newtheme' ), the_title_attribute( 'echo=0' ) ); ?>" rel="bookmark"><?php the_title(); ?></a></h2>
  6. <h3 class="entry-format"><?php _e( 'Featured', 'newtheme' ); ?></h3>
  7. </hgroup>
  8. <?php else : ?>
  9. <h1 class="entry-title"><a href="<?php the_permalink(); ?>" title="<?php printf( esc_attr__( 'Permalink to %s', 'newtheme' ), the_title_attribute( 'echo=0' ) ); ?>" rel="bookmark"><?php the_title(); ?></a></h1>
  10. <?php endif; ?>
  11.  
  12. <?php if ( 'post' == get_post_type() ) : ?>
  13. <div class="entry-meta">
  14. <?php newtheme_posted_on(); ?>
  15. </div><!-- .entry-meta -->
  16. <?php endif; ?>
  17.  
  18. <?php if ( comments_open() && ! post_password_required() ) : ?>
  19. <div class="comments-link">
  20. <?php comments_popup_link( '<span class="leave-reply">' . __( 'Reply', 'newtheme' ) . '</span>', _x( '1', 'comments number', 'newtheme' ), _x( '%', 'comments number', 'newtheme' ) ); ?>
  21. </div>
  22. <?php endif; ?>
  23. </header><!-- .entry-header -->
  24.  
  25. <?php if ( is_search() ) : // Only display Excerpts for Search ?>
  26. <div class="entry-summary">
  27. <?php the_excerpt(); ?>
  28. </div><!-- .entry-summary -->
  29. <?php else : ?>
  30. <div class="entry-content">
  31. <?php the_content( __( 'Continue reading <span class="meta-nav">&rarr;</span>', 'newtheme' ) ); ?>
  32. <?php wp_link_pages( array( 'before' => '<div class="page-link"><span>' . __( 'Pages:', 'newtheme' ) . '</span>', 'after' => '</div>' ) ); ?>
  33. </div><!-- .entry-content -->
  34. <?php endif; ?>
  35.  
  36. <footer class="entry-meta">
  37. <?php $show_sep = false; ?>
  38. <?php if ( 'post' == get_post_type() ) : // Hide category and tag text for pages on Search ?>
  39. <?php
  40. /* translators: used between list items, there is a space after the comma */
  41. $categories_list = get_the_category_list( __( ', ', 'newtheme' ) );
  42. if ( $categories_list ):
  43. ?>
  44. <span class="cat-links">
  45. <?php printf( __( '<span class="%1$s">Posted in</span> %2$s', 'newtheme' ), 'entry-utility-prep entry-utility-prep-cat-links', $categories_list );
  46. $show_sep = true; ?>
  47. </span>
  48. <?php endif; // End if categories ?>
  49. <?php
  50. /* translators: used between list items, there is a space after the comma */
  51. $tags_list = get_the_tag_list( '', __( ', ', 'newtheme' ) );
  52. if ( $tags_list ):
  53. if ( $show_sep ) : ?>
  54. <span class="sep"> | </span>
  55. <?php endif; // End if $show_sep ?>
  56. <span class="tag-links">
  57. <?php printf( __( '<span class="%1$s">Tagged</span> %2$s', 'newtheme' ), 'entry-utility-prep entry-utility-prep-tag-links', $tags_list );
  58. $show_sep = true; ?>
  59. </span>
  60. <?php endif; // End if $tags_list ?>
  61. <?php endif; // End if 'post' == get_post_type() ?>
  62.  
  63. <?php if ( comments_open() ) : ?>
  64. <?php if ( $show_sep ) : ?>
  65. <span class="sep"> | </span>
  66. <?php endif; // End if $show_sep ?>
  67. <span class="comments-link"><?php comments_popup_link( '<span class="leave-reply">' . __( 'Leave a reply', 'newtheme' ) . '</span>', __( '<b>1</b> Reply', 'nwtheme' ), __( '<b>%</b> Replies', 'newtheme' ) ); ?></span>
  68. <?php endif; // End if comments_open() ?>
  69.  
  70. <?php edit_post_link( __( 'Edit', 'newtheme' ), '<span class="edit-link">', '</span>' ); ?>
  71. </footer><!-- #entry-meta -->
  72. </article><!-- #post-<?php the_ID(); ?> -->

 

Sí, es mucho código pero como siempre os lo explicaré casi línea por línea.

En primer lugar tenemos las etiquetas article y header del post:

<article id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
 <header class="entry-header">

Aquí vemos dos funciones de WordPress, la primera the_ID() sirve para devolver el id del post, el segundo genera las clases de estilos para el post.

Ha continuación tenemos el siguiente bloque condicional dentro de la etiqueta header:

 

  1. <?php if ( is_sticky() ) : ?>
  2. <hgroup>
  3. <h2 class="entry-title"><a href="<?php the_permalink(); ?>" title="<?php printf( esc_attr__( 'Permalink to %s', 'newtheme' ), the_title_attribute( 'echo=0' ) ); ?>" rel="bookmark"><?php the_title(); ?></a></h2>
  4. <h3 class="entry-format"><?php _e( 'Featured', 'newtheme' ); ?></h3>
  5. </hgroup>
  6. <?php else : ?>
  7. <h1 class="entry-title"><a href="<?php the_permalink(); ?>" title="<?php printf( esc_attr__( 'Permalink to %s', 'newtheme' ), the_title_attribute( 'echo=0' ) ); ?>" rel="bookmark"><?php the_title(); ?></a></h1>
  8. <?php endif; ?>
  9.  
  10. <?php if ( 'post' == get_post_type() ) : ?>
  11. <div class="entry-meta">
  12. <?php newtheme_posted_on(); ?>
  13. </div><!-- .entry-meta -->
  14. <?php endif; ?>
  15.  
  16. <?php if ( comments_open() && ! post_password_required() ) : ?>
  17. <div class="comments-link">
  18. <?php comments_popup_link( '<span class="leave-reply">' . __( 'Reply', 'newtheme' ) . '</span>', _x( '1', 'comments number', 'newtheme' ), _x( '%', 'comments number', 'newtheme' ) ); ?>
  19. </div>
  20. <?php endif; ?>

 

Como puedes ver el condicional comprueba la función is_sticky(). Esta función comprueba si el post ha sido seleccionado para que se mantenga fijo en la página principal o como destacado. Como verás, si el post está fijo en la página principal se mostrará el título de la entrada y un texto (Featured o Destacado) que indica el estado de este.

En el caso que no sea un post destacado se genera el título por defecto. Para generar la url se utiliza la función the_permalink() que genera la url absoluta del post. Además se añade al atributo title del link el título del post.

  1. <?php if ( 'post' == get_post_type() ) : ?>
  2. <div class="entry-meta">
  3. <?php newtheme_posted_on(); ?>
  4. </div><!-- .entry-meta -->
  5. <?php endif; ?>

Este código genera el html correspondiente para las etiquetas meta de la página/post: fecha/hora, autor, descripción, etc.

  1. <?php if ( comments_open() && ! post_password_required() ) : ?>
  2. <div class="comments-link">
  3. <?php comments_popup_link( '<span class="leave-reply">' . __( 'Reply', 'newtheme' ) . '</span>', _x( '1', 'comments number', 'newtheme' ), _x( '%', 'comments number', 'newtheme' ) ); ?>
  4. </div>
  5. <?php endif; ?>

Aquí se comprueba si el post permite comentarios y no es requerida una contraseña. Dentro del condicional se crea el link que mostrará los comentarios, además el texto del vínculo será el número de comentarios que tiene el post. Esto crearía un número al lado del título del post, normalmente con un fondo con una burbuja de diálogo.

  1. <?php if ( is_search() ) : // Only display Excerpts for Search ?>
  2. <div class="entry-summary">
  3. <?php the_excerpt(); ?>
  4. </div><!-- .entry-summary -->
  5. <?php else : ?>
  6. <div class="entry-content">
  7. <?php the_content( __( 'Continue reading <span class="meta-nav">&rarr;</span>', 'newtheme' ) ); ?>
  8. <?php wp_link_pages( array( 'before' => '<div class="page-link"><span>' . __( 'Pages:', 'newtheme' ) . '</span>', 'after' => '</div>' ) ); ?>
  9. </div><!-- .entry-content -->
  10. <?php endif; ?>

Se comprueba si lo que se está mostrando es una búsqueda, si es así se carga parte del cuerpo del post pero añadiendo al final del texto […].

Si no se está mostrando una búsqueda se carga el contenido con la función the_content(), que en el caso que el post contenga un separador del tipo “read more… ” se mostrará un texto que lo indique. Por último se muestran una serie de links para poder ir directamente a las diferentes páginas del post.

  1. <footer class="entry-meta">
  2. <?php $show_sep = false; ?>
  3. <?php if ( 'post' == get_post_type() ) : // Hide category and tag text for pages on Search ?>
  4. <?php
  5. /* translators: used between list items, there is a space after the comma */
  6. $categories_list = get_the_category_list( __( ', ', 'newtheme' ) );
  7. if ( $categories_list ):
  8. ?>
  9. <span class="cat-links">
  10. <?php printf( __( '<span class="%1$s">Posted in</span> %2$s', 'newtheme' ), 'entry-utility-prep entry-utility-prep-cat-links', $categories_list );
  11. $show_sep = true; ?>
  12. </span>
  13. <?php endif; // End if categories ?>
  14. <?php
  15. /* translators: used between list items, there is a space after the comma */
  16. $tags_list = get_the_tag_list( '', __( ', ', 'newtheme' ) );
  17. if ( $tags_list ):
  18. if ( $show_sep ) : ?>
  19. <span class="sep"> | </span>
  20. <?php endif; // End if $show_sep ?>
  21. <span class="tag-links">
  22. <?php printf( __( '<span class="%1$s">Tagged</span> %2$s', 'newtheme' ), 'entry-utility-prep entry-utility-prep-tag-links', $tags_list );
  23. $show_sep = true; ?>
  24. </span>
  25. <?php endif; // End if $tags_list ?>
  26. <?php endif; // End if 'post' == get_post_type() ?>
  27.  
  28. <?php if ( comments_open() ) : ?>
  29. <?php if ( $show_sep ) : ?>
  30. <span class="sep"> | </span>
  31. <?php endif; // End if $show_sep ?>
  32. <span class="comments-link"><?php comments_popup_link( '<span class="leave-reply">' . __( 'Leave a reply', 'newtheme' ) . '</span>', __( '<b>1</b> Reply', 'nwtheme' ), __( '<b>%</b> Replies', 'newtheme' ) ); ?></span>
  33. <?php endif; // End if comments_open() ?>
  34.  
  35. <?php edit_post_link( __( 'Edit', 'newtheme' ), '<span class="edit-link">', '</span>' ); ?>
  36. </footer><!-- #entry-meta -->

Llegamos al pie del post donde se comprobará primero que lo que se muestra es un post y no una búsqueda, en el caso de ser esto afirmativo se cargan las categorías a la que pertenezca el post y se genera su código html correspondiente.

Después se carga el listado de tags o etiquetas y se genera el código html para mostrarlas.

A continuación mostramos de nuevo el número de comentarios del post.

Por último mostramos el link de editar post, siempre y cuando el usuario tenga permiso para ello.

Logo Cassandra

Cassandra 1.x y PHP para desarrolladores SQL: phpCassa (II)

0

En el anterior post traté las acciones habituales que realizamos con Cassandra: guardar, actualizar y eliminar. Sin embargo aun quedan dos acciones muy útiles por tratar: los contadores y los indices secundarios.

 

CONTADORES

Los contadores son en realidad un tipo especial de validador de Column Family.

 

CREAR UN CONTADOR 

Para crearla procedemos de la siguiente manera:

– Accedemos a Cassandra Cluster Admin:

Página principal de Cassandra Cluster Admin

– Entramos en el keyspace con el que estamos trabajando:

Detalle del keyspace my_keyspace

– Pulsamos en Create New Column Family y escribimos los siguientes datos:

Datos para crear una Column Family con contadores

– En Default Validation Class el texto completo a escribir es:

org.apache.cassandra.db.marshal.CounterColumnType

– Y pulsamos el botón Create Column Family.

Varias cosas sobre los CounterColumn:
– Para crear los CounterColumns es obligatorio indicar en Default Validation Class la clase de validador correcto. Indicado más arriba.
– Los contadores puedes tener números positivos o negativos.
– Los CounterColumns no son un sustituto de el autoincrement de las bases relacionales.

Ahora que ya está creada la Column Family es hora de programar.

 

GUARDAR Y/O ACTUALIZAR UN CONTADOR 

En nuestra clase en cassandra.php creamos el siguiente método:

 

  1. <?php
  2.  
  3. public function guardarContador($name_columnFamily, $key, $column, $value=1, $super_column=NULL){
  4.  
  5. try {
  6. if (!is_null($super_column)){
  7. $column_family = new SuperColumnFamily($this->conexion, $name_columnFamily);
  8. $column_family->add($key, $super_column, $column, $value);
  9. }
  10. else{
  11. $column_family = new ColumnFamily($this->conexion, $name_columnFamily);
  12. $column_family->add($key, $column, $value);
  13. }
  14. return true;
  15. }
  16. catch(Exception $e){
  17. return false;
  18. }
  19. }

 

Con este método podremos incrementar o disminuir el contador.


$name_columnFamily
: Es el nombre de la column family donde se encuentra el contador a modificar.

$key: Clave del registro donde se encuentra el contador.
$column: Nombre del contador.
$value: Valor a añadir al contador.
$super_column: Clave de la super column donde se encuentra el contador.

Añadimos el siguiente código a nuestro archivo test.php:

  1. <?php
  2.  
  3. if ( $cass->guardarContador('column_family_counter', 'post', 'num_total_post', 1)){
  4. print "El contador se ha actualizado correctamente<br />";
  5. }else{
  6. print "Error al actualizar el contador<br />";
  7. }
  8.  
  9. $result = $cass->obtener('column_family_counter', 'post');
  10.  
  11. print_r($result);

Como ves, para recuperar un contador se utiliza el mismo método que para obtener cualquier otro registro. El resultado de este código sería:

El contador se ha actualizado correctamente
 Array ( [num_total_post] => 1 )

 

PONER A CERO EL CONTADOR

Para poner a cero un contador hay que restarle el valor que tenga en ese momento el contador. En test.php escribiríamos lo siguiente:

  1. <?php
  2.  
  3. if ( $cass->guardarContador('column_family_counter', 'post', 'num_total_post', ($result['num_total_post']*-1))){
  4. print "El contador se ha actualizado correctamente<br />";
  5. }else{
  6. print "Error al actualizar el contador<br />";
  7. }
  8.  
  9. $result = $cass->obtener('column_family_counter', 'post');
  10.  
  11. print_r($result);

Y el resultado:

El contador se ha actualizado correctamente
 Array ( [num_total_post] => 0 )

 

INDICES SECUNDARIOS

Los indices secundarios son un objeto especial en Cassandra que nos permite realizar búsquedas por columnas concretas.

Estos índices solo funcionan en las column family standard, con lo que su uso se ve bastante limitado.

 

 

CREAR UN INDICE SECUNDARIO

Para ello vamos a nuestro Cassandra Cluster Admin y en la column family my_column_family_standard pulsamos en Create Secondary Index:

Detalle de la ubicación del botón Create Secondary Index

Detalle de la ubicación del botón Create Secondary Index

– Nos aparecerá el siguiente formulario:

Detalle del formulario para crear un índice secundario

Detalle del formulario para crear un índice secundario

– Para nuestro cometido vamos a crear el siguiente índice secundario:

Formulario con los datos para el ejemplo

Formulario con los datos para el ejemplo

–  Pulsamos en Add Secondary Index.

 

REALIZAR UNA CONSULTA CON UN INDICE SECUNDARIO 

Nos vamos a nuestro archivo cassandra.php y añadimos el siguiente método:

  1. <?php
  2.  
  3. private function getIndexOperator($value){
  4. switch ($value){
  5. case '=':
  6. $operator = 'EQ';
  7. break;
  8. case '>=':
  9. $operator = 'GTE';
  10. break;
  11. case '>':
  12. $operator = 'GT';
  13. break;
  14. case '<=':
  15. $operator = 'LTE';
  16. break;
  17. case '<':
  18. $operator = 'LT';
  19. break;
  20. default:
  21. $operator = 'EQ';
  22. break;
  23. }
  24.  
  25. return $operator;
  26. }

Este método nos permitirá trabajar con operadores diferentes a la igualdad, pudiendo utilizar >,<,>=,<=.

Pero para poder trabajar con índices es necesario incluir en nuestro listado de namespaces dos nuevas clases, tal y como se muestra en el siguiente código:

  1. <?php
  2.  
  3. use phpcassa\Connection\ConnectionPool;
  4. use phpcassa\ColumnFamily;
  5. use phpcassa\SuperColumnFamily;
  6. use phpcassa\ColumnSlice;
  7. use phpcassa\SystemManager;
  8. use phpcassa\Schema\StrategyClass;
  9. use phpcassa\Index\IndexExpression;
  10. use phpcassa\Index\IndexClause;

A continuación creamos el método que generará la consulta con los índices secundarios.

 

  1. <?php
  2.  
  3. public function obtenerPorIndices($name_columnFamily, $arrayColumnsValues, $range_start = "", $range_end = '', $column_count = 100, $invertir_orden = false){
  4.  
  5. try{
  6. // Creamos el objeto
  7. $column_family = new ColumnFamily($this->conexion, $name_columnFamily);
  8.  
  9. // Inicializamos las variables
  10. $index_exp = array();
  11. $registros = array();
  12.  
  13. // Creamos un array de index_expression
  14. foreach($arrayColumnsValues as $key => $value){
  15. if (array_key_exists('operator', $value)){
  16. $op = $this->getIndexOperator($value['operator']);
  17. }
  18. else{
  19. $this->getIndexOperator('=');
  20. }
  21.  
  22. $column = $value['values'];
  23. $key_column = key($column);
  24.  
  25. $index_exp[] = new IndexExpression($key_column, $column[$key_column], $op);
  26. }
  27.  
  28. // Creamos la index_clause
  29. $index_clause = new IndexClause($index_exp, $range_start, $column_count);
  30.  
  31. // Creamos la column_slice
  32. $column_slice = new ColumnSlice($range_start, $range_end, $column_count, $invertir_orden);
  33.  
  34. // Recuperamos los registros
  35. $rows = $column_family->get_indexed_slices($index_clause, $column_slice);
  36.  
  37. foreach($rows as $key => $columns){
  38. if (!array_key_exists($key, $registros)){ $registros[$key] = null; }
  39. $registros[$key] = $columns;
  40. }
  41. return $registros;
  42. }catch (Exception $e){
  43. return false;
  44. }
  45. }

 

Con este método podremos buscar registros con varios índices secundarios.

Lo primero que hacemos en este método es crear el objeto ColumnFamily que nos proveerá de los métodos para hacer la consulta con indices secundarios. A continuación inicializamos varias variables necesarias para el método.

Dentro de un bucle creamos un array de IndexExpression(). Este objeto le indicará a Cassandra qué indices, con qué valores y qué operador se deben buscar los registros.

Seguidamente creamos la iIndexClause(), que nos permite indicarle la key desde la que comenzará a recuperar registros y el número de registros a obtener.

Por último recuperamos los registros utilizando el método get_indexed_slices().

Para probar el método vamos a crear datos de prueba en test.php y haremos la consulta:

 

  1. <?php
  2.  
  3. $data[] = array(
  4. 'title' => 'Apache Cassandra',
  5. 'license' => 'Open Source',
  6. 'category' => 'no-sql',
  7. );
  8.  
  9. $data[] = array(
  10. 'title' => 'MongoDB',
  11. 'license' => 'Open Source',
  12. 'category' => 'no-sql',
  13. );
  14.  
  15. $data[] = array(
  16. 'title' => 'MySQL',
  17. 'license' => 'Open Source',
  18. 'category' => 'sql',
  19. );
  20.  
  21. foreach($data as $key => $value){
  22. $cass->guardar('my_column_family_standard', $key, $value);
  23. }
  24.  
  25. $arrayColumnsValues[] = array(
  26. 'values' => array(
  27. 'category' => 'no-sql'
  28. ),
  29. 'operator' => '='
  30. );
  31.  
  32. $result = $cass->obtenerPorIndices('my_column_family_standard', $arrayColumnsValues);
  33.  
  34. print_r($result);

 

Si ejecutamos el código anterior Cassandra nos devolverá:

Array ( [0] => Array ( [title] => Apache Cassandra [license] => Open Source [category] => no-sql ) [1] => Array ( [title] => MongoDB [license] => Open Source [category] => no-sql ) )

[ci-box type=”warning”]Al utilizar un operador diferente al = puede que Cassandra te devuelva un error. Para evitarlo añade otro indice secundario a la consulta pero con el operador =, siendo este la primera columna que Cassandra procese. Por alguna razón Cassandra devuelve un error si no se hace así. [/ci-box]

Con este post concluye la parte básica de PHPCassa, Cassandra y Cassandra Cluster Admin. En el próximo post y siguientes trataré varios temas que se han quedado un poco colgados o faltan por explicar como ordenar registros, cómo crear claves, mejorar el rendimiento de Cassandra, crear clusters, etc.

 

Logo Cassandra

Cassandra y PHP para desarrolladores SQL: phpCassa (II)

0

En el anterior post traté las acciones habituales que realizamos con Cassandra: guardar, actualizar y eliminar. Sin embargo aun quedan dos acciones muy útiles por tratar: los contadores y los indices secundarios.

 

CONTADORES

Los contadores son en realidad un tipo especial de validador de Column Family.

 

CREAR UN CONTADOR 

Para crearla procedemos de la siguiente manera:

– Accedemos a Cassandra Cluster Admin:

Página principal de Cassandra Cluster Admin

– Entramos en el keyspace con el que estamos trabajando:

Detalle del keyspace my_keyspace

– Pulsamos en Create New Column Family y escribimos los siguientes datos:

Datos para crear una Column Family con contadores

– En Default Validation Class el texto completo a escribir es:

org.apache.cassandra.db.marshal.CounterColumnType

– Y pulsamos el botón Create Column Family.

Varias cosas sobre los CounterColumn:
– Para crear los CounterColumns es obligatorio indicar en Default Validation Class la clase de validador correcto. Indicado más arriba.
– Los contadores puedes tener números positivos o negativos.
– Los CounterColumns no son un sustituto de el autoincrement de las bases relacionales.

Ahora que ya está creada la Column Family es hora de programar.

 

GUARDAR Y/O ACTUALIZAR UN CONTADOR 

En nuestra clase en cassandra.php creamos el siguiente método:

  1. <?php
  2.  
  3. public function guardarContador($columnFamily, $key, $column, $value=1, $super_column=NULL){
  4.  
  5. try {
  6. $column_family = new ColumnFamily($this->conexion, $columnFamily);
  7. $column_family->add($row_key, $column, $value, $super_column);
  8. return true;
  9. }
  10. catch(Exception $e){
  11. return false;
  12. }
  13. }

Con este método podremos incrementar o disminuir el contador.


$columnFamily
: Es el nombre de la column family donde se encuentra el contador a modificar.

$key: Clave del registro donde se encuentra el contador.
$column: Nombre del contador.
$value: Valor a añadir al contador.
$super_column: Nombre de la super column donde se encuentra el contador.

Añadimos el siguiente código a nuestro archivo test.php:

  1. <?php
  2.  
  3. if ( $cass->guardarContador('column_family_counter', 'post', 'num_total_post', 1)){
  4. print "El contador se ha actualizado correctamente<br />";
  5. }else{
  6. print "Error al actualizar el contador<br />";
  7. }
  8.  
  9. $result = $cass->obtener('column_family_counter', 'post');
  10.  
  11. print_r($result);

Como ves, para recuperar un contador se utiliza el mismo método que para obtener cualquier otro registro. El resultado de este código sería:

El contador se ha actualizado correctamente
Array ( [num_total_post] => 1 )

 

PONER A CERO EL CONTADOR

Para poner a cero un contador hay que restarle el valor que tenga en ese momento el contador. En test.php escribiríamos lo siguiente:

  1. <?php
  2.  
  3. if ( $cass->guardarContador('column_family_counter', 'post', 'num_total_post', ($result['num_total_post']*-1))){
  4. print "El contador se ha actualizado correctamente<br />";
  5. }else{
  6. print "Error al actualizar el contador<br />";
  7. }
  8.  
  9. $result = $cass->obtener('column_family_counter', 'post');
  10.  
  11. print_r($result);

Y el resultado:

El contador se ha actualizado correctamente
Array ( [num_total_post] => 0 )

 

INDICES SECUNDARIOS

Los indices secundarios son un objeto especial en Cassandra que nos permite realizar búsquedas por columnas concretas.

Estos índices solo funcionan en las column family standard, con lo que su uso se ve bastante limitado.

 

 

CREAR UN INDICE SECUNDARIO

Para ello vamos a nuestro Cassandra Cluster Admin y en la column family my_column_family_standard pulsamos en Create Secondary Index:

Detalle de la ubicación del botón Create Secondary Index

Detalle de la ubicación del botón Create Secondary Index

– Nos aparecerá el siguiente formulario:

Detalle del formulario para crear un índice secundario

Detalle del formulario para crear un índice secundario

– Para nuestro cometido vamos a crear el siguiente índice secundario:

Formulario con los datos para el ejemplo

Formulario con los datos para el ejemplo

–  Pulsamos en Add Secondary Index.

 

REALIZAR UNA CONSULTA CON UN INDICE SECUNDARIO 

Nos vamos a nuestro archivo cassandra.php y añadimos el siguiente método:

  1. <?php
  2.  
  3. public function obtenerPorIndices($columnFamily, $arrayColumnsValues, $rangeStart = "", $columnCount = 100, $ordenar = true){
  4.  
  5. try{
  6. // Creamos el objeto
  7. $column_family = new ColumnFamily($this->conexion, $columnFamily);
  8.  
  9. // Inicializamos las variables
  10. $index_exp = array();
  11. $registros = array();
  12.  
  13. // Creamos un array de index_expression
  14. foreach($arrayColumnsValues as $key => $value){
  15. $index_exp[] = CassandraUtil::create_index_expression($key, $value);
  16. }
  17.  
  18. // Creamos la index_clause
  19. $index_clause = CassandraUtil::create_index_clause($index_exp, $rangeStart, $columnCount);
  20.  
  21. // Recuperamos los registros
  22. $rows = $column_family->get_indexed_slices($index_clause, NULL, $rangeStart, '', $ordenar, $columnCount);
  23.  
  24. return $rows;
  25. }catch (Exception $e){
  26. return false;
  27. }
  28. }

Con este método podremos buscar registros con varios índices secundarios.

Lo primero que hacemos en este método es crear el objeto ColumnFamily que nos proveerá de los métodos para hacer la consulta con indices secundarios. A continuación inicializamos varias variables necesarias para el método.

Dentro de un bucle creamos un array de index_expression(). Este objeto le indicará a Cassandra qué indices y con qué valores se deben buscar los registros.

Seguidamente creamos la index_clause(), que nos permite indicarle la key desde la que comenzará a recuperar registros y el número de registros a obtener.

Por último recuperamos los registros utilizando el método get_indexed_slices().

Para probar el método vamos a crear datos de prueba en test.php y haremos la consulta:

  1. <?php
  2.  
  3. $data[] = array(
  4. 'title' => 'Apache Cassandra',
  5. 'license' => 'Open Source',
  6. 'category' => 'no-sql',
  7. );
  8.  
  9. $data[] = array(
  10. 'title' => 'MongoDB',
  11. 'license' => 'Open Source',
  12. 'category' => 'no-sql',
  13. );
  14.  
  15. $data[] = array(
  16. 'title' => 'MySQL',
  17. 'license' => 'Open Source',
  18. 'category' => 'sql',
  19. );
  20.  
  21. foreach($data as $key => $value){
  22. $cass->guardar('my_column_family_standard', $key, $value);
  23. }
  24.  
  25. $arrayColumnsValues = array(
  26. 'category' => 'no-sql',
  27. );
  28.  
  29. $result = $cass->obtenerPorIndices('my_column_family_standard', $arrayColumnsValues);
  30.  
  31. print_r($result);

Si ejecutamos el código anterior Cassandra nos devolverá:

Array ( [0] => Array ( [title] => Apache Cassandra [license] => Open Source [category] => no-sql ) [1] => Array ( [title] => MongoDB [license] => Open Source [category] => no-sql ) )

Con este post concluye la parte básica de phpCassa, Cassandra y Cassandra Cluster Admin. En el próximo post y siguientes trataré varios temas que se han quedado un poco colgados o faltan por explicar como ordenar registros, cómo crear claves, mejorar el rendimiento de Cassandra, crear clusters, etc.

 

Ir arriba