php знак собаки перед функцией
Знак собаки @ и подавление ошибок в PHP
Последняя модификация: 16.09.2016 г
Страница загружена с адреса: http://webdesign.site3k.ru/consulting/array_walk_error.html
Знак собаки @ и подавление ошибок в PHP
Как-то столкнулся с любопытной проблемой: при обработке массивов функцией вызванной командой array_walk, вместо того, чтобы проверять наличие массива, решил подавить сообщение ошибки, если массива нет. Как говорится, на нет и суда нет. Массив не был обязательной частью данных, он мог быть создан в результате действия предыдущего кода, а мог и не быть, в зависимости от различных условий. При наличии, массив обрабатывался, при отсутствии выдавалось сообщение об ошибке. Вот я и решил не проверять существование массива, а поставить в array_walk собаку, чтобы упростить код.
Я был сильно удивлен, когда обнаружил, что массив перестал обрабатываться.
Далее я создаю 3 тестовых массива с набором слов и для каждого из них вызываю функцию обработки командой array_walk. Но в первом случае я использую array_walk в чистом виде, а в двух следующих использую подавление сообщения об ошибке, если указанного массива не существует. При этом в одном варианте я ставлю собаку перед вызовом функции, а в другом перед именем массива. Вначале мне показалось, что это дает одинаковый результат. Для проверки я вывел содержимое массивов после обработки внутри блока
Внутри функции drink все шло по плану. PHP готов был пить и чай, и молоко, и даже пиво. По крайней мере, вывод на экран внутри функции соответствовал ожидаемому. Но на деле оказалось, что он филонит и тайком выливает виски под стол, потому как при проверке массива через print_r, слово «пить» не присоединилось, ни к пиву, ни к виски.
Почему так происходит, мне совершенно непонятно. Ведь внутри функции все выглядело великолепно независимо от положения собаки при вызове.
Далее последовала проверка подавления ошибки. Вызов обработки несуществующего массива без собаки вполне ожидаемо выдал сообщение об ошибке «аргумент должен быть массивом». Вызов обработки, предваренный собакой, ожидаемо умолчал об ошибке. А вот что будет при вызове с собакой перед массивом, заранее не было известно. То ли PHP будет нем, как рыба, потому что о массиве ему говорить запрещено, то ли начнет жаловаться, что аргумент должен быть массивом. Оказалось, жалуется. Жалуется, если массива нет. Симулирует обработку, если массив есть. То есть, помещение собаки перед массивом не только не отключает сообщение об ошибке, но и само вызывает ошибку при обработке данных.
Только помещение собаки перед вызовом функции дает желаемый результат: если массив есть, он обрабатывается, если его нет, PHP молча проходит мимо.
На последок хочу добавить, что вместо array_walk в большенстве случаев лучше использовать array_walk_recursive, который обработает не только простые массивы, но и многомерные со всеми их уровнями вложенности. Лучше использовать array_walk_recursive сразу, чем потом, в случае изменения массива, проверять, обрабатывается ли он рекурсивно.
Php знак собаки перед функцией
I was confused as to what the @ symbol actually does, and after a few experiments have concluded the following:
* the error handler that is set gets called regardless of what level the error reporting is set on, or whether the statement is preceeded with @
* it is up to the error handler to impart some meaning on the different error levels. You could make your custom error handler echo all errors, even if error reporting is set to NONE.
* so what does the @ operator do? It temporarily sets the error reporting level to 0 for that line. If that line triggers an error, the error handler will still be called, but it will be called with an error level of 0
Hope this helps someone
Be aware of using error control operator in statements before include() like this:
(@include( «file.php» ))
OR die( «Could not find file.php!» );
?>
This cause, that error reporting level is set to zero also for the included file. So if there are some errors in the included file, they will be not displayed.
It’s still possible to detect when the @ operator is being used in the error handler in PHP8. Calling error_reporting() will no longer return 0 as documented, but using the @ operator does still change the return value when you call error_reporting().
My PHP error settings are set to use E_ALL, and when I call error_reporting() from the error handler of a non-suppressed error, it returns E_ALL as expected.
But when an error occurs on an expression where I tried to suppress the error with the @ operator, it returns: E_ERROR | E_PARSE | E_CORE_ERROR | E_COMPILE_ERROR | E_USER_ERROR | E_RECOVERABLE_ERROR (or the number 4437).
I didn’t want to use 4437 in my code in case it changes with different settings or future versions of PHP, so I now use:
And, of course, if your error_reporting settings in PHP is something other than E_ALL, you’ll have to change that to whatever setting you do use.
If you’re wondering what the performance impact of using the @ operator is, consider this example. Here, the second script (using the @ operator) takes 1.75x as long to execute. almost double the time of the first script.
Error suppression should be avoided if possible as it doesn’t just suppress the error that you are trying to stop, but will also suppress errors that you didn’t predict would ever occur. This will make debugging a nightmare.
It is far better to test for the condition that you know will cause an error before preceding to run the code. This way only the error that you know about will be suppressed and not all future errors associated with that piece of code.
There may be a good reason for using outright error suppression in favor of the method I have suggested, however in the many years I’ve spent programming web apps I’ve yet to come across a situation where it was a good solution. The examples given on this manual page are certainly not situations where the error control operator should be used.
Please be aware that the behaviour of this operator changed from php5 to php7.
The following code will raise a Fatal error no matter what, and you wont be able to suppress it
Quick debugging methods :
There is no reason to NOT use something just because «it can be misused». You could as well say «unlink is evil, you can delete files with it so don’t ever use unlink».
?>
There are only 2 possible problems here: a missing variable or a missing index. If you’re sure you’re fine with both cases, you’re good to go. And again: suppressing errors is not a crime. Not knowing when it’s safe to suppress them is definitely worse.
After some time investigating as to why I was still getting errors that were supposed to be suppressed with @ I found the following.
1. If you have set your own default error handler then the error still gets sent to the error handler regardless of the @ sign.
Escape-последовательности и числовые нотации в PHP
Привет, Хабр. В преддверии старта онлайн-курса «PHP-разработчик» подготовили традиционный перевод материала. Предлагаем также посмотреть запись прошедшего демо-занятия «Экосистема PHP».
Многие современные языки программирования поддерживают различные способы использования различных символов, таких как обычные английские латинские буквы, числа, символы, эмодзи и различные специальные символы, такие как символ новой строки или символ табуляции.
PHP, наряду со многими другими языками программирования, поддерживает определенное количество escape-последовательностей для использования различных символов, которые не могут быть набраны с обычной клавиатуры, не могут быть представлены в текстовой форме (например, невидимые символы или различные управляющие символы) или иным образом не считываются. Эти символы используют escape-последовательности, которые распознает PHP.
Что касается чисел, PHP поддерживает стандартные десятичные числа, но также может использовать и другие нотиции, такие как двоичное, восьмеричное, шестнадцатеричное и даже научное (scientific) представление. Они могут сделать код более читаемым и понятным в зависимости от контекста.
Двойные кавычки и Heredoc
В PHP строка с двойными кавычками ( «string» ) или Heredoc (смотрите ниже) поддерживает escape-последовательности и интерполяцию переменных.
PHP будет пытаться интерполировать переменные, если строковый литерал находится внутри строки с двойными кавычками или Heredoc.
Альтернативно (и желательно) интерполируемые переменные могут быть выделены фигурными скобками, так они будут выглядеть более удобочитаемыми:
Строки в одинарных кавычках ( ‘string’ ) и синтаксис Nowdoc не интерполируют переменные:
Только строки в двойных кавычках и Heredoc поддерживают escape-символы.
Экранирование символов
Поскольку PHP интерпретирует и интерполирует специальные символы внутри строковых литералов в двойных кавычках и heredoc, знак обратной косой черты ( \ ) используется как «escape-символ».
Использование второго символа обратной косой черты предотвращает преобразование первого символа обратной косой черты в escape-символ.
Символы табуляции: \t и \v
Новые строки: \r и \n
\r («возврат каретки») и \n («перевод строки») являются символами новой строки.
Escape-символ: \e
Если приведенный выше фрагмент выполняется в терминале, который поддерживает управляющие последовательности ANSI, он интерпретирует его и изменяет текст:
Символ новой страницы: \f
Восьмеричные escape-последовательности символов ASCII
PHP поддерживает экранирование восьмеричного числа в его соответствующий ASCII символ.
Для символа P можно использовать восьмеричную escape-последовательность:
Любой базовый символ ASCII можно представить с помощью такой записи:
Любое значение в диапазоне от \0 до \377 будет интерпретироваться как восьмеричная escape-последовательность ASCII символа.
Обратите внимание, что числа для расширенных символов ASCII (от 128 до 255) несовместимы с UTF-8. PHP считает значение 128 (восьмеричное: 200 ; шестнадцатеричное: 80 ) недопустимым, поскольку оно не является допустимым значением UTF-8.
Хотя PHP принимает такие значения, они считаются недопустимыми символами в контексте UTF-8.
Шестнадцатеричные escape-последовательности символов ASCII
Кроме того, шестнадцатеричные символы не чувствительны к регистру (т.е. AF равно af и aF ).
Тот же «PHP.Watch» пример можно переписать с помощью шестнадцатеричных escape-последовательностей:
Escape-последовательности символов Unicode
PHP поддерживает использование любого Unicode символа с префиксом \u и шестнадцатеричным значением code point внутри фигурных скобок.
PHP выдаст ошибку парсера, если символ Unicode превышает значение 10FFFF :
Форму записи Unicode \u<> можно использовать качестве escape-последовательности для любого символа. Вот несколько примеров:
Символ
Code point (Dec)
Code point (Hex)
Escape-последовательность Unicode
Регулярные выражения для самых маленьких
Меня зовут Виталий Котов и я немного знаю о регулярных выражениях. Под катом я расскажу основы работы с ними. На эту тему написано много теоретических статей. В этой статье я решил сделать упор на количество примеров. Мне кажется, что это лучший способ показать возможности этого инструмента.
Некоторые из них для наглядности будут показаны на примере языков программирования PHP или JavaScript, но в целом они работают независимо от ЯП.
Из названия понятно, что статья ориентирована на самый начальный уровень — тех, кто еще ни разу не использовал регулярные выражения в своих программах или делал это без должного понимания.
В конце статьи я в двух словах расскажу, какие задачи нельзя решить регулярными выражениями и какие инструменты для этого стоит использовать.
Вступление
Регулярные выражения — язык поиска подстроки или подстрок в тексте. Для поиска используется паттерн (шаблон, маска), состоящий из символов и метасимволов (символы, которые обозначают не сами себя, а набор символов).
Это довольно мощный инструмент, который может пригодиться во многих случая — поиск, проверка на корректность строки и т.д. Спектр его возможностей трудно уместить в одну статью.
В PHP работа с регулярными выражениями заключается в наборе функций, из которых я чаще всего использую следующие:
Функции на match возвращают число найденных подстрок или false в случае ошибок. Функция на replace возвращает измененную строку/массив или null в случае ошибки. Результат можно привести к bool (false, если не было найдено значений и true, если было) и использовать вместе с if или assertTrue для обработки результата работы.
В JS чаще всего мне приходится использовать:
Пример использования функций
В PHP регулярное выражение — это строка, которая начинается и заканчивается символом-разделителем. Все, что находится между разделителями и есть регулярное выражение.
Часто используемыми разделителями являются косые черты “/”, знаки решетки “#” и тильды “
”. Ниже представлены примеры шаблонов с корректными разделителями:
Создать регулярное выражение можно так:
Или более короткий вариант:
Пример самого простого регулярного выражения для поиска:
В этом примере мы просто ищем все символы “o”.
В PHP разница между preg_match и preg_match_all в том, что первая функция найдет только первый match и закончит поиск, в то время как вторая функция вернет все вхождения.
Пример кода на PHP:
Пробуем то же самое для второй функции:
В последнем случае функция вернула все вхождения, которые есть в нашем тексте.
Тот же пример на JavaScript:
Модификаторы шаблонов
Для регулярных выражений существует набор модификаторов, которые меняют работу поиска. Они обозначаются одиночной буквой латинского алфавита и ставятся в конце регулярного выражения, после закрывающего “/”.
О том, какие вообще бывают модификаторы, можно почитать тут.
Пример предыдущего регулярного выражения с модификатором на JavaScript:
Метасимволы в регулярных выражениях
Примеры по началу будут довольно примитивные, потому что мы знакомимся с самыми основами. Чем больше мы узнаем, тем ближе к реалиям будут примеры.
Чаще всего мы заранее не знаем, какой текст нам придется парсить. Заранее известен только примерный набор правил. Будь то пинкод в смс, email в письме и т.п.
Первый пример, нам надо получить все числа из текста:
Чтобы выбрать любое число, надо собрать все числа, указав “[0123456789]”. Более коротко можно задать вот так: “7”. Для всех цифр существует метасимвол “\d”. Он работает идентично.
Но если мы укажем регулярное выражение “/\d/”, то нам вернётся только первая цифра. Мы, конечно, можем использовать модификатор “g”, но в таком случае каждая цифра вернется отдельным элементом массива, поскольку будет считаться новым вхождением.
Для того, чтобы вывести подстроку единым вхождением, существуют символы плюс “+” и звездочка “*”. Первый указывает, что нам подойдет подстрока, где есть как минимум один подходящий под набор символ. Второй — что данный набор символов может быть, а может и не быть, и это нормально. Помимо этого мы можем указать точное значение подходящих символов вот так: “
Сейчас будет пара примеров, чтобы это уложилось в голове:
Примерно так же мы работает с буквами, не забывая, что у них бывает регистр. Вот так можно задавать буквы:
Такое выражение выберет все слова, которые есть в предложении и написаны кириллицей. Нам нужно третье слово.
Помимо букв и цифр у нас могут быть еще важные символы, такие как:
Если мы точно знаем, что искомое слово последнее, мы ставим “$” и результатом работы будет только тот набор символов, после которого идет конец строки.
То же самое с началом строки:
Прежде, чем знакомиться с метасимволами дальше, надо отдельно обсудить символ “^”, потому что он у нас ходит на две работы сразу (это чтобы было интереснее). В некоторых случаях он обозначает начало строки, но в некоторых — отрицание.
Это нужно для тех случаев, когда проще указать символы, которые нас не устраивают, чем те, которые устраивают.
Допустим, мы собрали набор символов, которые нам подходят: “[a-z0-9]” (нас устроит любая маленькая латинская буква или цифра). А теперь предположим, что нас устроит любой символ, кроме этого. Это будет обозначаться вот так: “[^a-z0-9]”.
Выбираем все “не пробелы”.
Итак, вот список основных метасимволов:
Операторы [] и ()
По описанному выше можно было догадаться, что [] используется для группировки нескольких символов вместе. Так мы говорим, что нас устроит любой символ из набора.
Тут мы собрали в группу (между символами []) все латинские буквы и пробел. При помощи <> указали, что нас интересуют вхождения, где минимум 2 символа, чтобы исключить вхождения из пустых пробелов.
Аналогично мы могли бы получить все русские слова, сделав инверсию: “[^A-Za-z\s]<2,>”.
В отличие от [], символы () собирают отмеченные выражения. Их иногда называют “захватом”.
Они нужны для того, чтобы передать выбранный кусок (который, возможно, состоит из нескольких вхождений [] в результат выдачи).
Существует много решений. Пример ниже — это приближенный вариант, который просто покажет возможности регулярных выражений. На самом деле есть RFC, который определяет правильность email. И есть “регулярки” по RFC — вот примеры.
Мы выбираем все, что не пробел (потому что первая часть email может содержать любой набор символов), далее должен идти символ @, далее что угодно, кроме точки и пробела, далее точка, далее любой символ латиницы в нижнем регистре…
Получилось! Но что, если теперь нам надо по отдельности получить домен и имя по email? И как-то использовать дальше в коде? Вот тут нам поможет “захват”. Мы просто выбираем, что нам нужно, и оборачиваем знаками (), как в примере:
В массиве match нулевым элементом всегда идет полное вхождение регулярного выражения. А дальше по очереди идут “захваты”.
В PHP можно именовать “захваты”, используя следующий синтаксис:
Тогда массив матча станет ассоциативным:
Это сразу +100 к читаемости и кода, и регулярки.
Примеры из реальной жизни
Парсим письмо в поисках нового пароля:
Есть письмо с HTML-кодом, надо выдернуть из него новый пароль. Текст может быть либо на английском, либо на русском:
Сначала мы говорим, что текст перед паролем может быть двух вариантов, использовав “или”.
Вариантов можно перечислять сколько угодно:
Далее у нас знак двоеточия и один пробел:
А дальше нас интересует все, что не символ “
Использование @
Доброго времени суток.
Встретился с использованием оператора @, но не знаю для чего он. Прошу, Вас, по возможности, объяснить что делает данный оператор. Или дать ссылки на статьи.
Работа с двумерными числовыми массивами. Использование указателей. Использование функций пользователя.
Помогите пожалуйста. Сделать три варианта: первый вариант – передача данных между.
Создание и использование своих @NamedQueries. Использование EntityManager
Добрый день! Создавал классы сущностей и сессий через NetBeans генераторы кода. Использование.
Использование строк.Использование структур
Задачка: Дана строка,состоящая из групп нулей и едениц. Найти и вывести на экран группы с нечетным.
Да я ни за ни против. Просто говорю, что не всегда это так.
И таких примеров есть. А посему это:
не всегда верно. Иногда можно и даже должно.
А никто и не спорит.
Вообще лошадь на 4 ногах и то спотыкается. В любом программном продукте возможны ошибки. PHP не исключение, в нем тоже не все гладко. И хорошо, что есть инструменты, позволяющие эти шероховатости безболезненно сгладить.
Нельзя все отметать вчистую.
Если вы не любите собак, значит вы просто не умеете их готовить. (с) Корейская мудрость.
Добавлено через 30 минут
kester
Кстати, раз на то пошло. Ваш код плох хотя бы тем, что ошибки уровня WARNING не останавливают скрипт. А значит он становится заложником обстоятельств. С теми же правами. А вот пожалуйста и права и прочее:
Решение
«Безболезненно», говорите? Собака делает всё настолько «гладко», что с тем же успехом можно закрыть глаза, зарыть голову в песок и притвориться, что не видел, и что меня/тебя это не касается. Вот и нет проблемы. Но проблема от этого никуда не девается.
Используя собаку, Вы прячетесь от абсолютно любых ошибок, а не только от той, которую ожидали. В большинстве случаев Вы не можете быть уверены на 100%, что в данном месте не могут возникнуть никакие другие проблемы, кроме ожидаемой. Не следует забывать тонкую разницу между сообщениями об ошибках и настоящими источниками ошибок. Много разных причин могут привести к одному ошибочному результату.
Лично я, как настоящий параноик, не пожалею полграмма ресурсов на лишние 42 проверки в пользу диагностики, чтобы предусмотреть любой разумный вариант исхода. И никакие логи нигде не забьются бесполезными сообщениями. Зато потом ни я, ни, тем более, кто-то другой не будете выдирать волосы на голове в поисках черной кошки в черной комнате. Лучше пусть программа работает правильно и чуть более качественно, насколько у меня хватит способностей, чем быстро и хрен пойми как.
Любой фрагмент кода выполняет свою задачу. Если код выполнился без ошибок, значит он всё сделал именно так, как задумал его создатель. Мне не нужен код, который радостно мне сообщает, что всё прошло успешно, когда на самом деле это не так. Пусть он лучше из кожи вылезет, засрет мне все логи и все почтовые ящики, но об ошибке я должен знать.
На моей машине первый цикл отрабатывает в среднем за 1.5 сек, второй за 12.5. Что же я такого не знаю об этом операторе?
И откуда столько сарказма: святая водичка, религиозные нормы, недоверие под покровом ночи? Мы кажемся маленькими и тупыми с высоты Ваших безмерных познаний?
Согласен с Vovan-VE: профессиональный программист обязан быть параноиком.
Хорошо, я понял. У нас разные взгляды на программирование. Я придерживаюсь принципа KISS, у вас здоровая доля паранойи. Обе точки зрения имеют права на жизнь.
Но вот с этим я не соглашусь:
Не от любых, а именно от тех, которые, как вы и сами заметили, обусловлены «кривизной архитектуры языка».
Вернемся к unlink(). Функция вполне логично возвращает true в случае успешного завершения и false в случае фиаско. Этого вполне достаточно для дебаггинга. На кой ляд она еще и генерирует WARNING? Или допустим почившая в бозе mysql_result(). C какой целью она генерирует ошибку, если успешный запрос не вернул ни одной строчки? Причем тут вообще PHP. Или к примеру file_get_contents() с удаленными файлами?
Ну какая польза от логов, в которых будет записано
если это временное помешательство сбой связи? Ну никакой практической пользы.
Нет, я понимаю, когда это специальный лог (журнал), но он не имеет отношения к интерпретатору ошибок.
Добавлено через 23 минуты
philin,
Вот вы не правы, как и многие, кто пытается познать истину подобными тестами.
Вы пытаетесь сравнить время выполнения кода с оператором @ и без него. Разумеется, любой оператор требует времени и памяти. Однако вы забываете, что если не ставить собаку, придется делать другие проверки. И вот теперь напишите подобный тест на тот код, который привел в пример kester. Ну я помогу:
Добавлено через 2 минуты
Ненене, секундочку. Я не предлагал использовать собаку при обращениях к переменной. Ну уж коль на то пошло, ладно. Что показывает ваш тест. Что код с собакой работает в три раза медленее чем с isset()? Ну да, так и есть. Только одно но. В каком страшном сне может привидится 10! миллионов. обращений? А если уменьщить количество итераций в вашем тесте до хоть как то вписывающиеся в рамки разумного 1000, то абсолютная разница (не в процентах) не выйдет за рамки погрешности. Да и представить себе скрипт, в котором будет 1000 проверок на существование переменной я как то очень слабо могу.
О каком реальном (не теоретическом) выигрыше в скорости мы сейчас рассуждаем? В 1-2 пикосекунды на весь скрипт?
Ну а вернувшись к нашим баранам, все же напомню. Что я не призывал cтавить собаку везде и всюду. Тем паче в обращениях к переменной. Но в тех местах, где она действительно полезна, там и по скорости вопросов не возникает. Тест вы видели.
Не соглашусь с Вами также в том, что не важна причина, по которой файл не смог удалиться (мне показалось, Вы именно так это преподносите), по которой соединение порвалось и т.п. Если соединение рвется 1 раз в неделю в пятницу вечером, то я, видя такую статистику, еще соглашусь, что это в определенной степени допустимо. Но если, например, в той же статистике я увижу, что соединение врется несколько раз у сутки, то это уже проблема, и её надо как-то решать, если это возможно.
А без инфы об ошибках я вообще ничего никогда не узнаю. Получится т.н. синдром УМВР.
С причинами неудаления файла та же история. Возможные варианты причин уже писали выше.
Если ошибка (любая где бы то ни было) возникла не по моей вине, а по сторонним причинам, то и не мне брать на себя ответственность скрывать факт этой ошибки. Например, если не я [процесс, вызвавший unlink()] создал ситуацию, из-за которой удаление не прошло, то и не мне принимать решение, что с этим дальше делать (а, действительно, админ забыл раздать права, я-то [процесс, вызвавший unlink()] здесь прием? ваши проблемы, вы [люди] с этим сами и разбирайтесь).
Антипример того, что я хочу выразить, хоть и надуман и маразматичен, но главное смысл: