Cómo estructurar un complemento

41

Esta no es una pregunta sobre cómo construir un complemento de WordPress. Por el contrario, qué guías, si las hay, podrían aplicarse a cómo armar la arquitectura de archivos de cualquier complemento.

Algunos otros lenguajes de programación o bibliotecas tienen formas muy controladas de organizar directorios y archivos. A veces esto es molesto y resalta la libertad que ofrece PHP, pero por otro lado, los complementos de WordPress se combinan de cualquier manera según lo determine su autor.

No hay una respuesta correcta , pero mi esperanza es refinar cómo yo, y otros, construimos complementos para hacerlos más amigables para otros desarrolladores, más fáciles de depurar, más fáciles de navegar y posiblemente más eficientes.

La pregunta final: ¿cuál crees que es la mejor manera de organizar un complemento?

A continuación hay algunas estructuras de muestra, pero de ninguna manera hay una lista exhaustiva. Siéntase libre de agregar sus propias recomendaciones.

Estructura predeterminada asumida

  • /wp-content
    • /plugins
      • /my-plugin
        • my-plugin.php

Método de controlador de vista de modelo (MVC)

  • /wp-content
    • /plugins
      • /my-plugin
        • /controller
          • Controller.php
        • /model
          • Model.php
        • /view
          • view.php
        • my-plugin.php

Las tres partes de MVC:

  • El modelo interactúa con la base de datos, consulta y guarda datos, y contiene lógica.
  • El controlador contendría etiquetas de plantilla y funciones que la vista utilizaría.
  • La vista es responsable de mostrar los datos proporcionados por el modelo tal como los construyó el controlador.

Organizado por método de tipo

  • /wp-content
    • /plugins
      • /my-plugin
        • /admin
          • admin.php
        • /assets
          • css/
          • images/
        • /classes
          • my-class.php
        • /lang
          • my-es_ES.mo
        • /templates
          • my-template.php
        • /widgets
          • my-widget.php
        • my-plugin.php

WordPress Plugin Boilerplate

Disponible en Github

Basado en la API de complementos , estándares de codificación y estándares de documentación .

  • /wp-content
    • /plugins
      • /my-plugin
        • /admin
          • /css
          • /js
          • /partials
          • my-plugin-admin.php
        • /includes
          • my_plugin_activator.php
          • my_plugin_deactivator.php
          • my_plugin_i18n.php
          • my_plugin_loader.php
          • my_plugin.php
        • /languages
          • my_plugin.pot
        • /public
          • /css
          • /js
          • /partials
          • my-plugin-public.php
        • LICENSE.txt
        • README.txt
        • index.php
        • my-plugin.php
        • uninstall.php

Método poco organizado

  • /wp-content
    • /plugins
      • /my-plugin
        • css/
        • images/
        • js/
        • my-admin.php
        • my-class.php
        • my-template.php
        • my-widget.php
        • my-plugin.php
desarrollo
fuente
Esta no es una pregunta real, pero no voy a cerrar el voto, sino que marqué para hacer de este Wiki de la comunidad. Por cierto: creo que no tiene ningún sentido perfilar los nombres de archivo.
kaiser
Gracias, prefiero que sea una wiki comunitaria de todos modos. No creo que prefijar archivos de esa manera tenga mucho sentido tampoco, pero lo he visto mucho.
desarrollado el
1
Otro aspecto puntos: Tal vez los nombres más semánticamente correcto para las carpetas css/, images/y js/sería styles/, images/y scripts/.
Andrew Odri

Respuestas:

16

Tenga en cuenta que los complementos son todos "controladores" según los estándares de WP.

Depende de lo que se supone que debe hacer el complemento, pero en todos los casos trataría de separar la salida de pantalla del código PHP tanto como sea posible.

Aquí hay una forma de hacerlo fácilmente: primero, defina una función que cargue la plantilla:

function my_plugin_load_template(array $_vars){

  // you cannot let locate_template to load your template
  // because WP devs made sure you can't pass
  // variables to your template :(
  $_template = locate_template('my_plugin', false, false);

  // use the default one if the theme doesn't have it
  if(!_$template)
    $_template = 'views/template.php';

  // load it
  extract($_vars);        
  require $template;
}

Ahora, si el complemento utiliza un widget para mostrar datos:

class Your_Widget extends WP_Widget{

  ...      
  public function widget($args, $instance){

    $title = apply_filters('widget_title', $instance['title'], $instance, $this->id_base);

    // this widget shows the last 5 "movies"
    $posts = new WP_Query(array('posts_per_page' => 5, 'post_type' => 'movie')); 

    if($title)
      print $before_title . $title . $after_title;

    // here we rely on the template to display the data on the screen
    my_plugin_load_template(array(

      // variables you wish to expose in the template
     'posts'    => $posts,          
    ));

    print $before_widget;
  }
  ...

}

