1. Code
  2. WordPress
  3. Plugin Development

Usando Namespace y Autoloading en Plugins WordPress, Parte 1

Scroll to top
This post is part of a series called Using Namespaces and Autoloading in WordPress Plugins.
Using Namespaces and Autoloading in WordPress Plugins, Part 2

Spanish (Español) translation by Rodney Martinez (you can also view the original English article)

Namespaces y autoloading no son temas que, por lo general, discutimos a la hora de trabajar con los plugins de WordPress.

Algunos de estos tienen que ver con la comunidad que está alrededor de éste, algunos de ellos tienen que ver con las versiones de PHP que WordPress que tienen soporte para PHP y algunos de éstos, simplemente tienen que ver con el hecho de que no muchas personas están hablando al respecto. 

Y eso está bien para una medida.

Ni namespaces ni autoloading son temas que usted necesita usar para crear plugins. Sin embargo, pueden proporcionar una mejor forma de organizar y estructurar su código así como también reducir el número de declaraciones require, require_once, include o include_once que usa su plugin.

En estas series, vamos a echar un vistazo a lo que son exactamente los namespaces PHP y, por qué son ventajosos y cómo podemos usarlos. Luego, vamos a echar un vistazo a cómo usar autoloaders para cargar de manera automática los archivos que necesitamos sin tener que cargarlos manualmente en nuestro código.

Antes de comenzar

Para comenzar, usted va a necesitar las siguientes herramientas:

  • Un ambiente de desarrollo local que incluye PHP 5.6.20, el servidor web Apache y un servidor de bases de datos MySQL.
  • Un directorio de lo que WordPress 4.6 está siendo alojado.
  • Un editor de texto o IDE de su elección, es decir, uno con el cual usted se sienta cómodo para escribir su plugin.
  • Un conocimiento práctico de la API de Plugins de WordPress.

Una vez que tenga todo en orden, empecemos a construir nuestro un plugin. Note que si algunas de las cosas que mencionamos anteriormente le parecen nuevas, entonces no dude en revisar cualquiera de los tutoriales anteriores en mí página de perfil.

Asimismo, puede seguirme en mi blog y/o Twitter en @tommcfarlin, en donde hablo acerca del desarrollo de programas en el contexto de WordPress.

Con eso dicho, empecemos.

Que vamos a construir.

En esta serie, vamos a construir, sobre todo, un plugin para demostrar como namespaces y autoloading funcionan en PHP. Pero, para hacer eso, siempre es de ayuda aplicar los conceptos en una forma práctica.

Para tal fin, estaremos construyendo un plugin que hace más fácil cargar hojas de estilos y estilos de JavaScript en nuestro plugin, y que muestran un meta box que le indica al usuario con una pregunta para ayudarle a compartir ideas sobre que puede poner en un blog.

No, esto no es algo que usted enviaría al WordPress Plugin Repository, ni tampoco es algo que probablemente usaría fuera de esta demostración en particular. Pero recuerde, el propósito de esta serie es demostrar cómo funcionan namespaces y autoloading.

Y es a través de este ejemplo que vamos a hacer eso.

Construyendo el Plugin

Si ha seguido cualquiera de mis tutoriales anteriores, entonces usted conoce una de las cosas que me gusta hacer es; planificar lo que vamos a construir antes de empezar a escribir cualquier código. Por lo tanto, para la primera iteración de éste plugin, esto es lo que sabemos que necesitamos hacer:

  1. Definir un archivo bootstrap para empezar el plugin.
  2. Configurar un directorio para todos los archivos que reproducirá la meta box.
  3. Crear un directorio para alojar la clase que cargará nuestras dependencias.
  4. Prepare las hojas de estilo y JavaScript para nuestro plugin.

Parece sencillo, ¿cierto? Pero si no, no se preocupe. Lo voy a conducir a través del proceso completo con código, comentarios, capturas de pantalla y explicaciones.

Empecemos

Creando el Directorio Plugin

Desde el principio, sabemos que vamos a necesitar un archivo que sirve como el bootstrap para el plugin. También sabemos que vamos a necesitar un directorio para la funcionalidad administrativa.

Vamos a continuar y a crear eso ahora:

The plugins initial directory structureThe plugins initial directory structureThe plugins initial directory structure

