try/catch/finally

  • Автор темы autosoft
  • Дата начала

autosoft

Guest
try/catch/finally

Использую PHP 5.0.4
Конструкиция finally в языке отсутвует.

Возник вопрос - кто и как это обходит? Поделитесь опытом.

К примеру нужен следующий участок кода:

PHP:
global $variable;
$variable = 0;

try {
...
$variable++;
...
} finally {
$variable = 0;
}
То есть необходимо обнулить переменную независимо от того – было исключение или нет.
 

Profic

just Profic (PHP5 BetaTeam)
Я - никак.
Потому что объекты в php ведут себя почти так же как и в c++, которому finally не нужен. Т.е. объект убивается как только терят последнюю ссылку на себя. Читать в гугле про RAII или "Resource Acquisition Is Initialization".
 

autosoft

Guest
Причем тут объекты?
Например, нужно закрыть файл, а исключение, возникшее в процессе обработки файла, должно остаться.
 

Profic

just Profic (PHP5 BetaTeam)
autosoft
Притом. Есть такая вещь как RAII. Или ты идешь и читаешь что это такое и как это использовать или мне не о чем с тобой разговаривать.
 

autosoft

Guest
Profic
Меня не интерисует создание/удаление обектов из памяти.
Меня интерисует только их инициализация.

Поэтому вопрос ко всем кто понимает зачем нужен блок finally в обработке исклютечений.

Альтернативой кода (из Delphi):
try
...
except
...
end;

в PHP есть:
PHP:
try {
...
} catch (...) {
...
}
end;
Как в PHP записать (или чем заменить) конструкцию (из Delphi):
try
...
finally
...
end;
 

Andreika

"PHP for nubies" reader
PHP:
try { 
... 
$variable++; 
... 
} catch{ 
...
}
$variable = 0;
так? :)
или для полного щастья

PHP:
$exc = null;
try {
//  ...
$var++;
} catch (Exception $e) {
  $exc = $e;
}
// finally block )
$var = 0;
if ($exc) throw $exc;
ток зачем оно?
 

Profic

just Profic (PHP5 BetaTeam)
autosoft
Ок, специально для лентяев, или альтернативно одаренных - вот уж не знаю):
PHP:
<?php
class VariableSetter {
	private $var = NULL;
	private $val = NULL;
	public function __construct(&$var, $val) {
		$this->var =& $var;
		$this->val = $val;
	}
	public function __destruct() {
		$this->var = $this->val;
	}
}

function test($throw) {
	global $variable;
	try {
		$reset = new VariableSetter($variable, 0);
		++$variable;
		if ($throw) throw new Exception("test");
	} catch (Exception $e) {}
}

$variable = 0;

test(false);
echo $variable . "\n";

test(true);
echo $variable . "\n";
?>
И неужто ты думаешь, что я не знаю и не понимаю зачем НЕ нужен finally в C++ и PHP?
 

autosoft

Guest
Profic
Ты предлагаеш каждый раз писать этот (или подобный ему) код?!

По поводу "понимаешь ты или нет зачем нужен finally". Я думаю, что не понимаешь – иначе не предлагал бы такой громоздкий вариант. Кстати, Andreika, во втором варианте, более элегантный код предлагает. Учись у него.
 

Profic

just Profic (PHP5 BetaTeam)
Хи-хи, не смешите мои тапочки. Громоздкий код? Одна строчка с созданием чистильщика? То что этот класс будет использоваться везьде где нужно и на самом деле съэкономит кучу написанного кода в голову не приходило?
Я прекрасно знаю зачем нужен finally в Java. Насчет delphi не знаю, а вот в php он не нужен. С единственным исключением: такой подход невозможно использовать в глобальном пространстве имен. Однако это не такая большая проблема. К тому же, если finally нет в php, то значит он там и не нужен.
 

autosoft

Guest
Profic
Областью видимости такого "чистильщика" в PHP и Delphi будет тело функции. В то время как в С++ это составной оператор. Поэтому деструктор "чистильщика" в PHP будет вызван после выполнения всей функции, но для имитации finally нужен вызов сразу за последним catch.

