Cómo incluir archivos PHP en plugins de la manera correcta
Mi problema es cuando en el archivo principal del plugin incluyo un archivo PHP de esta manera:
include(WP_PLUGIN_URL . '/wordpress-group-buying/ipn/paypal-ipn.php');
// o
include_once(WP_PLUGIN_URL . '/wordpress-group-buying/ipn/paypal-ipn.php');
// o
require(WP_PLUGIN_URL . '/wordpress-group-buying/ipn/paypal-ipn.php');
// o
require_once(WP_PLUGIN_URL . '/wordpress-group-buying/ipn/paypal-ipn.php');
y en ese archivo tengo una llamada a una función de WordPress como:
add_action('hook', 'callback');
y obtengo:
Fatal Error: Call to undefined function add_action()
Ahora antes de que digas "usa if(**function_exists**('add_action')){
" si uso eso simplemente no funciona.
Las preguntas:
- ¿Cuál sería la forma correcta de hacer eso?
- ¿Cuáles son las diferencias entre
include
,include_once
,require
y cuándo uso cada uno?

Llegando tarde a esta fiesta, pero aquí está la forma "WordPress": usa plugin_dir_path( __FILE__ )
, por ejemplo:
<?php
include( plugin_dir_path( __FILE__ ) . 'ipn/paypal-ipn.php');
?>
Ten en cuenta que la función sí devuelve la barra diagonal final para la ruta del archivo.

Ten en cuenta que al usar __FILE__
devolverá la ruta relativa al archivo actual desde donde lo llamas, así que si tu declaración include
se hace desde un subdirectorio dentro de la estructura de archivos de tu plugin, obtendrás también ese subdirectorio.

Revisé un par de plugins que creé anteriormente para ver las diferentes formas en las que he incluido archivos adicionales dentro de los plugins y noté que hay dos métodos que puedes usar, probablemente hay más.
Define tu directorio de plugin
Dentro de tu plugin, usa la siguiente definición para establecer la ubicación actual del plugin.
Código de ejemplo:
define( 'PLUGIN_DIR', dirname(__FILE__).'/' );
Incluir o requerir directamente
Puedes simplemente usar: include, include_once, require o require_once dentro de la carpeta de tu plugin haciendo referencia a la ubicación como en el ejemplo de código a continuación. El ejemplo siguiente se basa en un archivo en el directorio raíz del plugin que incluye otro archivo de una carpeta dentro de tu directorio de plugin.
Código de ejemplo:
include "classes/plugin-core.php";

Termino evitando las construcciones de WordPress para los includes y uso lo siguiente:
require_once(dirname(__FILE__) . '/filename.php');
No creo que realmente resuelva tu problema, que parece ser un tema de ámbito, pero es el código que yo uso.
En cuanto a la diferencia entre include y require:
include mostrará una advertencia si el archivo no se encuentra
require mostrará un error fatal si el archivo no se encuentra
include_once y require_once no incluirán/requerirán el archivo/código nuevamente si ya ha sido incluido/requerido (ten en cuenta que, hasta donde sé, esto solo aplica para un archivo específico en un directorio específico).

Incluir
La sentencia include() incluye y evalúa el archivo especificado.
Incluir Una Vez
La sentencia include_once() incluye y evalúa el archivo especificado durante la ejecución del script. Este comportamiento es similar al de la sentencia include(), con la única diferencia de que si el código de un archivo ya ha sido incluido, no se volverá a incluir. Como su nombre lo indica, se incluirá solo una vez.
Requerir
require() e include() son idénticos en todo excepto en cómo manejan los fallos. Ambos producen una Advertencia (Warning), pero require() resulta en un Error Fatal. En otras palabras, no dudes en usar require() si quieres que un archivo faltante detenga el procesamiento de la página.
Requerir Una Vez
La sentencia require_once() incluye y evalúa el archivo especificado durante la ejecución del script. Este comportamiento es similar al de la sentencia require(), con la única diferencia de que si el código de un archivo ya ha sido incluido, no se volverá a incluir.
La información anterior proviene de la documentación de PHP, el asunto es que no hay una opción correcta, dependerá de la necesidad del código. Yo uso require() para cosas importantes como funciones, pero en archivos del tema como el footer o el loop uso include_once o include porque puedo manejar la advertencia y decirle al usuario/visitante que ocurrió un error en lugar de simplemente mostrar un error_fatal.

Primero, gracias a todos los que respondieron,
Mi problema era llamar a los archivos incluidos con la URL completa, de esa manera no pasaban por WordPress. Y eso sucedió porque, como mencioné en la pregunta, los estaba llamando desde el archivo principal del plugin. Así que la solución terminó siendo usar:
include_once('/ipn/paypal-ipn.php');
Leí sobre esto en el soporte de WordPress. ¡Y nuevamente gracias por responder!

¿Podrías reconsiderar marcar esta respuesta (https://wordpress.stackexchange.com/a/32002/123092) como la aceptada?

include( plugin_dir_path( __FILE__ ) . 'ipn/paypal-ipn.php');
o
define( 'PLUGIN_ROOT_DIR', plugin_dir_path( __FILE__ ) );
include( PLUGIN_ROOT_DIR . 'ipn/paypal-ipn.php');
o
$plugin_dir_path = plugin_dir_path( __FILE__ );
include( $plugin_dir_path . 'ipn/paypal-ipn.php');
Nota: para cargar archivos .css & .js con admin_enqueue_scripts
dentro del plugin, usa plugin_dir_url( __FILE__ )
$plugin_dir_uri = plugin_dir_url( __FILE__ );
wp_enqueue_style( 'plugin-style', $plugin_dir_uri . 'css/plugin-style.css');

Hola @בניית אתרים:
Cuando WordPress se está cargando, define la función add_action()
antes de intentar cargar cualquier plugin. El hecho de que estés recibiendo ese error me indica que estás haciendo algo inusual o que hay algún problema con tu instalación de WordPress.
¿Cómo estás haciendo que tu "plugin" se cargue? ¿Estás usando include*()
o require*()
para cargarlo, quizás en tu archivo wp-config.php
?

Cada vez que creas un nuevo archivo dentro de tu directorio de trabajo, tienes que incluirlo manualmente cada vez. Pero prueba un método para escanear tu directorio y adjuntarlo automáticamente, no solo los archivos PHP, lo cual ayuda a incluir archivos PHP, JS y CSS correctamente en ambos lados (backend y frontend).
http://kvcodes.com/2014/05/wordpress-theme-development-include-files-automatically/
