Spanish (Español) translation by Elías Nicolás (you can also view the original English article)
Cuando se trata de escribir plugins para WordPress, generalmente hay dos formas de hacerlo: Programación Orientada a Objetos y Programación Funcional (con los Widgets hay una excepción - lo veremos más tarde en el artículo).
Aunque por lo general hay gente que se inclina por un estilo de programación sobre el otro, cada uno tiene sus ventajas y desventajas.
En esta serie de dos partes Stephen Harris y yo vamos a desglosar las dos formas en que puedes escribir plugins para WordPress. Concretamente yo voy a hablar sobre la programación orientada a objetos y el lo hará sobre la programación funcional.
Ya que la experiencia de los lectores varía, no vamos a hablar sobre la programación a un nivel alto por lo que si eres principiante no deberías tener ningún problema para seguir adelante. Si sin embargo eres un desarrollador más experimentado, entonces encontrarás más información útil después en este artículo.
Dicho esto comencemos a ver el enfoque orientado a objetos para desarrollar plugin WordPress.
Desarrollo de Widgets WordPress
Como he mencionado en la introducción, los plugins se pueden desarrollar para WordPress de dos formas:
- 1. Programación Orientada a Objetos.2. Programación Funcional.
- Programación Funcional
El segundo artículo de esta serie cubrirá la Programación Funcional por lo tanto vamos a dar una definición de la programación orientada a objetos de modo que todos estemos al mismo nivel en este artículo.
La programación orientada a objetos (POO) es un paradigma de programación que usa "objetos" - generalmente instancias de una clase - que consisten en campos de datos y métodos junto con sus interacciones - para diseñar aplicaciones y programas de ordenador.
Aquellos que tienen más experiencia con la programación de computadoras, especialmente aquellos que usan técnicas de programación orientadas a objetos, probablemente prefieran esa definición.
Pero vamos a simplificarlo para los propósitos de este artículo:
La programación orientada a objetos es una técnica que usa una colección de métodos relacionados para definir un programa de ordenador o parte de un programa de ordenador.
Bastante claro ¿verdad? En nuestro caso nuestros plugins son parte de un programa de ordenador desde que están incluidos en WordPress.
Aunque veremos código durante el resto de este artículo date cuenta de que los programas orientados a objetos se identifican por el grupo de sus métodos relacionados y esto se hace dentro del contexto de lo que se llama una clase - que lo veremos en seguida.
Una Palabra Sobre los Widgets
Aunque es cierto que los plugins de WordPress se pueden desarrollar utilizando POO o programación funcional, hay una excepción en cuanto al desarrollo de Widgets.
De acuerdo con el artículo del Codex developing widgets, se utilizará la siguiente estructura para escribir un widget:
1 |
class My_Widget extends WP_Widget { |
2 |
|
3 |
public function __construct() { |
4 |
// widget actual processes
|
5 |
}
|
6 |
|
7 |
public function form( $instance ) { |
8 |
// outputs the options form on admin
|
9 |
}
|
10 |
|
11 |
public function update( $new_instance, $old_instance ) { |
12 |
// processes widget options to be saved
|
13 |
}
|
14 |
|
15 |
public function widget( $args, $instance ) { |
16 |
// outputs the content of the widget
|
17 |
}
|
18 |
|
19 |
}
|
Esto quiere decir que todos los Widgets se deben escribir usando POO. Si no has visto código como el anterior, lo veremos en la siguiente sección y te proporcionará todo lo que necesitas saber para entender lo que está pasando.
Una Introducción Concisa a la POO
Antes de empezar a ver y crear plugin para WordPress basados en POO vamos a echar un vistazo a las bases de la POO para estar seguros de que entendemos la terminología y cómo funciona el paradigma.
Clases
Como hemos definido antes, la POO usa "una colección de métodos relacionados". Pero no podemos dejarlo ahí. Después de todo, la programación funcional hace lo mismo.
En POO estos "métodos relacionados" están todos relacionados en el contexto de lo que llamamos una clase
. En el ejemplo del Widget de arriba, verás la palabra class
como la primera palabra del código.
Comienza en una línea que termina con la apertura de corchetes (como las funciones) y dentro incluye todas sus funciones relacionadas antes de terminar con un cierre de corchetes (por ahora, ignora la palabra extends
en el ejemplo del Widget - hablaremos de ello dentro de un momento).
Un Agrupamiento Lógico de Funciones
Si estás empezando con la escritura de clases y te estás preguntando si una función pertenece a una clase dada, pregúntate si la función hace algo que haría esta clase en particular .
Por ejemplo, en el ejemplo del Widget de arriba, el método update
es algo que éste widget haría. Pero digamos que estás escribiendo una clase que será la responsable de leer un post de blog de la base de datos de WordPress. Tendría sentido para esta clase en particular tener una función llamada read
o read_by_id
, pero ¿debe tener una función llamada write
? ¿Qué pasa con delete
?
Dependiendo de cómo hayas diseñado tu clase, posiblemente. Pero si el único propósito de la clase es leer datos, entonces probablemente no.
Y esto es POO. agrupa lógicamente tus funciones juntas en una clase pero este agrupamiento depende en el responsabilidad que les estés dando a tu clase.
Temas Avanzados en POO
La POO es un potente paradigma que se emplea en toda aplicación WordPress. La POO permite operaciones avanzadas como la herencia (que está representada por la palabra extends
en al clase Widget), patrones de diseño que esencialmente son soluciones existentes a problemas comunes.
Este artículo no intenta profundizar en la programación orientada a objetos. Simplemente intenta dar una base a partir de la cual podamos explorar las dos formas de escribir plugins WordPress pero los menciono por si estás interesado en profundizar en la programación orientada a objetos.
Desarrollar Plugin Basados en Clases
Ahora que hemos definido la programación orientada a objetos y explorado lo suficiente como para sentar las bases, es hora de empezar a hablar de los componentes del desarrollo basado en OOP en el contexto de los complementos de WordPress.
A lo largo del resto de este artículo, vamos a cubrir los aspectos básicos de lo que se requiere para escribir complementos basados en OOP, y las ventajas que aporta.
Definiendo la clase
Antes de hacer algo en desarrollo orientado a objetos, debe definir su clase. Suponiendo que ya tengas una idea de lo que tu clase va a hacer, generalmente es cuestión de pensar qué nombre quieres dar a tu clase.
En su mayor parte, creo que ver el código de ejemplo siempre es una ventaja cuando se enseña código, por lo que echaremos un vistazo al Complemento de WordPress.
Tenga en cuenta que el plugin Boilerplate es un proyecto que creé originalmente para ayudar a reiniciar los complementos basados en OOP. Desde entonces ha sido contribuido por una cantidad de personas diferentes. Lo estoy usando en este artículo porque demuestra el tema en cuestión.
Dicho esto, observe que la definición de clase para el complemento de complemento se ve así:
1 |
class PluginName { |
2 |
|
3 |
// More to come…
|
4 |
|
5 |
}
|
Debido a que el Complemento repetitivo es un lugar de inicio para el desarrollo, obviamente cambiaríamos el nombre de la clase. Para este artículo, vamos a llamarlo DemoPlugin
.
1 |
class DemoPlugin { |
2 |
|
3 |
// More to come…
|
4 |
|
5 |
}
|
En este punto, estamos listos para comenzar a definir las funciones que viven dentro de la clase.
El Constructor
En OOP, la primera función que es probable que veas en una clase es una función llamada "el constructor" y PHP no es diferente.
Una definición simple y funcional del constructor es esta:
El constructor es donde inicializa los datos que se usarán en toda la clase.
Cómo funciona esto varía de un proyecto a otro, pero hay dos cosas principales que podemos hacer en el contexto de un plugin de WordPress:
- Configura el textdomain para fines de localización
- Defina nuestras acciones y filtros (específicamente, nuestras acciones y nuestros filtros).
En nuestro DemoPlugin
, vamos a hacer justamente eso. Configuraremos un dominio de texto de demo-plugin
y registraremos acciones para registrar y poner en cola una hoja de estilo de ejemplo y un ejemplo de archivo de JavaScript.
Para completar en nuestro ejemplo, también registraremos un enlace para agregar texto al final del contenido que se muestra en una publicación.
Primero, definamos el constructor:
1 |
class DemoPlugin { |
2 |
|
3 |
public function __construct() { |
4 |
|
5 |
}
|
6 |
|
7 |
}
|
Tenga en cuenta que en PHP, un constructor se define mediante una función pública llamada construct
que está precedida por dos guiones bajos.
A continuación, definamos nuestro dominio de texto:
1 |
class DemoPlugin { |
2 |
|
3 |
public function __construct() { |
4 |
|
5 |
load_plugin_textdomain( 'demo-plugin', false, dirname( plugin_basename( __FILE__ ) ) . '/lang' ); |
6 |
|
7 |
}
|
8 |
|
9 |
}
|
En la línea de código anterior, tenga en cuenta que hemos definido la clave para que nuestro dominio de texto sea demo-plugin
y la línea espera encontrar los archivos de localización en un subdirectorio llamado lang
en el directorio del complemento.
Debido a que la localización está fuera del alcance de este artículo, no bucearé más, pero puede revisar el código fuente del Complemento repetitivo para ver cómo está configurado.
A continuación, definamos las acciones para registrar nuestras hojas de estilo y JavaScript, así como también el filtro que agregará texto al final de nuestro contenido:
1 |
class DemoPlugin { |
2 |
|
3 |
public function __construct() { |
4 |
|
5 |
load_plugin_textdomain( 'demo-plugin', false, dirname( plugin_basename( __FILE__ ) ) . '/lang' ); |
6 |
|
7 |
add_action( 'wp_enqueue_scripts', array( $this, 'register_plugin_styles' ) ); |
8 |
add_action( 'wp_enqueue_scripts', array( $this, 'register_plugin_scripts' ) ); |
9 |
|
10 |
add_filter( 'the_content', array( $this, 'append_post_notification' ) ); |
11 |
|
12 |
}
|
13 |
|
14 |
}
|
Si no está familiarizado con las acciones y los filtros, asegúrese de leer uno de mis artículos recientes aquí en Wptuts+, ya que explica la diferencia.
Ahora, si está familiarizado con el desarrollo de temas de WordPress o la programación funcional, entonces probablemente esté acostumbrado a ver algo como lo siguiente:
1 |
add_action( 'wp_enqueue_scripts', 'register_plugin_styles' ); |
Más bien que:
1 |
add_action( 'wp_enqueue_scripts', array( $this, 'register_plugin_styles' ) ); |
Observe que la diferencia en las dos llamadas anteriores está en el segundo parámetro. Específicamente, en nuestro complemento estamos pasando una matriz, mientras que la primera línea de código simplemente está pasando una cadena.
Debido a que estamos desarrollando este complemento utilizando OOP, WordPress tiene que saber dónde llamar al método register_plugin_styles
. Dado que vive dentro de nuestra clase, debemos decirle a WordPress que llame al método en una instancia de nuestra clase.
¿Tiene sentido?
Esencialmente, le estamos diciendo a WordPress: Tengo este método llamado register_plugin_styles
, pero debe llamarlo en una instancia de esta clase (de ahí la palabra clave this
).
Si es nuevo en WordPress, pero proviene de un entorno de programación, entonces puede imaginarse que le está diciendo a WordPress que haga esto:
1 |
$demo = new DemoPlugin(); |
2 |
$demo->register_plugin_styles(); |
De todos modos, la conclusión es que si está desarrollando sus complementos usando OOP, entonces debes registrar sus ganchos usando una matriz con dos índices: el primero es $this
y el segundo es el nombre de la función.
Una nota sobre Pass-by-Reference y Pass-by-Value
Los desarrolladores avanzados estarán familiarizados con la capacidad de PHP de pasar por referencia y pasar por valor. En WordPress Development, no es raro ver lo siguiente:
1 |
add_action( 'wp_enqueue_scripts', array( &$this, 'register_plugin_styles' ) ); |
Donde this
se pasa por referencia; sin embargo, a partir de PHP 5.4, se eliminó la capacidad de pasar variables por referencia en el momento de la llamada. Es por eso que este tutorial está optando por pasar por
valor.
Funciones
En la programación, las funciones son las unidades de código que son esencialmente responsables de "hacer algo". En la programación orientada a objetos, es útil pensar en ellos de forma ligeramente diferente.
En OOP, las clases generalmente están representadas por sustantivos. En nuestro caso, tenemos un DemoPlugin
. Del mismo modo, las funciones son a menudo verbos. Es decir, son acciones que nuestro sustantivo puede tomar. En este punto, ya hemos optado por definir las siguientes funciones:
register_plugin_styles
register_plugin_scripts
append_post_notification
Observe cómo cada nombre de función representa una acción que se puede tomar. Esta es una buena regla empírica para emplear al escribir funciones.
En la programación funcional, solo existe la idea de funciones; sin embargo, en OOP, hay varios tipos diferentes de funciones, dos de las cuales son funciones "públicas" y funciones "privadas".
Funciones públicas
Las funciones públicas son funciones a las que se puede acceder fuera de la clase. Esto significa que puede llamar a estos métodos una vez que haya instanciado la clase.
Esto es exactamente lo que hicimos anteriormente en el siguiente código:
1 |
$demo = new DemoPlugin(); |
2 |
$demo->register_plugin_styles(); |
Básicamente, estas funciones son accesibles para el público (donde el público puede ser un programador u otro objeto).
Las funciones que estamos escribiendo para registrar nuestras hojas de estilo, nuestro JavaScript y que estamos escribiendo para agregar texto a una publicación deben marcarse como públicas porque habrá una llamada de terceros en ellas: WordPress.
Definamos las dos funciones para la acción wp_enqueue_scripts
:
1 |
public function register_plugin_styles() { |
2 |
|
3 |
wp_register_style( 'demo-plugin', plugins_url( 'demo-plugin/css/plugin' ) ); |
4 |
wp_enqueue_style( 'demo-plugin' ); |
5 |
|
6 |
}
|
7 |
|
8 |
public function register_plugin_scripts() { |
9 |
|
10 |
wp_register_script( 'demo-plugin', plugins_url( 'demo-plugin/js/display.js' ) ); |
11 |
wp_enqueue_script( 'demo-plugin' ); |
12 |
|
13 |
}
|
Nuevamente, tenga en cuenta que estas dos funciones esperan que las hojas de estilo y JavaScript residan en los subdirectorios css y js, respectivamente. Para ver esto en acción, recuerde ver el Complemento.
Finalmente, definamos la función para el filtro de the_content
:
1 |
public function append_post_notification( $content ) { |
2 |
|
3 |
$notification = __( 'This message was appended with a Demo Plugin.', 'demo-plugin-locale' ); |
4 |
|
5 |
return $content . $notification; |
6 |
|
7 |
}
|
Tenga en cuenta que estamos usando la función __ para asegurarnos de que nuestra secuencia de comandos se localiza con el textdomain
que definimos en el constructor.
Funciones privadas
Si cualquiera puede acceder a los métodos públicos, implicaría que nadie puede acceder a las funciones privadas, ¿verdad? En su mayor parte, eso es correcto: la única persona, o cosa, que puede llamar a métodos privados es la clase en la que están definidos.
Eso significa que WordPress, objetos de terceros, ni programadores pueden llamar programáticamente a funciones privadas. Las funciones privadas solo pueden invocarse desde la clase en la que se utilizan.
En términos generales, las funciones privadas son muy útiles cuando se escriben métodos auxiliares, es decir, son útiles para manipular datos internamente para ayudar a que otra función realice su trabajo.
Para dar un ejemplo de trabajo, definamos una función privada que devolverá una cadena localizada que nuestra función append_post_notification
puede usar:
1 |
private function get_localized_notification() { |
2 |
return __( 'This message was appended with a Demo Plugin.', 'demo-plugin-locale' ); |
3 |
}
|
A continuación, redefinemos la función append_post_notification
para llamar a este nuevo helper:
1 |
public function append_post_notification( $content ) { |
2 |
return $content . $this->get_localized_notification(); |
3 |
}
|
Tenga en cuenta que hemos simplificado la primera función al agregar una segunda función. También podría argumentar que hemos aumentado la legibilidad de la función inicial agregando una llamada a una función con un nombre que ayuda a aclarar lo que está sucediendo.
Quizás lo más importante a tener en cuenta es que para llamar a funciones privadas, debe anteponer la llamada de función con $this
keyword y el ->
. Esto le dice a PHP: "Call the get_localized_notification
function that lives in this
class" ("Llame a la función get_localized_notification que existe en esta clase").
En cualquier caso, le hemos dado a cada método una única responsabilidad, otra buena práctica en programación orientada a objetos, y hemos demostrado el uso de funciones tanto públicas como privadas.
Otros tipos de funciones
En la programación orientada a objetos, también hay otros tipos de funciones que están más allá del alcance de este artículo.
Para ser completo, quería resumirlos aquí:
- Las funciones estáticas son funciones que no requieren una instancia de una clase para llamar. En cambio, simplemente puede llamarlos directamente sobre el nombre de la clase. Por ejemplo:
DemoPlugin::use_this_static_method().
- Las funciones protegidas son como funciones privadas a excepción de las subclases. Es decir, los únicos objetos que pueden acceder a las funciones protegidas son las subclases de la clase dada. Este tipo particular de función juega con el concepto de herencia que se mencionó anteriormente en el artículo.
Ventajas en WordPress
En este punto, hemos llegado a todas las notas altas para el desarrollo de WordPress orientado a objetos. Para resumir las ventajas:
1. Todas las funciones están en contexto
Al usar programación orientada a objetos, no es necesario que prefija una función con el nombre del tema o el nombre del complemento en el que está trabajando, ni tiene que preocuparse por nombrar una función que pueda interferir con una función de WordPress, la función de otro tema o la función de otro complemento.
En cambio, todas las funciones viven dentro del contexto de otra clase. Lo único que debe asegurarse es que su clase no sea nombrada como algo que interfiere con otra clase existente.
2. Llamarlos fuera de la API
Mediante el uso de programación orientada a objetos, puede invocar su plugin desde su propio sistema desde fuera de la API estándar de WordPress.
Digamos que estás desarrollando un tema y quieres que se muestre algo en la barra lateral que proporciona tu complemento. En la plantilla de la barra lateral, puede crear una instancia de su complemento y luego llamar a los métodos para que escriba información en la barra lateral.
Esto es particularmente útil cuando trabaja en una plantilla y desea proporcionar algunos datos predeterminados si el usuario no ingresa algo manualmente.
Conclusión
Como dijimos al principio del artículo: esta es solo una forma de desarrollar sus plugins de WordPress. El artículo de Stephen cubrirá cómo hacerlo usando programación funcional.
Después de leer este artículo, debe tener una mejor comprensión de la programación orientada a objetos, sus ventajas, y debe poder seguir el código documentado en la API de widgets, en mi Widget Boilerplate relacionado e incluso en todos los lugares en la base de código de WordPress.