Поймай исключение, ничего не делая в улове

В PHP я иногда ловлю некоторые исключения с помощью try/catch:

try {
    ...
} catch (Exception $e) {
    // Nothing, this is normal
}

С таким кодом я получаю переменную $e, которая создается даром (много ресурсов), а PHP_MD (PHP Mess Detector) создает предупреждение из-за неиспользуемой переменной.

Есть ли способ поймать исключение, не создавая переменную?

Спасибо

8 ответов

Начиная с PHP 8, который будет выпущен в ноябре 2020 года, можно будет использовать не захватывающий улов.

Это соответствующий RFC, за который проголосовали 48-1.

Теперь можно будет сделать что-то вроде этого:

try {
    readFile($file);
} catch (FileDoesNotExist) {
    echo "File does not exist";
} catch (UnauthorizedAccess) {
    echo "User does not have the appropriate permissions to access the file";
    log("User attempted to access $file");
}

При этом для некоторых крайних случаев, когда детали исключения не актуальны, а тип исключения уже предоставляет весь необходимый контекст, будет возможно перехватить исключение без создания новой переменной.

Нет, но вы можете сбросить его.

try {
    ...
} catch (Exception $e) {
    unset($e);
}

Я предполагаю, что вы ловите исключение только потому, что не должны, потому что хотите. Вы должны использовать catch если вы хотите использовать try, поэтому мнения людей о том, является ли плохой идеей поймать исключение, не имеют значения. Усилия должны быть направлены на достижение требуемого результата без использования try/catch, Насколько я знаю, альтернативы нет.

Я использую что-то подобное для моего движка шаблонов.

//array of templates ordered by version new to old.
for($templates as $tpl){
    try {
        $output = render($tpl,$data);
        //it worked
        break;
    } catch(ErrorException $e){
        unset($e);
    }
}
if(!empty($output)){
    return $output;
}

В этом весь смысл исключений - вы можете иметь несколько различных блоков catch, чтобы перехватывать любые исключения, которые вы хотите обработать. Данные исключения должны быть где-то назначены, отсюда и переменная. Вы могли бы просто сделать что-то вроде unset($e) внутри блока catch, если вы действительно не хотите видеть эти предупреждения... или отключить предупреждения (как правило, плохая идея).

Я принципиально не согласен с ответами Марка Б. и Артефакто. Есть случаи, когда пропустить улов лучше или даже единственный вариант. Особенно при использовании внешних библиотек (где вы не можете контролировать, какие исключения генерируются) и / или асинхронных операций.

Например:

Я хочу создать файл, только если он еще не существует. Я использую внешнюю библиотеку ввода / вывода. Представь File::exists($fileName) а также File::create($fileName) методы.

Вариант 1 (если пропустить улов было возможно):

try {
    File::create($fileName);
}
// Go on with the rest of the code.

Вариант 2 (без try/catch):

if (!File::exists($fileName))
    File::create($fileName);

Здесь вариант 1 является совершенно допустимым, поскольку у варианта 2 есть две важные проблемы:

  1. Если несколько потоков выполняются и проходят через этот раздел кода одновременно, возможно, этот поток A сначала проверяет, существует ли файл. Затем поток B проверяет, существует ли файл. Они оба считают, что его не существует. Поток A создает файл. Затем поток B пытается создать его снова и выдает исключение, даже если вы используете проверку if.
  2. Весьма вероятно, что сама библиотека уже выполняет !File::exists($fileName) проверять. Поэтому вы теряете звонок, который уже сделан.

Заключение

Заявление, что что-то никогда не является хорошей идеей, почти никогда не является хорошей идеей. Всегда есть исключения (хе-хе) из правил. Как и любое соглашение или шаблон дизайна, это просто практическое правило, призванное помочь менее опытным разработчикам принять правильное решение.

Нет.

В любом случае, это вообще плохая идея - поймать исключение и ничего не делать; Исключения существуют именно для того, чтобы заставить вас обработать исключительные обстоятельства (в противном случае выполнение отменяется), поэтому вполне понятно, что язык не способствует такому варианту использования.

Начиная с PHP 8.0 , он может быть введен без переменных, но общий случай для каждой из них теперь . Учебный класс Exceptionреализует Throwable.

      try {
    ...
} catch (CustomException) {
    // CustomException
} catch (Throwable) {
    //All other classes implementing Throwable interface
}

Да, вы можете это сделать, начиная с PHP 8.0. Если вы хотите поймать все исключения, вы можете использовать Throwable.

try {
    ...
} catch (Exception) {
    // Exception
} catch (Throwable) {
    //All other classes implementing Throwable interface
}

Исключения используются не только для исключительных обстоятельств.

Этот сценарий фактически использует исключения, чтобы убедиться, что пользователь вышел из системы. На этом этапе сценария очень дорого обходится, чтобы выяснить, какие данные должны быть удалены, поэтому на самом деле быстрее всего просто удалить все и поймать исключения.

        try {
        GDS::$DB->exec('DELETE FROM sessions WHERE session_id = ' . session_id());
        GDS::$DB->exec('DELETE FROM sessions WHERE user_id = ' . $this->data['user_id']);
    } catch(PDOException $ex) {}
    session_regenerate_id(true);
    setcookie('bis_[user_id]', 0, time() - 1, null, null, false, true);
    setcookie('bis_[session_start]', 0, time() - 1, null, null, false, true);
    setcookie('bis_[session_time]', 0, time() - 1, null, null, false, true);
Другие вопросы по тегам