¿Dónde poner mi código: plugin o functions.php?
¿Existe un esquema fácil de entender para decidir qué tipo de código pertenece a un plugin o al archivo functions.php
del tema?
Hay muchos casos y ejemplos y muchos debates sobre este tema, principalmente porque existen algunos conceptos erróneos sobre el funcionamiento interno de WordPress. Busco una respuesta basada en hechos, no en opiniones.
Debería explicar cómo manejar estos puntos (y probablemente más):
- tipos de publicación personalizados y taxonomías
- formularios de contacto
- shortcodes
- widgets personalizados
add_theme_support( 'automatic-feed-links' );
- funciones SEO como elementos
meta
personalizados - cambio de tema
A menudo hay pros y contras para ambos lados. Nuestra pregunta más popular Mejor Colección de Código para tu archivo functions.php recibió muchos fragmentos de código como respuestas que son al menos debatibles.
Necesitamos criterios que un principiante pueda entender, tal vez una lista de verificación – con razones.
Ver también la pregunta relacionada de Chip Bennett en nuestro sitio meta: Preguntas que específicamente piden una solución "sin un plugin"
Relacionado: ¿Dónde pongo los fragmentos de código que encontré aquí o en otro lugar de la web?
Comenzaría con esta pregunta: ¿La funcionalidad está relacionada con la presentación del contenido, o con la generación/gestión del contenido, del sitio o de la identidad del usuario?
Si la funcionalidad no está relacionada específicamente con la presentación del contenido, entonces claramente pertenece al territorio de los Plugins. Esta lista es larga:
- Modificar filtros principales de WP (contenido de
wp_head
, como enlaces canónicos, meta HTML del generador, etc.) - Favicon del sitio
- Shortcodes en el contenido de las publicaciones
- Enlaces para compartir publicaciones
- Scripts de Google Analytics (y similares) en el pie de página
- Herramientas/controles SEO
- etc.
Si la funcionalidad está relacionada con la presentación del contenido, entonces es un candidato para ser incluido en el Tema. En este punto, recurriría al criterio de cambio de Tema de @Raf912: ¿Echarías de menos la funcionalidad al cambiar de Tema? Si la respuesta a esa pregunta es no, entonces la funcionalidad pertenece al Tema. Algunos ejemplos:
- Eliminar/sobrescribir el CSS de la Galería del núcleo de WP
- Filtrar la longitud del extracto de la publicación, el texto "leer más", etc.
- Cualquier cosa implementada mediante
add_theme_support()
(supongo que esto debería ser obvio) - CSS personalizado
Normalmente, estas dos preguntas proporcionarán una línea de diferenciación bastante clara; sin embargo, hay excepciones.
Tipos de contenido personalizados
Los Custom Post Types, por ejemplo, son un híbrido único entre generación y presentación de contenido, dada la forma en que funciona la Jerarquía de plantillas para las páginas de archivo y las páginas de publicación individual de tipos de contenido personalizados. El aspecto de generación de contenido de los CPT normalmente los colocaría claramente en el territorio de los Plugins; sin embargo, los Plugins no pueden definir páginas de plantilla que encajen inherentemente en el diseño/estilo de cualquier Tema (especialmente si el CPT muestra algo más allá del habitual Título/Contenido/Meta, o tiene taxonomías personalizadas asociadas).
A largo plazo, la solución a esta disparidad, en mi opinión, es tener una convención/consenso estándar para la definición de CPTs para tipos de contenido específicos (listados de bienes raíces, eventos de calendario, productos de comercio electrónico, entradas de biblioteca de libros/medios, etc.). De esa manera, el contenido generado por el usuario seguiría siendo portable entre Temas que implementen la definición estándar/convencional de un CPT dado, mientras que los desarrolladores de Temas conservan la flexibilidad de definir el diseño/estilo de ese CPT en los archivos de plantilla del Tema.
Enlaces a redes sociales
De manera similar, normalmente diría que los enlaces a perfiles de redes sociales, que se han vuelto casi omnipresentes en los Temas actuales, pertenecen al territorio de los Plugins, porque no tienen nada que ver con la presentación del contenido. La mejor solución sería que estos perfiles se definieran en algún lugar del núcleo; sin embargo, actualmente no existe un medio estándar/consensuado para definir estos enlaces. ¿Se definen mejor a nivel de configuración del sitio, o por usuario? Si es por usuario, ¿qué metadatos de usuario se exponen en la plantilla? etc.
Así que, nuevamente, a largo plazo, la solución a esta disparidad es que el núcleo defina dónde se definen estos enlaces, o que la comunidad de desarrolladores de Temas desarrolle su propio consenso. Mientras tanto, realmente no hay más remedio que mantenerlos definidos dentro de cada Tema.