Obviamente, tenemos un solo archivo vacío y un directorio de administración. Continuemos y ajustemos este plugin para que éste muestre dentro del contexto de la pantalla de activación del Plugin de WordPress.

Para hacer esto, necesitamos añadir el siguiente bloque de código a la parte superior del archivo plugin:

1
<?php
2
/**

3
 * The plugin bootstrap file

4
 *

5
 * This file is read by WordPress to generate the plugin information in the

6
 * plugin admin area. This file also includes all of the dependencies used by

7
 * the plugin, registers the activation and deactivation functions, and defines

8
 * a function that starts the plugin.

9
 *

10
 * @link              http://.tutsplus.com/tutorials/using-namespaces-and-autoloading-in-wordpress-plugins-part-1

11
 * @since             0.1.0

12
 * @package           tutsplus_namespace_demo

13
 *

14
 * @wordpress-plugin

15
 * Plugin Name:       Tuts+ Namespace Demo

16
 * Plugin URI:        http://.tutsplus.com/tutorials/using-namespaces-and-autoloading-in-wordpress-plugins-part-1

17
 * Description:       Learn how to use Namespaces and Autoloading in WordPress.

18
 * Version:           0.1.0

19
 * Author:            Tom McFarlin

20
 * Author URI:        https://tommcfarlin.com/

21
 * License:           GPL-2.0+

22
 * License URI:       http://www.gnu.org/licenses/gpl-2.0.txt

23
 */

Luego, cuando usted navegue por la Página del Plugin de WordPress en el área de administración, usted debería mostrarlo en su lista de plugins. Si usted opta por activarlo, nada ocurrirá ya que no hemos escrito ningún código.

The Tuts Namespace Demo plugin in the WordPress administration areaThe Tuts Namespace Demo plugin in the WordPress administration areaThe Tuts Namespace Demo plugin in the WordPress administration area

En este punto, podemos continuar y comenzar a definir la clase que reproducirá nuestra meta box en la página Add New Post [Añadir Nueva Publicación].

Añadiendo una Meta Box

Esta parte del tutorial asumirá que usted tiene muchos conocimientos en la creación de meta box. Si no, no dude en revisar los conceptos en esta serie y luego vuelva a está parte una vez que lo haya hecho.

Primero, vamos a crear una archivo llamado class-meta-box-display.php in el directorio principal admin de nuestro plugin. El código debería incluir lo siguiente. Asegúrese de revisar los comentarios para estar seguro de que entendió todo sobre lo que esta clase es responsable de hacer.

1
<?php
2
/**

3
 * Defines the functionality required to render the content within the Meta Box

4
 * to which this display belongs.

5
 */
6
7
/**

8
 * Defines the functionality required to render the content within the Meta Box

9
 * to which this display belongs.

10
 *

11
 * When the render method is called, the contents of the string it includes

12
 * or the file it includes to render within the meta box.

13
 */
14
class Meta_Box_Display {
15
16
    /**

17
     * Renders a single string in the context of the meta box to which this

18
     * Display belongs.

19
     */
20
    public function render() {
21
        echo 'This is the meta box.';
22
    }
23
}

Del código anterior, usted debería ser capaz de averiguar que esta clase será responsable de mostrar el contenido dentro de la meta box. Por ahora, sin embargo, simplemente tenemos el eco de la declaración para la vista.

Cambiaremos esto después en el tutorial.

Luego, necesitamos introducir una clase que represente la meta box. Así que cree un archivo class-meta-box.php en el directorio admin de nuestro plugin. Aquí está el código para hacer exactamente eso. Otra vez, revise el código y luego le explicaré lo que está pasando en la siguiente clase:

1
<?php
2
/**

3
 * Represents a meta box to be displayed within the 'Add New Post' page.

4
 */
5
6
/**

7
 * Represents a meta box to be displayed within the 'Add New Post' page.

8
 *

9
 * The class maintains a reference to a display object responsible for

10
 * displaying whatever content is rendered within the display.

11
 */