La plantilla:

<?php while($posts->have_posts()): $posts->the_post(); ?>

<p><?php the_title(); ?></p> 

<?php endwhile; ?>

Archivos:

/plugins/my_plugin/plugin.php           <-- just hooks 
/plugins/my_plugin/widget.php           <-- widget class, if you have a widget
/themes/twentyten/my_plugin.php         <-- template
/plugins/my_plugin/views/template.php   <-- fallback template

¿Dónde colocar sus CSS, JS, imágenes o cómo diseña el contenedor para los ganchos es menos importante? Es una cuestión de preferencia personal, supongo.

Pony de un solo truco
fuente
6

Depende del complemento. Esta es mi estructura básica para casi todos los complementos:

my-plugin/
    inc/
        Any additional plugin-specific PHP files go here
    lib/
        Library classes, css, js, and other files that I use with many
        plugins go here
    css/
    js/
    images/
    lang/
        Translation files
    my-plugin.php
    readme.txt

Esto sería algo que iría en la libcarpeta.

Si es un complemento particularmente complejo, con mucha funcionalidad de área de administración, agregaría una admincarpeta para contener todos esos archivos PHP. Si el complemento hace algo como reemplazar los archivos de tema incluidos , tal vez haya una carpeta templateo themetambién.

Entonces, una estructura de directorio podría verse así:

my-plugin/
    inc/
    lib/
    admin/
    templates/
    css/
    js/
    images/
    lang/
    my-plugin.php
    readme.txt
chrisguitarguy
fuente
¿Incluiría también los archivos css y js del administrador dentro de la carpeta / admin? ¿Por lo tanto tener otro / css y / js dentro de / admin?
urok93
6

En mi humilde opinión, la ruta más fácil, más potente y más fácil de mantener es usar una estructura MVC, y WP MVC está diseñado para hacer que la escritura de complementos MVC sea muy fácil (aunque estoy un poco sesgado ...). Con WP MVC, simplemente crea los modelos, las vistas y los controladores, y todo lo demás se maneja detrás de escena por usted.

Se pueden crear controladores y vistas separadas para las secciones públicas y administrativas, y todo el marco aprovecha muchas de las características nativas de WordPress. La estructura de archivos y gran parte de la funcionalidad es exactamente la misma que en los marcos MVC más populares (Rails, CakePHP, etc.).

Puede encontrar más información y un tutorial aquí:

Tom
fuente
5

Estamos usando una combinación de todos los métodos. En primer lugar, estamos usando Zend Framework 1.11 en nuestros complementos y, por lo tanto, tuvimos que usar una estructura similar para los archivos de clase debido a la mecánica de carga automática.

La estructura de nuestro complemento principal (que es utilizada por todos nuestros complementos como base) es similar a esta:

webeo-core/
    css/
    images/
    js/
    languages/
    lib/
        Webeo/
            Core.php
        Zend/
            /** ZF files **/
        Loader.php
    views/
    readme.txt
    uninstall.php
    webeo-core.php
  1. WordPress llama al webeo-core.phparchivo en la carpeta raíz del complemento.
  2. En este archivo vamos a establecer la ruta de inclusión de PHP y registrar los ganchos de activación y desactivación para el complemento.
  3. También tenemos una Webeo_CoreLoaderclase dentro de este archivo, que establece algunas constantes del complemento, inicializa el autocargador de clases y realiza una llamada al método de configuración de la Core.phpclase dentro de la lib/Webeocarpeta. Esto se ejecuta en el plugins_loadedgancho de acción con una prioridad de 9.
  4. La Core.phpclase es nuestro archivo de arranque de complemento. El nombre se basa en el nombre del complemento.

Como puede ver, tenemos un subdirectorio dentro de la libcarpeta para todos nuestros paquetes de proveedores ( Webeo, Zend). Todos los subpaquetes dentro de un proveedor están estructurados por el propio módulo. Para un nuevo Mail Settingsformulario de administrador, tendríamos la siguiente estructura:

webeo-core/
    ...
    lib/
        Webeo/
            Form/
                Admin/
                    MailSettings.php
                Admin.php
            Core.php
            Form.php

Nuestros sub-plugins tienen la misma estructura con una excepción. Vamos a un nivel más profundo dentro de la carpeta del proveedor debido a la resolución de conflictos de nombres durante el evento de carga automática. También llamamos a los plugins clase boostrap E.g. Faq.phppor prioridad 10dentro del plugins_loadedgancho.

webeo-faq/ (uses/extends webeo-core)
    css/
    images/
    js/
    languages/
    lib/
        Webeo/
            Faq/
                Faq.php
                /** all plugin relevant class files **/
    views/
    readme.txt
    uninstall.php
    webeo-faq.php

