Penso che sia impossibile dare una risposta definitiva qui, perché scelte come questa sono preferenze personali.
Considera che ciò che segue è il mio approccio e non ho alcuna presunzione che sia quello giusto .
Quello che posso dire con certezza è che dovresti evitare la tua terza opzione:
Restituisce solo null / false
Questo è negativo sotto diversi aspetti:
- ritorno tipo di coerenza
- rende le funzioni più difficili per il test unitario
- impone il controllo condizionale sul tipo restituito (
if (! is_null($thing))...
) rendendo il codice più difficile da leggere
Io, più spesso, uso OOP per codificare plugin, e i miei metodi di oggetti spesso generano eccezioni quando qualcosa va storto.
In questo modo, io:
- realizzare la coerenza del tipo di ritorno
- rendere il codice semplice per unit test
- non è necessario un controllo condizionale sul tipo restituito
Tuttavia, gettando le eccezioni in un plugin per WordPress, significa che nulla si cattura di loro, finendo in un errore fatale che è assolutamente non auspicabile, soprattutto nella produzione.
Per evitare questo problema, normalmente ho una "routine principale" che si trova nel file del plugin principale, che avvolgo in un blocco try
/ catch
. Questo mi dà la possibilità di cogliere l'eccezione nella produzione e prevenire l'errore fatale.
Un esempio approssimativo di una classe:
# 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;
}
}
e usandolo dal file del plugin principale:
# 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');
Naturalmente, nel mondo reale puoi lanciare e catturare diversi tipi di eccezione e comportarti in modo diverso a seconda dell'eccezione, ma questo dovrebbe darti una direzione.
Un'altra opzione che uso spesso (e non hai menzionato) è quella di restituire oggetti che contengono un flag per verificare se non si verificano errori, ma mantenendo la coerenza del tipo restituito.
Questo è un esempio approssimativo di un oggetto del genere:
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;
}
}
Ora, da qualsiasi posto nel tuo plugin, puoi fare:
/**
* @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
}
Nota come my_plugin_get_options()
sopra restituisce sempre un'istanza di Options
classe, in questo modo puoi sempre passare il valore restituito e persino iniettarlo in altri oggetti che usano il suggerimento del tipo con le preoccupazioni ora che il tipo è diverso.
Se la funzione era stata restituita null
/ false
in caso di errore, prima di passarla in giro era stata costretta a verificare se il valore restituito è valido.
Allo stesso tempo, hai un modo chiaro per capire se qualcosa non va nell'istanza dell'opzione.
Questa è una buona soluzione nel caso in cui l'errore sia qualcosa che può essere facilmente recuperato, usando i valori predefiniti o qualunque cosa si adatti.