Comments 73
А вообще, кому как удобней.
я даже не поленился проверить, чтобы уличить вас во лжи!
Спутал с похожей функцией, которую предлагали в комментах мануала php:
Beware that the chk() function below creates the variable or the array index if it didn't existed.
<?php
function chk(&$var) {
if (!isset($var))
return NULL;
else
return $var;
}
Вот так создается индекс:
chk($a['b']);
Сам использую собак только в @mysql_connect/@mysql_select_db.
Есть четкие правила использования оператора @:
* общее - только перед встроенными функциями:
$f = @fopen($fname);
$d = @mysql_connect(...);
@mkdir(...)
* при проверке возможно неинициализированных переменных: if(@$_POST['var'])
* Когда лень писать много кавычек в массивах: @$arr[element1][element2][element3]
В остальных случаях использование данной директивы не рекомендуется.
Ни в коем случае нельзя использовать оператор @ перед:
* директивой include(), так как подавятся все сообщения об ошибках во включаемом файле.
* перед вызовом собственных функций.
* перед функцией eval()
Замечу также, что оператор @ лишь подавляет вывод сообщений об ошибках в браузер. В логи сообщения будут продолжать писаться (при включенном log_error, конечно же)
Собака, ради того, чтобы не ставить кавычки — по-моему уже перебор.
да, варнингы во многих фукнциях, если что-то идет не так, раздражают. Очень. Но когда ты девелопишь, они в тоже время очень сильно тебе помогают. Потому как я сейчас не могу вспомнить ни одного случая когда варнинг был мог бы присутсвовать в нормальной ситуации.
А про забитие на кавычки в массивах и isset при проверке входящих данных(который вообще пишется только один раз и помещается в какой-нибудь компонент работаютщий) - за это, извините, но надо избивать. Причем до тех пор, пока человек не поймет, что если он будет писать номральный грамотный и читаемый код, который сам ему подскажет что к чему - то он так и будет тратить 80% своего времени заниямась рутинным кодингом.
Но не стоит, однако, путать лень хорошего программиста, с нежеланием быдлокодера писать хороший код. Первый знает что и почему он делает; второй делает, чтобы "замазать", спрятать надоедающие вещи, не понимая причины их появления и нежелая их исправлять.
Вся тонкость оператора @ как раз состоит в том, что при и только при правильном его применении он позволяет написать короткий и элегантный код.
Однако, опять же, обращаю ваше внимание на то, что использование оператора @ в _законченных_ скриптах не рекомендуется - лучше применять его только при отладке.
}
вместо
if(isset($_POST['varname'])){
}
И продолжить тем, что обращатся напрямую к посту, в нормальном приложении - дурной тон, как уже было сказанно выше (с приведенными примерами), лучше написать функцию\класс для работы с енвиронментом. Вопервых, мы избавим себя от рутинного кода в будущем, во вторым - сократим количество потенциальных дыр и улучшим читабельность.
В треитьих, посудите сами как будет выглядить такой код, если нам нужно будет вытащить несколько переменных из поста\гета?
То есть, первое условие вернет false, а второе - true.
Это основная проблема.
Warning: mail() [function.mail]: SMTP server response:… (тут код и описание ошибки, их бывает довольно много, например Invalid Address, Unable to relay for xxx@xxx.xx, и т.д.)
function getRequestParameter($key, $default = null)
{
if(isset($_REQUEST[$key])) return $_REQUEST[$key];
else return $default;
}
п.с.: возможны опечатки, т.к. писал прямо здесь.
можно модифицировать, чтобы брать значения только из гет, или только из пост, а не всего реквеста
class Request {
 l lpublic function getQueryParam($name, Filter $filter, $default = null) {
 l l l lif(isset($_GET[$name])) {
 l l l l l lreturn ($filter)? $filter->apply($name) : $_GET[$name];
 l l l l}
 l l l lelse {
 l l l l l lreturn $default;
 l l l l} l l l
 l l}
 l l//...
}
Фильтры кстати тоже пишутся за час-два до приемлимого уровня ;)
Ну а вообще стоит написать функцию типа getGET, которой третим параметром нужно подать еще и тип ожидаемого значения. А внутри уже распарсить.
Если потратить побольше времени и не полениться хорошо написать, функция вполне себе подойдет для копи-пастов в следующих проектах.
Вот как раз в этом куске кода, что бросил сюда из своего прожекта, этот параметр вообщем-то не и нужен - все это длается именно в фильтре(у меня куча различных фильтров на каждый тип данных со своими фишками ), по нему уже определяем какой типа нам нужен, и если к примеру нам нужен инт или флоат, а получаем строку, то можем выкинуть и UnexpectedValueException, если захотим. Или постараемся преобразовать ;)
Единственное, где можно использовать - исключительные случаи при чтении потоков на IIS, и некоторые другие.
Вот мое решение:
Файл MyException.class.php:
class MyException extends Exception {
public function __construct($message, $errorCode = 0, $errorFile = '', $errorLine = 0) {
parent::__construct($message, $errorCode);
$this->file = $errorFile;
$this->line = $errorLine;
}
}
set_error_handler(create_function('$c, $m, $f, $l', 'throw new MyException($m, $c, $f, $l);'), E_ALL);
?>
Далее в коде пишем так:
try {
$a = 57 / 0;
}
catch (Exception $e) {
echo $e;
}
Пояснения по коду:
По умолчанию, в 5-м PHP ошибки и исключения - это разные вещи, что странно. Поэтому просто ошибка при вызове функции исключения не вызовет.
Да и смысл всего этого действа, ведь на E_ALL, эксепшн вылезет даже там, где будет кинут простой notice.
И кстати. Ошибки и исключения - это разные механизмы.
- А кто мешает использовать нормальный call-back? Мне нравятся лямбда-функции, но вы можете использовать то, что вам удобнее
- Кто мешает вместо E_ALL поставить любую комбинацию уровней error reporting допустимых в error_reporting()? Не нравится notices? Используем в коде E_ALL & ~E_NOTICE!
- Читайте внимательно мои пояснения к моему же коду :)
Лично мне кажется, что исключения более эффективный механизм контроля и обработки ошибок нежели стандартные средства, пришедшие из старых версий. Во-первых, наследование, во-вторых, сквозная генерация ошибок (во вложенных функциях и методах)
lambda-функции сейчас, может, неэффективны в силу некоторых особенностей, но в предверии выхода PHP 5.3 уже можно потихоньку на них переходить, поскольку в этом релизе ситуация изменится кардинально!
И еще одно насчет notices: The following error types cannot be handled with a user defined function: E_ERROR, E_PARSE, E_CORE_ERROR, E_CORE_WARNING, E_COMPILE_ERROR, E_COMPILE_WARNING, and most of E_STRICT raised in the file where set_error_handler() is called. Так что не волнуйтесь, E_NOTICE в исключение не передается.
Подробнее о lambda-функциях
Скопировал ваш код, запустил:
try {
$_POST['b'];
}
catch (Exception $e) {
echo $e;
}
Получил, как и ожидал: exception 'MyException' with message 'Undefined index: b' in D:\Web\home\localhost\htdocs\dev\Nano\index.php:45 Stack trace: #0 D:\Web\home\localhost\htdocs\dev\Nano\index.php(45): __lambda_func(8, 'Undefined index...', 'D:\Web\home\loc...', 45, Array) #1 {main}
Правда у меня нотисы я все таки выкинул, с помощью switch($errno), на E_NOTICE... так спокойнее.
Что exception вывело на экран? Так там echo стоит... Обрабатывайте как хотите.
Если вы по поводу того, что WARNING выкинул Exception, то опять же, отключите E_WARNING в set_error_handler.
Вот только что проверил - работает:
set_error_handler(create_function('$c, $m, $f, $l', 'throw new MyException($m, $c, $f, $l);'), E_ALL & ~E_NOTICE);
Во-первых, зачем красиво оформлять notice, если он предназначен только для разработчика? Во-вторых, а как бы вы красиво оформляли notice, не используя Exceptions - только стандартными функциями PHP?
Второй параметр в callback-функции ($errorCode) - это на самом деле:
the level of the error raised, as an integer
Так что переопределяйте метод __toString и вперед, за орденами:
public function __toString() {
if ($this->code === E_NOTICE) {
echo "Это красивый notice!!!";
}
}
Я бы правда вынес нотис за грани эксепшна и проверял, что это нотис на уровне call-back-а (как вариант кидать NoticeException ;) ) и как-нибудь его выводил, хоть одной строкой, тут уже все равно.
Выводить notice прямо в callback - наиболее приемлемое, на мой взгляд, решение. Оно позволяет в случае обхода массива в цикле вывести все notices, а не только первый.
Теперь вы согласны, что исключения в PHP более прогрессивный инструмент нежели стандартные ошибки и его можно и нужно заменять?
НИКОГДА не юзайте собаку, кроме случаев, когда без нее никак (например @mail()). @ просто скрывает сообщение об ошибке, но оно все равно генерируется. А значит, кроме всего еще и время тратится лишнее. За всякие @$v[s] и @$_GET['ddd'] надо убивать.
// old code
$foo = isset($_GET['foo']) ? $_GET['foo'] : 42;
// new code
$foo = $_GET['foo'] ?: 42;
Аха, нашел описание тут http://www.php.net/~derick/meeting-notes…
По сути он делит ошибки на три вида - debug, warning, error и выводит их по соответствующим правилам. Можно назвать это расширенным логгером с возможностью тонкой настройки вывода ошибок (либо на экран либо в лог файл).
PHP. Собака — зло?