12
class Meta_Box {
13
14
    /**

15
     * A reference to the Meta Box Display.

16
     *

17
     * @access private

18
     * @var    Meta_Box_Display

19
     */
20
    private $display;
21
22
    /**

23
     * Initializes this class by setting its display property equal to that of

24
     * the incoming object.

25
     *

26
     * @param Meta_Box_Display $display Displays the contents of this meta box.

27
     */
28
    public function __construct( $display ) {
29
        $this->display = $display;
30
    }
31
32
    /**

33
     * Registers this meta box with WordPress.

34
     *

35
     * Defines a meta box that will render inspirational questions at the top

36
     * of the sidebar of the 'Add New Post' page in order to help prompt

37
     * bloggers with something to write about when they begin drafting a post.

38
     */
39
    public function init() {
40
41
        add_meta_box(
42
            'tutsplus-post-questions',
43
            'Inspiration Questions',
44
            array( $this->display, 'render' ),
45
            'post',
46
            'side',
47
            'high'
48
        );
49
    }
50
}

Esta clase tiene un único atributo que es una referencia a su pantalla. Esto significa que su clase es responsable por definir la meta box (la cual, a su vez, llama al objeto pantalla para reproducir el mensaje).

La pantalla se mantiene como una propiedad privada fijada en el constructor. La meta box, de hecho, no está definida hasta que le método init es llamado (el cual lo veremos en el plugin de bootstrap más tardes en éste tutorial).

En este punto, tenemos todo lo que necesitamos para mostrar meta box elemental sobre la Add New Post Page [Añadir Nueva Página de Publicación]. Pero primero, necesitamos configurar el bootstrap del plugin.

En tutoriales anteriores, he hecho esto bastante, por lo que voy a incluir sólo el código que eso requiere (ya que he definido el encabezado arriba). He añadido comentarios, pero también, me aseguraré de explicar que está pasando después del código.

Esto es especificamente relevante porque nuestro autoloader, eventualmente, negará la necesidad de algo de lo que vamos ver. 

1
<?php
2
3
// If this file is accessed directory, then abort.

4
if ( ! defined( 'WPINC' ) ) {
5
    die;
6
}
7
8
// Include the files for rendering the display.

9
include_once( 'admin/class-meta-box.php' );
10
include_once( 'admin/class-meta-box-display.php' );
11
12
add_action( 'plugins_loaded', 'tutsplus_namespace_demo' );
13
/**

14
 * Starts the plugin by initializing the meta box, its display, and then

15
 * sets the plugin in motion.

16
 */
17
function tutsplus_namespace_demo() {
18
19
  $meta_box = new Meta_Box( new Meta_Box_Display() );
20
	$meta_box->init();
21
}

Primero, nos aseguraremos de que este archivo no puede tener acceso directo y solamente puede ser ejecutado por el mismo WordPress.

Después, incluimos las clases include_once que hemos creado hasta ahora. Luego, instanciamos la Meta_Box y pasamos una instancia del Meta_Box_Display en su constructor.

Finalmente, llamamos al método init que reside en la clase Meta_Box.

Suponiendo que todo va bien, deberíamos de ser capaces de activar el plugin y ver la meta box en una página Add New Post [Añadir Nueva Publicación] (o, realmente, también en una página Actualizada de una Publicación).

Our Meta Box appearing on the New Post Edit Post pageOur Meta Box appearing on the New Post Edit Post pageOur Meta Box appearing on the New Post Edit Post page

En este punto, tenemos funcionando un plugin, pero en realidad no hace otra cosa que crear un meta box y mostrar una cadena de texto.

Vamos, al menos, mostrar alguna cita inspiradora y mostrar una aleatoria cada vez que la página es cargada.

Mostrando las Citas Inspiradoras

Primero, necesitamos encontrar un archivo de texto de citas de inspiración. Por fortuna, el Internet ofrece un sin fin de estas que podemos usar en nuestro proyecto (y que están disponibles de forma gratuita). Para tal fin he creado una subdirectorio data en admin que estoy usando para alojar mi archivo questions.txt

The questionstxt file in the data subdirectoryThe questionstxt file in the data subdirectoryThe questionstxt file in the data subdirectory

Después, vamos a necesitar crear una que:

  1. Abrirá un archiv.
  2. Leerá una línea aleatoria en una cadena.
  3. Cerrará el archivo.
  4. Regresará la cadena a quien la llamo.

Vamos a continuar y a crear esa clase, ahora. Ya que esto es una clase pública y va a ser utilizada en el lado administrativo del plugin, vamos a crear un subdirectorio util en admin. Después, vamos a crear un archivo llamado class-questions-reader.php

Especificaremos el código para esta clase en un momento, pero devolveremos el archivo boostrap del plugin y recuerde incluir el archivo. El resultado del código debería de lucir así:

