Entradas etiquetadas con tutorial

Cassandra 2.x y PHP para desarrolladores SQL: El modelo de datos
0Si has trabajado con una base de datos relacional tal vez te resulte algo confuso al principio comprender el modelo de datos que usa Cassandra, intentaré ser lo más claro posible, pero si te surgen preguntas no dudes en dejarlas en los comentarios.
Columns
El elemento más básico de la base de datos Cassandra es la columna, se compone de tres elementos: nombre de la columna, valor y timestamp. Os muestro un ejemplo como un array:
array( "nombre" => "email", "valor" => "webmaster@localhost.com", "timestamp" => time(), );
Cassandra añade el timestamp automáticamente, con lo que otra forma de representarlo es como un conjunto clave:valor:
nombre_columna:valor
Super columnas (En desuso) y Columnas Compuestas
Las super columnas son un conjunto de columnas con sus correspondientes valores:
array( "nombre_superColumna" => array( "usuario1" => array( "nombre" => "email", "valor" => "webmaster@localhost.com", "timestamp" => time() ), "usuario2" => array( "nombre" => "email", "valor" => "email@email.com", "timestamp" => time() ), "usuario3" => array( "nombre" => "email", "valor" => "otroemail@otroemail.com", "timestamp" => time() ), ), )
Las super columnas tienen algunos problemas de rendimiento, sobre todo al ordenarlas. Para solucionarlo se crearon las columnas compuestas que se benefician de los comparadores compuestos, y sobretodo, de CQL 3 (Cassandra Query Language).
Familia de columnas
Es el conjunto de columnas o super columnas. Me explico:
Las column Family o familia de columnas se puede configurar de dos maneras: como Super o como Standard. Si se elige la opción Standard, en la column family solo se podrán guardar columnas, no super columnas. En cambio si la column family está configurada como Super podrá guardar, además de las columnas, las super columnas. Esta flexibilidad permite jugar con la base de datos y adaptarla a nuestras necesidades.
Ejemplo:
array( "name" => "ColumnFamily", array( "name" => "SuperColumn", array( "colums" ) ), )
Keyspace
El keyspace es nuestra base de datos, donde alojaremos todas las columFamilies que necesitemos.
Ejemplo:
array( "name" => "keyspace", array("name" => "columnFamily", array( [...] ), ), )

