конструкция finally - неужели бестолковая?

berkut

Новичок
В php нет конструкции finally - гуглил, в том числе и тут - практически хором говорят, что не нужна она..
Вот собсна вопрос по коду, что в нем не так, почему мне так неудержимо хочется finally в данном упрощенном коде..
PHP:
public function proccessTemplateStrict(array $data) {
    $results = array();
    $parser = new RTFParser(); // тут fopen() огромный и часто используемый файл
    try {
        foreach ($data as $k=>$v) {
            $results[] = $parser->replace($k, $v); // тут может кинуться исключение. в данном методе это критично.
        }
    } catch (ParserException $e) {
        writeLog($e); // и эта фунция могет кинуть исключение! 
    } finally {
        $parser->__destruct(); // закрываем там файлик FCLOSE()
    }
    someCode();
}
что я делаю не так?
или такой пример
PHP:
public function proccessTemplate() {
    $parser = new RTFParser();
    try {
        $parser->replace();
    } catch (Exception $e) {
        $parser->__destruct();
        throw new Exception();
    }
    $parser->__destruct(); // тут дублирование кода
    someCode();
}
 

grigori

( ͡° ͜ʖ ͡°)
Команда форума
все исключения - потомки класса Exception, т.е. finally был бы просто синтаксическим сахаром для catch( Exception $E),
try внутри catch тоже работает,
писать логические конструкции надо просто научиться, сложно только тебе
нет смысла усложнять язык лишним ключевым словом
 

berkut

Новичок
grigori ну ок-ок-ок, убедил, я идиот. а что делать со вторым примером?
 

grigori

( ͡° ͜ʖ ͡°)
Команда форума
PHP:
try {
        $parser->replace();
    } catch (Exception $e) {
        try{
            $parser->__destruct();
        }catch (Exception $e) {
            header('500 server error')
            log();
            mail('admin','error');
            exit('<H1>server error</H1>');
        }
    }
 

AmdY

Пью пиво
Команда форума
там же деструктор сам должен вызваться при выходе из метода.
 

berkut

Новичок
AmdY
почему именно "при выходе"? разве сборщик не вызывается хаотично?
grigori
я про второй пример говорил - как избавится от дублирования
 

AmdY

Пью пиво
Команда форума
вот тест кейс
PHP:
class test {
    public function __construct() {
        echo __METHOD__ . '<br/>';
    }
    public function __destruct() {
        echo __METHOD__ . '<br/>';
    }
}
class test2 {
    public function run() {
        $a = new test();
        echo __METHOD__ . '<br/>';
    }
} 
$b = new test2();
$b->run();
echo "test<br/>";
die('END');
test::__construct
test2::run
test::__destruct
test - деструктор срабоал сразу после выхода из метода
END

но это лирика, потому что решает частный случай, а в общем, действительно, происходит дублирование, конструкция бы пыху не помешала.
 

Mols

Новичок
Да всё правильно.
здесь сказано
The destructor method will be called as soon as all references to a particular object are removed or when the object is explicitly destroyed or in any order in shutdown sequence.
А ссылки существующие внутри метода просто обязаны уничтожаться при выходе из этого метода.
Объекты же передаются по ссылке... если передать объект в метод, а при выходе из метода ссылку на такой объект не прибить, то как вообще сборщик то работать сможет?
Так что по доке, похоже сразу при выходе из метода должен и деструктор сработать.
З.Ы.
мне одному странно видеть явный вызов деструктора?
хотя бы так...
PHP:
 unset($parser)
 

Вурдалак

Продвинутый новичок
По-моему, тут кто-то не знает что такое finally, а бросается объяснять. finally — блок кода, выполняющийся всегда после выхода из try/catch вне зависимости от возникшей ситуации (не было исключений или были), к обработке всех исключений это не имеет отношения.
 

Mols

Новичок
Вурдалак
Эм... если это про мой пост, дык я не про finally, а про то когда сработает деструктор))) (откровенно говоря самому стало интересно как этот сборщик сработает, предыдущий пост как раз попытка это понять.)
Хотя в общем то, что такое finally - очевидно из первого поста.
 

Вурдалак

Продвинутый новичок
Mols, как раз в первом посте написана хрень. Ещё раз: finally не имеет отношения к обработке всех исключений.

P.S. В том же C# все исключения тоже являются потомками одного класса, к тому же там есть свой синтаксический сахар вида
Код:
try
{

}
catch
{
    // Любые исключения
}
finally же там служит для других целей.

P.P.S. Более реальный пример из жизни, где finally бы мог пригодиться:
PHP:
<?php
try
{
    $fh = fopen(...);

    // ...
}
catch(Exception1 $e)
{

}
catch(Exception2 $e)
{

}
finally
{
    fclose($fh);
}
Здесь подразумевается, что все ошибки замены исключениями (см. ErrorException).
 

AmdY

Пью пиво
Команда форума
Mols
+1, там ни то что деструктор не должен вызываться, а дрёгаться отдельный метод $parser->close();, потому что с объектом можно ещё и дальше работать, почистив память. но это опять же частности не важные в случае сабжа.

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

Mols

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

fixxxer

К.О.
Партнер клуба
PHP:
try {
   begin();
   copy_tmp_file();
   insert();
   commit();
} catch (Exception $e) {
   rollback();
}
// finally:
unlink_tmp_file();
if (isset($e)) throw $e;
 

Mols

Новичок
fixxxer
эм.... я или гоню, или по идее смысл финали в том, что он отработает даже если
PHP:
try {
    // Здесь бросаем простой Exception который не ловится в catch 
} catch (MySuperException $e) {
   rollback();
} finally {:
unlink_tmp_file();
}
[update]
угу... узрел я, что пример fixxxer позволяет это реализовать)))
отбой.
 

Вурдалак

Продвинутый новичок
Mols, именно так, finally выполняется всегда. Но исключение тут никуда не денется: оно «полетит» дальше после выполнения unlink_tmp_file().

if (isset($e)) по-моему коряво.. гораздо бодрее finally{}..
— язык интерпретируемый, может на этом экономят. В компилируемых пофиг сколько синтаксического сахара будет, тут — нет.
 
Сверху