1
<?php
2
3
// Include the files for rendering the display.

4
include_once( 'admin/class-meta-box.php' );
5
include_once( 'admin/class-meta-box-display.php' );
6
include_once( 'admin/util/class-question-reader.php' );

Como puede ver, el número de archivos que estamos trabajando para incluir de forma manual está haciéndose más largo. ¡Imagine si fueramos a trabajar un plugin más grande! Sin embargo, regresaremos a esto después en la serie.

Por ahora, vamos a cambiar nuestra atención de vuelta a la pregunta del lector. El código para la clase debería de lucir así:

1
<?php
2
/**

3
* Reads the contents of a specified file and returns a random line from the

4
* file.

5
*/
6
7
/**

8
* Reads the contents of a specified file and returns a random line from the

9
* file.

10
*

11
* This class is used to populate the contents of the meta box with questions

12
* that prompt the user for ideas about which to write.

13
*

14
* Note this class is only for demo purposes. It has no error handling and

15
* assumes the specified file always exists.

16
*/
17
class Question_Reader {
18
19
  /**

20
   * Retrieves a question from the specified file.

21
   *

22
   * @param  string $filename  The path to the file that contains the question.

23
   * @return string $question A single question from the specified file.

24
   */
25
  public function get_question_from_file( $filename ) {
26
27
      $question = '';
28
29
      $file_handle = $this->open( $filename );
30
      $question    = $this->get_random_question( $file_handle, $filename );
31
32
      $this->close( $file_handle );
33
34
      return $question;
35
  }
36
37
  /**

38
   * Opens the file for reading and returns the resource to the file.

39
   *

40
   * @access private

41
   * @param  string $filename  The path to the file that contains the question.

42
   * @return resource          A resource to the file.

43
   */
44
   private function open( $filename ) {
45
      return fopen( $filename, 'r' );
46
   }
47
48
   /**

49
    * Closes the file that was read.

50
    *

51
    * @access private

52
    * @param  string $file_handle The resource to the file that was read.

53
    */
54
   private function close( $file_handle ) {
55
      fclose( $file_handle );
56
   }
57
58
   /**

59
    * Opens the file for reading and returns the resource to the file.

60
    *

61
    * @access private

62
    * @param  string $file_handle The resource to the file that was read.

63
    * @param  string $filename    The path to the file containing the question.

64
    * @return string $question    The question to display in the meta box.

65
    */
66
   private function get_random_question( $file_handle, $filename ) {
67
68
      $questions = fread( $file_handle, filesize( $filename ) );
69
      $questions = explode( "\n", $questions );
70
71
      // Look for a question until an empty string is no longer returned.

72
      $question = $questions[ rand( 0, 75 ) ];
73
      while ( empty( $question ) ) {
74
         $question = $questions[ rand( 0, 75 ) ];
75
      }
76
77
      return $question;
78
    }
79
}

Observe que el código para esto es relativamente sencillo, pero si usted no se está familiarizado con algo de las operaciones básicas del archivo en PHP, entonces esto es lo que vamos hacer:

  1. Vamos abrir el archivo usando fopen, el cual nos concede un recurso para leer el archivo.
  2. Después, vamos a leer los contenidos del archivo y entonces tomaremos cada línea del archivo y escribirlo en un índice de un conjunto.
  3. Después de eso, escogeremos un número al azar del conjunto de preguntas y lo devolveremos al método que está llamándolo. Si éste devuelve una cadena vacía, lo haremos de nuevo hasta que una pregunta sea localizada.
  4. Luego, cerramos el recurso para el archivo.

Finalmente, para usar esta clase, usted simplemente necesita instanciarla, conocer la ruta completa hacia el archivo de preguntas y luego llamar al método get_question_from_file.

Nota: Esta clase no maneja ningún error. Esa es una práctica estándar cuando está trabajando con estos archivos. Por ejemplo, ¿qué deberíamos hacer si el archivo no existe? ¿Qué deberíamos hacer si no está formateado correctamente o que tal si nos equivocamos al cerrar el medio?

Todas son buenas preguntas, pero están fuera del alcance de este tutorial. Toda esta información puede ser encontrada en el manual de PHP (y quizás, en otros tutoriales a través de la red Envato Tuts+).

Por ahora, estamos preocupados con leer un archivo que sabemos que existe, y estamos interesados con mostrar el resultado en una meta box.