Cassandra 2.x y PHP para desarrolladores SQL: Instalación
0La base de datos No-SQL Cassandra fue creada por Facebook a causa de la necesidad de disponer de una base de datos distribuida de alto rendimiento, flexible, tolerante a fallos, escalable y que fuese capaz de procesar grandes cantidades de datos. Más tarde fue liberada bajo licencia Apache y actualmente es utilizada principalmente por empresas de internet con proyectos con un alto uso de base de datos como Twitter.
En esta serie de artículos iré desgranando la instalación, funcionamiento y desarrollo de aplicaciones en PHP con Cassandra, comparando las sentencias utilizadas para insertar, actualizar, etc de SQL con los métodos a utilizar en Cassandra. Por desgracia al ser algo completamente distinto a cualquier base de datos SQL tendré que añadir algo de teoría, pero intentaré que os resulte lo más ameno posible.
Al toro.
REQUISITOS
Para la realización de esta guía se utilizará Debian 8 Jessie como sistema operativo.
Doy por hecho que ya se dispone de un servidor web Apache con PHP instalado en la máquina de testeo que se esté usando. Las aplicaciones que se van a instalar han sido probadas en una máquina virtual Debian 8 Jessie utilizando como aplicación de virtualización VirtualBox, instalado en un host Debian 8 Jessie.
En un servidor de producción recomiendo que tenga bastante RAM (por encima de 1GB, ya veremos más adelante el porqué. En la máquina virtual que uso de testeo dispone de 700 MB y funciona bien, pero en producción no es lo recomendable).
Instalaremos la base de datos Cassandra y PHP-Driver que nos dará la extensión para PHP y una abstracción de la base de datos donde tenemos los métodos básicos para trabajar con Cassandra: insertar, actualizar, borrar, crear, etc.
PREPARANDO EL SISTEMA
Antes de empezar a instalar debemos actualizar el sistema operativo de la forma habitual:
apt-get update apt-get upgrade
Una vez actualizado el sistema empezamos a instalar.
INSTALANDO CASSANDRA
Lo primero que necesitamos hacer para instalar Cassandra es editar los repositorios de Debian:
nano /etc/apt/sources.list
Una vez que se abra el editor añadimos las siguientes lineas:
deb http://www.apache.org/dist/cassandra/debian/ 21x main deb-src http://www.apache.org/dist/cassandra/debian/ 21x main
Como podrás observar después de la ruta del repositorio se ha añadido «21x» esto indica el número de versión a obtener, en este caso es la versión actual de cassandra al crear este post. No se indica el número de parche, es decir, actualmente se puede descargar Cassandra 2.1.
Si dentro de unos meses sale la versión «2.2» solo tendrás que cambiar el uno por el dos.
Volvemos a consola y actualizamos los repositorios.
apt-get update
Nos dará un error en las claves gpg. Procedemos a actualizarlas con las siguientes instrucciones:
gpg --keyserver pgp.mit.edu --recv-keys F758CE318D77295D gpg --export --armor F758CE318D77295D | sudo apt-key add -
Ojo con el guión del final, hay que añadirlo, sino dará error.
Con el paquete 0.7.5 nos da otro error de clave gpg así que también instalamos esta de la misma manera:
gpg --keyserver pgp.mit.edu --recv-keys 2B5C1B00 gpg --export --armor 2B5C1B00 | sudo apt-key add -
También necesitarás añadir la siguiente clave:
gpg --keyserver pgp.mit.edu --recv-keys 0353B12C gpg --export --armor 0353B12C | sudo apt-key add -
Verificamos que tenemos el sistema actualizado.
apt-get update apt-get upgrade
Actualizamos todos los paquetes que aparezcan.
Procedemos a instalar el paquete de la base de datos NoSQL Cassandra:
apt-get install cassandra
Cassandra necesita Java para funcionar. Debian 8 ya dispone de OpenJDK en su versión 7, y aunque desde los desarrolladores de Cassandra no recomiendan su uso, para los ejemplos que vamos a desarrollar nos sirve.
En producción, o si vas a desarrollar un proyecto con Cassandra tendrás que instalar la última versión de Java de Oracle.
Por último, ejecutamos el siguiente comando para construir las dependencias:
dpkg-buildpackage -uc -us
Si el sistema no te reconoce el comando es porque te falta el paquete dpkg-dev. Instálalo de la forma habitual, y vuelve a intentarlo:
apt-get install dpkg-dev
INSTALANDO DATASTAX PHP-DRIVER PARA CASSANDRA
Datastax PHP driver, es el controlador y abstracción de base de datos que utilizaremos para conectar con Cassandra desde PHP. Este controlador nos da la posibilidad de trabajar tanto con CQL (Cassandra Query Language. Parecido a SQL) y/o el protocolo binario de Cassandra.
Aunque en la página del repositorio nos indican varias formas de instalar el controlador (https://github.com/datastax/php-driver/blob/master/ext/README.md), el único que me ha funcionado correctamente ha sido el de descargar las fuentes y compilarlo. Tú puedes probar los otros métodos, pero el que te voy a indicar funciona en Debian 8.
Las siguientes instrucciones deberías ejecutarlas en el ordenador de desarrollo y no en el servidor o máquina virtual donde tengas instalada la base de datos. (A no ser que la hayas instalado en el ordenador de desarrollo).
Instalamos algunos paquetes necesarios para realizar la compilación:
apt-get install g++ make cmake libuv-dev libssl-dev libgmp-dev php5 php5-dev openssl libpcre3-dev git
Primero necesitamos descargar las fuentes desde GitHub, utiliza el directorio que prefieras:
git clone https://github.com/datastax/php-driver.git cd php-driver git submodule update --init cd ext ./install.sh
Estos comandos nos ha creado un archivo llamado cassandra.so en /usr/lib/php5/20131226/ (el número del directorio puede variar en tu instalación. Revísalo).
Ahora creamos un archivo .ini para la extensión de PHP:
nano /etc/php5/mods-available/cassandra.ini
Dentro de ese archivo añadimos las siguientes líneas:
; configuration for PHP driver Cassandra extension=cassandra.so
Guardamos.
Le indicamos a PHP que nos active la extensión
php5enmod cassandra
Y reiniciamos Apache:
/etc/init.d/apache2 restart
Ahora si ejecutamos el siguiente comando para mostrar los módulos de PHP debería aparecernos Cassandra, si no es así es que algo a fallado:
php -m
INICIANDO CASSANDRA POR PRIMERA VEZ
Ahora que ya tenemos todo instalado es el momento de arrancar Cassandra. Esto es algo muy sencillo, solo tienes que ejecutar el siguiente comando:
cassandra -f
También tienes otras maneras de iniciar Cassandra. Por ejemplo como servicio:
service cassandra start
Si al iniciar Cassandra te da un error de memoria, haz lo siguiente:
Accede a /etc/cassandra y edita el archivo cassandra-env.sh:
cd /etc/cassandra nano cassandra-env.sh
Busca las siguientes dos líneas:
#MAX_HEAP_SIZE="4G" #HEAP_NEWSIZE="800M"
Descomenta las dos líneas, y sustituye los valores por unos más bajos. En mi caso he bajado MAX_HEAP_SIZE a 2G y HEAP_NEWSIZE lo he dejado como está.
Estas dos líneas permiten configurar la cantidad de memoria RAM que Cassandra utilizará.
Ahora vamos a utilizar el código de ejemplo que hay en el repositorio de PHP-Driver para probar que todo funciona correctamente.
Crea un archivo PHP con el siguiente contenido:
- <?php
- $cluster = Cassandra::cluster() // connects to localhost by default
- ->build();
- $keyspace = 'system';
- $session = $cluster->connect($keyspace); // create session, optionally scoped to a keyspace
- $statement = new Cassandra\SimpleStatement( // also supports prepared and batch statements
- 'SELECT keyspace_name, columnfamily_name FROM schema_columnfamilies'
- );
- $future = $session->executeAsync($statement); // fully asynchronous and easy parallel execution
- $result = $future->get(); // wait for the result, with an optional timeout
-
- foreach ($result as $row) { // results and rows implement Iterator, Countable and ArrayAccess
- printf("The keyspace %s has a table called %s\n", $row['keyspace_name'], $row['columnfamily_name']);
- }
Este código devuelve las tablas que contiene el Keyspace «system» (Más adelante explicaré que es eso). Si te da error como este: «No hosts available for the control connection», puede ser por dos razones, o bien no está funcionando Cassandra, con lo que tendrás que iniciarla con uno de los comandos anteriores, o bien no la tienes en localhost sino en un servidor externo o máquina virtual.
Para resolverlo tendrás que sustituir las siguientes líneas:
- <?php
- $cluster = Cassandra::cluster() // connects to localhost by default
- ->build();
Por estas otras:
- <?php
- $cluster = Cassandra::cluster()
- ->withContactPoints('127.0.0.1')
- ->build();
Sí, solo añadimos «->withContactPoints(‘127.0.0.1’)», con este método le estamos indicando la ip de nuestro servidor. En tu caso es posible que tengas que sustituir «127.0.0.1» por la ip de tu servidor o máquina virtual. Más adelante explicaré cada método, pero para verificar que está funcionando todo correctamente es suficiente.
Con esto finalizamos la instalación de Cassandra para que pueda ser utilizada por PHP.
Cómo crear un servidor REST en PHP
0Un servidor REST es una aplicación que nos permite crear, actualizar, eliminar y recuperar datos de forma remota siguiendo el estandar de diseño REST. Lo habitual cuando programamos, por ejemplo peticiones ajax, es nombrar las urls como «/obtenerProducto», «/crearProducto», etc. En REST los verbos «obtener» o «crear» no se usan, ya que se utiliza una única url para todas las acciones, en nuestro ejemplo «/producto». Además, REST nombra a estas urls como recursos.
Para poder diferenciar la acción que se está realizando sobre un recurso concreto se utiliza un método u otro en la petición: GET, POST, PUT o DELETE.

Cómo remplazar el cron de WordPress con un cron job real
0Es posible que alguna vez hayas programado un post para ser publicado en un momento del día concreto y cuando has entrado a tu blog has visto como el post aun no se había publicado. Esto es algo que puede ocurrir de forma habitual, y puede resultar muy frustrante, además de perder una oportunidad de obtener las visitas que se esperaba tener al programar la publicación del post a una hora concreta.
Para comprender por qué ocurre, necesitamos saber que el WP-Cron no es un cron job real. De hecho es un cron virtual que solo se ejecuta cuando una página se carga (por ejemplo cuando accede un usuario al blog o a una página o post). Esta forma de ejecutar el cron virtual tiene un problema de rendimiento si tienes muchos eventos que ejecutar, o tardan demasiado en terminar.
Continue reading “Cómo remplazar el cron de WordPress con un cron job real” »

Discos duros en RAID en Debian
0Os dejo un tutorial muy interesante y que he utilizado para configurar varios discos duros en RAID 1:

WordPress 3.x para desarrolladores: Temas y plantillas, index.php y content.php
0Con 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().
- <div id="primary">
- <div id="content" role="main">
-
- <?php if ( have_posts() ) : ?>
-
- <?php newtheme_content_nav( 'nav-above' ); ?>
-
- <?php /* Start the Loop */ ?>
- <?php while ( have_posts() ) : the_post(); ?>
-
- <?php get_template_part( 'content', get_post_format() ); ?>
-
- <?php endwhile; ?>
-
- <?php newtheme_content_nav( 'nav-below' ); ?>
-
- <?php else : ?>
-
- <article id="post-0" class="post no-results not-found">
- <header class="entry-header">
- <h1 class="entry-title"><?php _e( 'Nothing Found', 'newtheme' ); ?></h1>
- </header><!-- .entry-header -->
-
- <div class="entry-content">
- <p><?php _e( 'Apologies, but no results were found for the requested archive. Perhaps searching will help find a related post.', 'newtheme' ); ?></p>
- </div><!-- .entry-content -->
- </article><!-- #post-0 -->
-
- <?php endif; ?>
-
- </div><!-- #content -->
- </div><!-- #primary -->
-
- <?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:
- <article id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
- <header class="entry-header">
- <?php if ( is_sticky() ) : ?>
- <hgroup>
- <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>
- <h3 class="entry-format"><?php _e( 'Featured', 'newtheme' ); ?></h3>
- </hgroup>
- <?php else : ?>
- <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>
- <?php endif; ?>
-
- <?php if ( 'post' == get_post_type() ) : ?>
- <div class="entry-meta">
- <?php newtheme_posted_on(); ?>
- </div><!-- .entry-meta -->
- <?php endif; ?>
-
- <?php if ( comments_open() && ! post_password_required() ) : ?>
- <div class="comments-link">
- <?php comments_popup_link( '<span class="leave-reply">' . __( 'Reply', 'newtheme' ) . '</span>', _x( '1', 'comments number', 'newtheme' ), _x( '%', 'comments number', 'newtheme' ) ); ?>
- </div>
- <?php endif; ?>
- </header><!-- .entry-header -->
-
- <?php if ( is_search() ) : // Only display Excerpts for Search ?>
- <div class="entry-summary">
- <?php the_excerpt(); ?>
- </div><!-- .entry-summary -->
- <?php else : ?>
- <div class="entry-content">
- <?php the_content( __( 'Continue reading <span class="meta-nav">→</span>', 'newtheme' ) ); ?>
- <?php wp_link_pages( array( 'before' => '<div class="page-link"><span>' . __( 'Pages:', 'newtheme' ) . '</span>', 'after' => '</div>' ) ); ?>
- </div><!-- .entry-content -->
- <?php endif; ?>
-
- <footer class="entry-meta">
- <?php $show_sep = false; ?>
- <?php if ( 'post' == get_post_type() ) : // Hide category and tag text for pages on Search ?>
- <?php
- /* translators: used between list items, there is a space after the comma */
- $categories_list = get_the_category_list( __( ', ', 'newtheme' ) );
- if ( $categories_list ):
- ?>
- <span class="cat-links">
- <?php printf( __( '<span class="%1$s">Posted in</span> %2$s', 'newtheme' ), 'entry-utility-prep entry-utility-prep-cat-links', $categories_list );
- $show_sep = true; ?>
- </span>
- <?php endif; // End if categories ?>
- <?php
- /* translators: used between list items, there is a space after the comma */
- $tags_list = get_the_tag_list( '', __( ', ', 'newtheme' ) );
- if ( $tags_list ):
- if ( $show_sep ) : ?>
- <span class="sep"> | </span>
- <?php endif; // End if $show_sep ?>
- <span class="tag-links">
- <?php printf( __( '<span class="%1$s">Tagged</span> %2$s', 'newtheme' ), 'entry-utility-prep entry-utility-prep-tag-links', $tags_list );
- $show_sep = true; ?>
- </span>
- <?php endif; // End if $tags_list ?>
- <?php endif; // End if 'post' == get_post_type() ?>
-
- <?php if ( comments_open() ) : ?>
- <?php if ( $show_sep ) : ?>
- <span class="sep"> | </span>
- <?php endif; // End if $show_sep ?>
- <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>
- <?php endif; // End if comments_open() ?>
-
- <?php edit_post_link( __( 'Edit', 'newtheme' ), '<span class="edit-link">', '</span>' ); ?>
- </footer><!-- #entry-meta -->
- </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:
- <?php if ( is_sticky() ) : ?>
- <hgroup>
- <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>
- <h3 class="entry-format"><?php _e( 'Featured', 'newtheme' ); ?></h3>
- </hgroup>
- <?php else : ?>
- <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>
- <?php endif; ?>
-
- <?php if ( 'post' == get_post_type() ) : ?>
- <div class="entry-meta">
- <?php newtheme_posted_on(); ?>
- </div><!-- .entry-meta -->
- <?php endif; ?>
-
- <?php if ( comments_open() && ! post_password_required() ) : ?>
- <div class="comments-link">
- <?php comments_popup_link( '<span class="leave-reply">' . __( 'Reply', 'newtheme' ) . '</span>', _x( '1', 'comments number', 'newtheme' ), _x( '%', 'comments number', 'newtheme' ) ); ?>
- </div>
- <?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.
- <?php if ( 'post' == get_post_type() ) : ?>
- <div class="entry-meta">
- <?php newtheme_posted_on(); ?>
- </div><!-- .entry-meta -->
- <?php endif; ?>
Este código genera el html correspondiente para las etiquetas meta de la página/post: fecha/hora, autor, descripción, etc.
- <?php if ( comments_open() && ! post_password_required() ) : ?>
- <div class="comments-link">
- <?php comments_popup_link( '<span class="leave-reply">' . __( 'Reply', 'newtheme' ) . '</span>', _x( '1', 'comments number', 'newtheme' ), _x( '%', 'comments number', 'newtheme' ) ); ?>
- </div>
- <?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.
- <?php if ( is_search() ) : // Only display Excerpts for Search ?>
- <div class="entry-summary">
- <?php the_excerpt(); ?>
- </div><!-- .entry-summary -->
- <?php else : ?>
- <div class="entry-content">
- <?php the_content( __( 'Continue reading <span class="meta-nav">→</span>', 'newtheme' ) ); ?>
- <?php wp_link_pages( array( 'before' => '<div class="page-link"><span>' . __( 'Pages:', 'newtheme' ) . '</span>', 'after' => '</div>' ) ); ?>
- </div><!-- .entry-content -->
- <?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.
- <footer class="entry-meta">
- <?php $show_sep = false; ?>
- <?php if ( 'post' == get_post_type() ) : // Hide category and tag text for pages on Search ?>
- <?php
- /* translators: used between list items, there is a space after the comma */
- $categories_list = get_the_category_list( __( ', ', 'newtheme' ) );
- if ( $categories_list ):
- ?>
- <span class="cat-links">
- <?php printf( __( '<span class="%1$s">Posted in</span> %2$s', 'newtheme' ), 'entry-utility-prep entry-utility-prep-cat-links', $categories_list );
- $show_sep = true; ?>
- </span>
- <?php endif; // End if categories ?>
- <?php
- /* translators: used between list items, there is a space after the comma */
- $tags_list = get_the_tag_list( '', __( ', ', 'newtheme' ) );
- if ( $tags_list ):
- if ( $show_sep ) : ?>
- <span class="sep"> | </span>
- <?php endif; // End if $show_sep ?>
- <span class="tag-links">
- <?php printf( __( '<span class="%1$s">Tagged</span> %2$s', 'newtheme' ), 'entry-utility-prep entry-utility-prep-tag-links', $tags_list );
- $show_sep = true; ?>
- </span>
- <?php endif; // End if $tags_list ?>
- <?php endif; // End if 'post' == get_post_type() ?>
-
- <?php if ( comments_open() ) : ?>
- <?php if ( $show_sep ) : ?>
- <span class="sep"> | </span>
- <?php endif; // End if $show_sep ?>
- <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>
- <?php endif; // End if comments_open() ?>
-
- <?php edit_post_link( __( 'Edit', 'newtheme' ), '<span class="edit-link">', '</span>' ); ?>
- </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.

WordPress 3.x para desarrolladores: Convenciones
0Aunque es un tema cuanto menos, aburrido, es muy necesario a la hora de trabajar en grupo, o si vas a publicar tu plugin o plantilla en WordPress. Las convenciones son normas aplicadas al código para que todos los desarrolladores puedan interpretar el código sin muchos problemas. También por estética: queda más elegante un código con la misma tabulación (por ejemplo) en cada linea que, que cada programador ponga la tabulación que se le antoje. Sin más preámbulos vamos al tema:
COMILLAS SIMPLES Y DOBLES
- <?php
-
- echo '<a href="/static/link" title="Yeah yeah!">Link name</a>';
- echo "<a href='$link' title='$linktitle'>$linkname</a>"
Si no tienes nada que evaluar en la cadena, pon comillas simples, sino comillas dobles.
SANGRÍA
Usa tabulaciones y no espacios.
- <?php
-
- [tab]$foo = 'somevalue';
- [tab]$foo2 = 'somevalue2';
- [tab]$foo34 = 'somevalue3';
- [tab]$foo5 = 'somevalue4';
Los arrays asociativos deberían empezar en una linea nueva.
- <?php
-
- [tab]'foo' => 'somevalue',
- [tab]'foo2' => 'somevalue2',
- [tab]'foo3' => 'somevalue3',
- [tab]'foo34' => 'somevalue3',
- );
LLAVES
En bloques multilinea se deben poner las llaves tal como sigue:
- <?php
-
- if ( condition ) {
- action1();
- action2();
- } elseif ( condition2 && condition3 ) {
- action3();
- action4();
- } else {
- defaultaction();
- }
Si solo hay una linea en cada bloque se pueden omitir por brevedad.
- <?php
-
- if ( condition )
- action1();
- elseif ( condition2 )
- action2();
- else
- action3();
Si hay un bloque con más de una linea se deberán escribir con llaves:
- <?php
-
- if ( condition ) {
- action1();
- } elseif ( condition2 ) {
- action2a();
- action2b();
- }
Los bucles deben contenerse siempre entre llaves:
- <?php
-
- foreach ( $items as $item ) {
- process_item( $item );
- }
NO UTILIZAR LA ETIQUETA DE INICIO CORTA DE PHP
La forma correcta sería:
<?php ... ?>
NO CERRAR EL SCRIPT DE PHP CON SU ETIQUETA
Es decir en vez de usar:
<?php ... ?>
Usaremos solo la inicial
<?php ...
USO DEL ESPACIO
Pon espacios siempre después de las comas y en ambos lados de los operadores lógicos, de comparación, de cadenas y de asignación.
x == 23 foo && bar ! foo array( 1, 2, 3 ) $baz . '-5' $term .= 'X'
Pon espacios a ambos lados de los paréntesis de apertura y cierre.
foreach ( $foo as $bar ) { ...
Cuando definas una función, hazlo así:
function my_function( $param1 = 'foo', $param2 = 'bar' ) { ...
Al realizar comparaciones lógicas:
if ( ! $foo ) { ...
Cuando hagas una conversión de tipos:
foreach ( (array) $foo as $bar ) { ... $foo = (boolean) $bar;
Cuando se hace referencia a un elemento de un array, solo se incluyen espacios en blanco cuando es una variable:
$x = $foo['bar'];$x = $foo[ $bar ];
FORMATEO DE SENTENCIAS SQL
Las partes de la sentencia que sean palabras de SQL deben ir en mayusculas, como SELECT o WHERE.
Es recomendable usar el método $wpdb->prepare() para formatear la sentencia SQL. Este método añadirá las comillas a los valores que lo necesiten.
$var = "dangerous'"; // Los datos en crudo podrían o no necesitar ser formateados $id = some_foo_number(); // El dato que nosotros esperamos es un número, pero no estamos seguros $wpdb->query( $wpdb->prepare( "UPDATE $wpdb->posts SET post_title = %s WHERE ID = %d", $var, $id ) );
%s se utiliza cuando el valor es una cadena (string) y %d cuando es un número. En el método prepare() se añaden las variables que se formatearán y añadirán a la consulta en orden.
CONVENCIONES DE NOMENCLATURAS
Usa letras minúsculas en variables y nombres de funciones. Separa las palabras con guiones bajos (_).
function some_name( $some_variable ) { [...] }
Los nombres de clases deben utilizar palabras capitalizadas separadas con guiones bajos. Las siglas deben estar en mayúsculas:
class Walker_Category extends Walker { [...] } class WP_HTTP { [...] }
Los archivos deben ser nombrados descriptivamente con letras minúsculas y las palabras deben separarse con guiones.
my-plugin-name.php
Los nombres de archivos de clase se basarán en el nombre de la clase precedido de class- y los guiones bajos de la clase serán sustituidos por guiones, por ejemplo WP_Error pasa a ser:
class-wp-error.php
VALORES DE PARÁMETROS DE FUNCIONES AUTOEXPLICATIVOS
Se prefieren valores de cadena que solo true y false cuando se llama a las funciones.
// Correcto function eat( $what, $speed = 'slowly' ) { ... } eat( 'mushrooms' ); eat( 'mushrooms', 'slowly' ); eat( 'dogfood', 'fast' );
OPERADOR TERNARIO
El operador ternario está bien, pero siempre que lo uses prueba que la sentencia sea verdad, no falsa. De la otra forma es confuso. En el caso de empty() se permite el uso de ! empty(), ya que es más legible.
// (si la sentencia es verdad) ? (hacer esto) : (sino, hacer esto); $musictype = ( 'jazz' == $music ) ? 'cool' : 'blah'; // (si el campo no está vacío ) ? (hacer esto) : (sino, hacer esto);
CONDICIONES YODA
if( true == $the_force ){ $victorious = you_will( $be ); }
Siempre que hagas comparaciones lógicas pon la variable en el lado derecho, la constante o el literal en el izquierdo.
Esto se utiliza para en el caso de que en vez de == pongas = (admítelo, más de una vez te habrá pasado), de esta manera saltará un error ya que no puedes asignar a una constante el valor de la variable.
Es un poco extraño, pero útil.
CÓDIGO LIMPIO
En general, la legibilidad es más importante que la limpieza o la brevedad.
isset( $var ) || $var = some_function();if ( ! isset( $var ) ) $var = some_function();

WordPress 3.x para desarrolladores: Introducción
0Después de varias semanas buscando información sobre WordPress para un proyecto que tenía pendiente (ya acabado), he observado que hay cierta escasez de información sobre el desarrollo de WordPress, ya que la mayoría de tutoriales o manuales que rondan por internet están limitados a la creación básica de plugins o a lo más básico de la creación de plantillas.
Por ello voy a realizar un tutorial que, basandome en el tema Twenty Eleven de WordPress permita conocer el funcionamiento de los temas y las plantillas. Para desarrollar la parte de los plugins se creará uno de ejemplo.
Muchos ejemplos de código serán de la documentación principal de WordPress y es la que deberías consultar más habitualmente si vas a desarrollar para WordPress: http://codex.wordpress.org/Main_Page
Durante las próximas semanas publicaré un tema por semana hasta que se complete el tutorial.