Eu acho que é impossível dar uma resposta definitiva aqui, porque escolhas como essa são preferência pessoal.
Considere que o que se segue é a minha abordagem, e não tenho presunção de que seja a correta .
O que posso dizer com certeza é que você deve evitar sua terceira opção:
Basta retornar nulo / falso
Isso é ruim sob aspectos diferentes:
- tipo de retorno consinstency
- torna as funções mais difíceis de testar na unidade
- forçar verificação condicional no tipo de retorno (
if (! is_null($thing))...
), dificultando a leitura do código
Eu, mais frequentemente, uso OOP para codificar plug-ins, e meus métodos de objeto geralmente lançam exceção quando algo dá errado.
Fazendo isso, eu:
- realizar consinstência de tipo de retorno
- simplifique o código para o teste de unidade
- não precisa de verificação condicional no tipo retornado
No entanto, lançar exceções em um plugin do WordPress significa que nada as pegará , resultando em um erro fatal que não é absolutamente desejável, especialmente na produção.
Para evitar esse problema, normalmente tenho uma "rotina principal" localizada no arquivo principal do plug-in, que envolvo em um bloco try
/ catch
. Isso me dá a chance de capturar a exceção na produção e evitar o erro fatal.
Um exemplo aproximado de uma 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 usando-o no arquivo principal do plug-in:
# 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');
Obviamente, no mundo real, você pode lançar e capturar diferentes tipos de exceção e se comportar de maneira diferente de acordo com a exceção, mas isso deve lhe dar uma direção.
Outra opção que costumo usar (e você não mencionou) é retornar objetos que contêm um sinalizador para verificar se nenhum erro ocorre, mas mantendo a consistência do tipo de retorno.
Este é um exemplo aproximado de um objeto como esse:
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;
}
}
Agora, de qualquer lugar no seu plugin, você pode:
/**
* @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
}
Observe como my_plugin_get_options()
acima sempre retorna uma instância da Options
classe; dessa forma, você sempre pode passar o valor de retorno e até injetá-lo em outros objetos que usam a dica de tipo, agora preocupam que o tipo seja diferente.
Se a função retornou null
/ false
em caso de erro, antes de passá-la, você foi forçado a verificar se o valor retornado é válido.
Ao mesmo tempo, você tem uma maneira clara de entender se algo está errado com a instância da opção.
Essa é uma boa solução, caso o erro seja algo que possa ser facilmente recuperado, usando padrões ou o que for adequado.