Que tenemos hasta ahora.

En este punto podemos comenzar a juntar todo. Asumiendo que hemos hecho todo correctamente, deberíamos de ser capaces de pasar una instancia del Question_Reader al Meta_Box_Display, hacer una pregunta, y luego mostrarla en la meta box.

Primero, vamos a actualizar el archivo bootstrap.

1
<?php
2
3
function tutsplus_namespace_demo() {
4
5
    $meta_box = new Meta_Box(
6
		new Meta_Box_Display(
7
			new Question_Reader()
8
		)
9
	);
10
11
	$meta_box->init();
12
}

En el código anterior, observe que el Meta_Box_Display ahora acepta una instancia de la pregunta del lector en su constructor. Esto implica que necesitaremos introducir una nueva propiedad, lo cual, haremos ahora:

1
<?php
2
/**

3
 * Defines the functionality required to render the content within the Meta Box

4
 * to which this display belongs.

5
 */
6
7
/**

8
 * Defines the functionality required to render the content within the Meta Box

9
 * to which this display belongs.

10
 *

11
 * When the render method is called, the contents of the string it includes

12
 * or the file it includes to render within the meta box.

13
 */
14
class Meta_Box_Display {
15
16
        /**

17
	 * A reference to the object responsible for retrieving a question to display.

18
	 *

19
	 * @access private

20
	 * @var    Question_Reader $question_reader

21
	 */
22
	private $question_reader;
23
24
	/**

25
	 * Initializes the class by setting the question reader property.

26
	 *

27
	 * @param Question_Reader $question_reader The object for retrieving a question.

28
	 */
29
	public function __construct( $question_reader ) {
30
		$this->question_reader = $question_reader;
31
	}
32
33
	/**

34
	 * Renders a single string in the context of the meta box to which this

35
	 * Display belongs.

36
	 */
37
	public function render() {
38
39
		$file = dirname( __FILE__ ) . '/data/questions.txt';
40
		$question = $this->question_reader->get_question_from_file( $file );
41
42
		echo wp_kses( $question );
43
	}
44
}

Observe que este archivo usa la ruta para las preguntas que el archivo añadió al subdirectorio de datos. Aparte de la ruta que ha sido codificada, esta clase es, además, dependiente de una instancia del Question_Reader.

Para el propósito de la demostración para la que estamos trabajando (a saber, namespaces y autoloading) está bien. En un futuro proyecto, nos gustaría que los proyectos tengan menos cantidad de acoplamiento entre ellos. Quizá esto será un tema para un futuro tutorial.

El principal aporte del código anterior, es que la clase Meta_Box_Display puede mostrar una pregunta para el usuario.

Asimismo, observe el uso de wp_kses en favor de la comprobación de los datos antes de presentarlos al usuario.

Al actualizar la página Add New Post [Añadir Nueva Publicación] debería presentarse con una imagen como esta:

Random questions appearing in a meta boxRandom questions appearing in a meta boxRandom questions appearing in a meta box

Y si actualiza la página después, usted puede ver que la nueva pregunta está siendo cargada.

¿A dónde vamos desde aquí?

Obviamente, todavía no hemos abordado los temas de namespaces y autoloading, pero está bien. Es importante que coloquemos la base para un plugin que no usamos. De esa forma, cuando lo implementemos, podemos ver los beneficios que tiene.

Por lo tanto, aún tenemos trabajo adicional que hacer: Necesitamos introducir JavaScript y CSS y algunos recursos. Esto nos permitirá tener, incluso, un imagen más amplia de cómo empacar nuestros archivos en namespaces es favorable.

Recuerde que puede encontrar todos mis tutoriales anteriores en mi página de perfil y, también, puede seguirme en mi blog o en Twitter.

Como siempre, si usted está buscando otros servicios que le ayuden a construir su creciente conjunto de herramientas de WordPress o por ejemplo código para estudiarlo y convertirse en un conocedor de WordPress, entonces no olvide ver lo que tenemos disponible en Envato Market.

Con eso dicho, tendremos una versión trabajando del plugin listo para descargarlo empezando en el próximo tutorial en esta serie. Si a usted le gustaría usar el código del tutorial anterior, no dude en intentar hacerlo. Por lo tanto, siéntase libre de hacerme cualquier pregunta en los comentarios.

Recursos