Это хорошо видно если изменить функцию test на следующую:

PHP:
function test($throw) { 
    global $variable; 
    try { 
        $reset = new VariableSetter($variable, 0); 
        ++$variable; 
        if ($throw) throw new Exception("test"); 
    } catch (Exception $e) {} 
    echo $variable;
}
Вообщем RAII для C++ себя может и оправдывает, а вот в случае с PHP - это полная чепуха.

И ещё. Конструкция finally сохраняет исключение. Твой пример его "блокирует".
 

Profic

just Profic (PHP5 BetaTeam)
autosoft
Ок, нужен finally? Пошли патч разработчикам. Мне он еще ни разу не нужен был.
Для кода написанно на коленке, возможно, finally и нужен. Если же придерживаться правила одна функция/метод - одно действие, то никто не мешает использовать такую технику. Насчет "блокирует", убери try/catch из тела функции и всех делов.
 

autosoft

Guest
Profic
Форум не для тебя одного. Не знаеш или сомневаешся - спрашивай, читай книги, учись.

По поводу "необхимости finally в коде написаном на коленке". За это просто браво! Теперь всем наконецто стало понятно зачем же он этот самый finally в других языках нужен. Ну и для написания какого кода они, языки соответственно, годятся :).
 

autosoft

Guest
-~{}~ 25.11.05 01:22:

PHP:
echo "<table><tr><td>";

$exception = NULL;

try {

    ...

} catch (Exception $e) {

    $exception = $e->getMessage();
}

echo "</td></tr></table>";

if (!is_null($exception)) throw new Exception($exception);
-~{}~ 25.11.05 01:23:

PHP:
echo "<table><tr><td>";

$exception = NULL;

try {

    ...

} catch (Exception $e) {

    $exception = $e->getMessage();
}

echo "</td></tr></table>";

if (!is_null($exception)) throw new Exception($exception);
 

Nirva

Dmitry Polyakov
autosoft
товарищ, вы перепрограммировали на дельфи и сейчас придумываете проблему.

за сим. реальный код вследствие которого у вас возник такой вопрос?
 

Andreika

"PHP for nubies" reader
Nirva
товарисч, давайте вы дадите реальный php код в котором жизненно нужны исключения, а я потом постараюсь накатать код с finally :)
 

autosoft

Guest
Nirva
Проще говоря этот пример надуманный? Ну и что?
Если ставить задачу: чистый и понятный код + чистый вывод результатов его выполнения (например, исключить возможные искажения отображения результатов в браузере вследствие ошибок), то используя исключения без finally не обойтись.

Кстати предыдущий пример с finally мог бы выглядеть следующим образом:
PHP:
echo "<table><tr><td>";

try {

    ...

} finally {

    echo "</td></tr></table>";
}
Разницу чувствуем?

Кстати по поводу программирования в Delphi и Вам советую – расширяет кругозор.
 

BeGe

Вождь Апачей, блин (c)
А чем будет оличаться такой код....
PHP:
try {
    echo "<table><tr><td>";
    ...
    echo "</td></tr></table>";
} catch(e) {
    echo "<table><tr><td>";
    echo "</td></tr></table>";
}
Дублирование ? Ок не проблема.

PHP:
try {
    $table->drawHeader();
    ...
    $table->drawFooter();
} catch(e) {
    $table->drawHeader();
    $table->drawFooter();
}
Опять дублирование ? ну не знаю...
 

svetasmirnova

маленький монстрик
autosoft
>то используя исключения без finally не обойтись.
Исключения удобная вещь, но и без них можно обойтись.
For и while удобная вещь, но и без них можно обойтись.
Изучение первых языков программирования расширяет кругозор ;)
 

Nirva

Dmitry Polyakov
autosoft
спасибо, за заботу о кругозоре.
вобщем, реального кода нет. вы пытаетесь перенести знакомую вам логику туда, где она просто не нужна.
лучший вариант решения такой вещи - начать с четвертой версии пхп.

-~{}~ 25.11.05 14:54:

...расширяет кругозор ;)
 
Сверху