Probablemente cambiaré el nombre de la libcarpeta vendorsy moveré todas las carpetas públicas (css, images, js, languages) a una carpeta nombrada publicen la próxima versión.

rofflox
fuente
5

Como muchos aquí ya respondieron, realmente depende de lo que se supone que debe hacer el complemento, pero aquí está mi estructura base:

my-plugin/
    admin/
        holds all back-end administrative files
        js/
            holds all back-end JavaScript files
        css/                    
            holds all back-end CSS files
        images/
            holds all back-end images
        admin_file_1.php        back-end functionality file
        admin_file_2.php        another back-end functionality file 
    js/
        holds all front end JavaScript files
    css/
        holds all fronted CSS files
    inc/
        holds all helper classes
    lang/                   
        holds all translation files
    images/
        holds all fronted images
    my-plugin.php               main plugin file with plugin meta, mostly includes,action and filter hooks
    readme.txt                  
    changelog.txt
    license.txt
Bainternet
fuente
4

Soy parcial con el siguiente diseño de complemento, sin embargo, generalmente cambia según cuáles sean los requisitos del complemento.

wp-content/
    plugins/
        my-plugin/
            inc/
                Specific files for only this plugin
                admin/ 
                    Files for dealing with administrative tasks
            lib/
                Library/helper classes go here
            css/
                CSS files for the plugin
            js/
                JS files
            images/
                Images for my plugin
            lang/
                Translation files
        plugin.php 
            This is the main file that calls/includes other files 
        README 
            I normally put the license details in here in addition to helpful information 

Todavía tengo que crear un complemento de WordPress que requiera una arquitectura de estilo MVC, pero si tuviera que hacerlo, lo diseñaría con un directorio MVC separado, que contiene vistas / controladores / modelos.

mystline
fuente
4

Mi lógica, cuanto más grande es el complemento, más estructura utilizo.
Para complementos grandes tiendo a usar MVC.
Lo uso como punto de partida y omito lo que no es necesario.

controller/
    frontend.php
    wp-admin.php
    widget1.php
    widget2.php
model/
    standard-wp-tables.php // if needed split it up
    custom-tabel1.php
    custom-tabel2.php
view/
    helper.php
    frontend/
        files...php
    wp-admin/
        files...php
    widget1/
        file...php
    widget2/
        file...php
css/
js/
image/
library/  //php only, mostly for Zend Framework, again if needed
constants.php //tend to use it often
plugin.php //init file
install-unistall.php  //only on big plugins
janw
fuente
3

Todos mis complementos siguen esta estructura, que parece ser muy similar a lo que están haciendo la mayoría de los demás desarrolladores:

plugin-folder/
    admin/
        css/
            images/
        js/
    core/
    css/
        images/
    js/
    languages/
    library/
    templates/
    plugin-folder.php
    readme.txt
    changelog.txt
    license.txt

plugin-folder.php suele ser una clase que carga todos los archivos necesarios desde el núcleo / carpeta. Muy a menudo en el gancho init o plugins_loaded.

Solía ​​prefijar todos mis archivos también, pero como señaló @kaiser anteriormente, es realmente redundante y recientemente he decidido eliminarlo de cualquier complemento futuro.

La biblioteca / carpeta contiene todas las bibliotecas auxiliares externas de las que puede depender el complemento.

Dependiendo del complemento, puede haber un archivo uninstall.php en la raíz del complemento también. Sin embargo, la mayoría de las veces esto se maneja a través de register_uninstall_hook ().

Obviamente, algunos complementos pueden no requerir ningún archivo o plantilla de administrador, etc., pero la estructura anterior funciona para mí. Al final solo tienes que encontrar una estructura que funcione para ti y luego quedarte con ella.

También tengo un complemento de inicio, basado en la estructura anterior que utilizo como punto de partida para todos mis complementos. Todo lo que necesito hacer es buscar / reemplazar los prefijos de función / clase y listo. Cuando todavía estaba prefijando mis archivos, era un paso adicional que tenía que hacer (y bastante molesto), pero ahora solo tengo que cambiar el nombre de la carpeta del complemento y el archivo del complemento principal.

shabushabu
fuente
0

Un enfoque menos común para estructurar los archivos y directorios de un complemento es el enfoque de tipo de archivo. Vale la pena mencionar aquí para completar:

plugin-name/
    js/
        sparkle.js
        shake.js
    css/
        style.css
    scss/
        header.scss
        footer.scss
    php/
        class.php
        functions.php
    plugin-name.php
    uninstall.php
    readme.txt

Cada directorio contiene archivos de ese tipo solamente. Vale la pena señalar que este enfoque se queda corto cuando tiene muchos tipos de archivos .png .gif .jpgque podrían archivarse de manera más lógica en un solo directorio, images/por ejemplo.

henrywright
fuente