add_theme_support( 'automatic-feed-links' );
no es presentacional. Pero es requerido por las pautas de temas. ¿Por qué es un riesgo necesario perder esta funcionalidad después de cambiar de tema?

Cualquier cosa que se implemente mediante add_theme_support()
solo puede implementarse a través del Tema. Usar add_theme_support( 'automatic-feed-links' )
dentro del Tema en realidad garantiza una experiencia consistente de un Tema a otro, ya que los enlaces de feed generados serán los mismos.

Creo que está mal nombrado: Los enlaces de feed no son presentacionales. Si el siguiente tema no llama a esa función, el usuario perderá los enlaces de feed. Y puedes agregarlo mediante un plugin sin ningún problema. Por eso estoy confundido al respecto. :)

Una prueba sencilla para determinar dónde colocar mejor el código:
- Escribe el código en el archivo functions.php
- Cambia de tema
¿Echas de menos la funcionalidad, el blog no funciona correctamente o quedan fragmentos del tema anterior (por ejemplo, shortcodes)?
Sí: colócalo en un plugin
No: déjalo en functions.php
Ejemplos: Escribe un shortcode. Después de cambiar de tema, los shortcodes en bruto quedan en tus publicaciones. Por lo tanto, será mejor colocarlo en un plugin.
Escribe una función para listar los últimos comentarios. Después de cambiar de tema, todo está bien porque quizás el otro tema tenga una función equivalente.
Realmente depende del código y lo que haga. Algunos códigos solo influyen en el estilo o contenido del tema, otros modifican las publicaciones del blog.

No creo que haya una respuesta fácil a esta pregunta, pero apuesto a que podríamos hacer un diagrama de flujo para ayudar con la decisión. Aquí hay un esquema aproximado de dicho diagrama, que puede y debe ampliarse. ¡Comenta con sugerencias!
- ¿Este código estará alojado en una instalación de WordPress de un solo sitio?
- Sí - ¿El tema del sitio solo cambia con rediseños importantes y cambios en la funcionalidad?
- Sí - ¿El código en cuestión es específico para este diseño actual?
- Sí: functions.php
- No: Plugin
- No (cambia con frecuencia o por capricho) - Plugin
- Sí - ¿El código en cuestión es específico para este diseño actual?
- No (Multisitio) - ¿Estás alojando la instalación multisitio O es una solución multisitio alojada que permite plugins?
- Sí: ¿La funcionalidad en cuestión es específica para este sitio, o puede/debe ser utilizada por otros sitios en la red?
- Específica para este sitio: functions.php
- Compartida entre múltiples sitios - ¿Quieres forzarla en cada sitio?
- Sí: Plugin, almacenado en el directorio mu-plugins o activado en red
- No: ¿Es esta una red de sitios no relacionados? (ej. diferentes clientes)
- Sí: ¿Sería malo o poco profesional si el cliente A viera o activara el plugin que escribiste para los clientes B, C y D? (ej. tal vez rompería el sitio o causaría funcionalidad indeseable)
- Sí: functions.php
- No: Plugin
- No: Probablemente plugin
- Sí: ¿Sería malo o poco profesional si el cliente A viera o activara el plugin que escribiste para los clientes B, C y D? (ej. tal vez rompería el sitio o causaría funcionalidad indeseable)
- No (alojado por un servicio como VIP que no permite plugins): usa functions.php
- Sí: ¿La funcionalidad en cuestión es específica para este sitio, o puede/debe ser utilizada por otros sitios en la red?
- Sí - ¿El tema del sitio solo cambia con rediseños importantes y cambios en la funcionalidad?
- Temas padre -- a veces con funcionalidad compartida sería mejor crear un tema padre y poner la funcionalidad en el archivo functions.php del tema padre.
- Los directorios de plugins de grandes instalaciones multisitio pueden volverse rápidamente inmanejables, por lo que a veces la funcionalidad compartida usada por un bajo porcentaje de sitios (ej. < 1%) sería mejor duplicarla en archivos functions.php.

