Creo que es imposible dar una respuesta definitiva aquí, porque opciones como esta son preferencias personales.
Considere que lo que sigue es mi enfoque, y no tengo la presunción de que sea el correcto .
Lo que puedo decir con certeza es que debe evitar su tercera opción:
Solo devuelve nulo / falso
Esto es malo en diferentes aspectos:
- consistencia de tipo de retorno
- hace que las funciones sean más difíciles de realizar pruebas unitarias
- forzar la verificación condicional en el tipo de retorno (
if (! is_null($thing))...
) haciendo que el código sea más difícil de leer
Yo, más que a menudo, uso OOP para codificar complementos, y mis métodos de objeto a menudo arrojan excepciones cuando algo sale mal.
Al hacer eso, yo:
- lograr la consistencia del tipo de retorno
- hacer el código simple para la prueba unitaria
- no necesita verificación condicional en el tipo devuelto
Sin embargo, lanzar excepciones en un plugin para WordPress, significa que nada se coger ellos, que termina en un error fatal que es absolutamente no deseable, EXPECIALLY en la producción.
Para evitar este problema, normalmente tengo una "rutina principal" ubicada en el archivo de complemento principal, que envuelvo en un try
/ catch
bloque. Esto me da la oportunidad de detectar la excepción en la producción y evitar el error fatal.
Un ejemplo aproximado de una clase:
# myplugin/src/Foo.php
namespace MyPlugin;
class Foo {
/**
* @return bool
*/
public function doSomething() {
if ( ! get_option('my_plugin_everything_ok') ) {
throw new SomethingWentWrongException('Something went wrong.');
}
// stuff here...
return true;
}
}
y usándolo desde el archivo de complemento principal:
# myplugin/main-plugin-file.php
namespace MyPlugin;
function initialize() {
try {
$foo = new Foo();
$foo->doSomething();
} catch(SomethingWentWrongException $e) {
// on debug is better to notice when bad things happen
if (defined('WP_DEBUG') && WP_DEBUG) {
throw $e;
}
// on production just fire an action, making exception accessible e.g. for logging
do_action('my_plugin_error_shit_happened', $e);
}
}
add_action('wp_loaded', 'MyPlugin\\initialize');
Por supuesto, en el mundo real puede lanzar y atrapar diferentes tipos de excepción y comportarse de manera diferente según la excepción, pero esto debería darle una dirección.
Otra opción que uso a menudo (y no mencionó) es devolver objetos que contienen un indicador para verificar si no ocurre ningún error, pero manteniendo la consistencia del tipo de retorno.
Este es un ejemplo aproximado de un objeto como ese:
namespace MyPlugin;
class Options {
private $options = [];
private $ok = false;
public function __construct($key)
{
$options = is_string($key) ? get_option($key) : false;
if (is_array($options) && $options) {
$this->options = $options;
$this->ok = true;
}
}
public function isOk()
{
return $this->ok;
}
}
Ahora, desde cualquier lugar en su complemento, puede hacer:
/**
* @return MyPlugin\Options
*/
function my_plugin_get_options() {
return new MyPlugin\Options('my_plugin_options');
}
$options = my_plugin_get_options();
if ($options->isOk()) {
// do stuff
}
Tenga en cuenta que lo my_plugin_get_options()
anterior siempre devuelve una instancia de Options
clase, de esta manera siempre puede pasar el valor de retorno e incluso inyectarlo en otros objetos que usan la sugerencia de tipo, ahora le preocupa que el tipo sea diferente.
Si la función había regresado null
/ false
en caso de error, antes de pasarla se vio obligado a verificar si el valor devuelto es válido.
Al mismo tiempo, tiene una manera clara de entender si algo está mal con la instancia de la opción.
Esta es una buena solución en caso de que el error sea algo que se pueda recuperar fácilmente, utilizando valores predeterminados o lo que sea apropiado.