Desde aquí Temas VS Plugins
Añade código personalizado a un tema hijo para que cuando actualices el tema padre, tu código personalizado no se pierda.
También puedes crear un plugin específico para el sitio que contenga todo tu código personalizado.
En cuanto a escribir código versus plugins, puedes usar plugins y las funciones, sin embargo, para la mayoría de lo que deseas, codificar manualmente es lo mejor ya que es más fácil de modificar excepto en algunos casos como meta boxes donde puedes considerar usar un plugin a menos que seas un desarrollador de temas.
function modify_contact_methods($profile_fields) {
// Añadir nuevos campos
$profile_fields['twitter'] = 'Usuario de Twitter';
$profile_fields['facebook'] = 'URL de Facebook';
$profile_fields['gplus'] = 'URL de Google+';
return $profile_fields;
}
add_filter('user_contactmethods', 'modify_contact_methods');
http://codex.wordpress.org/Plugin_API/Filter_Reference/user_contactmethods
- Añadir nuevo tipo de entrada personalizado - Código
- Añadir nuevos campos a los Usuarios - Código arriba
- Añadir nuevos widgets - Código
- Añadir enlaces permanentes personalizados - Configuración de Enlaces Permanentes de WordPress

Sé que este es un tema muy trillado y que Chip básicamente lo ha cubierto, pero quería añadir algunas reflexiones.
Si te ganas la vida programando y te encuentras trabajando en sitios WordPress con plazos ajustados, vas a darte cuenta de que todo se reduce al tiempo.
En la mayoría de los casos, especialmente para los que están empezando, es mucho más rápido y sencillo simplemente añadir lo que necesitas en un tema y darlo por terminado.
Dicho esto, si trabajas con WordPress de forma semi regular, deberías considerar seriamente hacer lo siguiente:
- Crea un esqueleto de plugin
Esto debería manejar todo lo que comúnmente necesitarás hacer con un plugin, incluyendo activación, desactivación, actualización de versiones, construcción de paneles de administración y desinstalación.
Si te tomas el tiempo para hacer esto, descubrirás:
- Ya no toma mucho tiempo extra añadir funcionalidades mediante plugins
- Puedes empezar a construir una lista sólida de plugins para reutilizar en otros proyectos según sea necesario, ahorrándote mucho tiempo a largo plazo.
- Puedes hacerlos públicos si quieres mayor visibilidad
Ahora puedes construir las cosas correctamente y completar proyectos futuros más rápidamente.
- Crea un esqueleto de tema
Esto debería manejar todo lo que comúnmente se necesita en un tema:
- Una hoja de estilos principal que contenga estilos que uses comúnmente (resets, etc.)
- Un archivo index.php adecuado, manejando todo lo que necesitas para cualquier plantilla
- Un archivo functions.php - no lo usarás tanto, pero aún así será útil.
Una vez que tengas eso listo, construye un esqueleto de tema hijo que use tu tema principal.
- Añade la hoja de estilos, referenciando tu tema padre.
- Añade el archivo functions.php
Una vez que tengas estas dos cosas hechas, crear nuevos sitios para clientes se volverá mucho más rápido.
Si haces lo anterior, entonces podrás trabajar en lo siguiente:
- Usar tu nuevo tiempo libre para familiarizarte más con PHP, WordPress, JavaScript, CSS y/o MySQL... cuanto más aprendas de esto, más rápido completarás tus proyectos.
- Actualizar tus esqueletos de plugin, tema y tema hijo a medida que encuentres cosas que mejorar. No importa cuán bueno seas, si sigues aprendiendo encontrarás mejoras por hacer.
Y, si haces todo lo anterior, descubrirás que la respuesta de Chip no solo será ideal, sino que se convertirá en la óptima.

La respuesta simple es esta...
¿El código depende de alguna funcionalidad incorporada en un tema específico? Si es así, entonces colócalo en el tema.
¿Quieres que este código sea transferible entre sitios y entre temas? Si es así, entonces colócalo en un plugin.
Si la respuesta es no a ambas preguntas anteriores, entonces imagina el sitio dentro de 5 años, cuando sea momento de un rediseño. ¿La función del código que estás escribiendo es algo que sobrevivirá a la próxima actualización de diseño? Si es así, colócalo en un plugin.
Además, si no estás usando temas hijos y planeas actualizar el tema, también te sugeriría que uses un plugin.

Para responder al OP:
Tipos de contenido personalizados y taxonomías
Deberían ir en un plugin ya que definen elementos a nivel estructural/conceptual, no a nivel de presentación
Formularios de contacto
Son de presentación y deben ir en las funciones del tema
Shortcodes
En plugin por ser estructurales
Widgets personalizados
Son claramente de presentación y deben ir con el tema: functions
add_theme_support( 'automatic-feed-links' );
El soporte del tema va en las funciones del tema
Funciones SEO como meta elementos personalizados
Presentación, por lo tanto en functions
