Php check if fatal error

PHP Unit Tests: Is it possible to test for a Fatal Error?

FWIW I’m using SimpleTest 1.1alpha. I have a singleton class, and I want to write a unit test that guarantees that the class is a singleton by attempting to instantiate the class (it has a private constructor). This obviously causes a Fatal Error:

Oldschool unit test frameworks are unfit for that. Write a PHPT for that test and mingle it into a PHPUnit/SimpleTest case using a regex on the output.

3 Answers 3

No. Fatal error stops the execution of the script.

And it’s not really necessary to test a singleton in that way. If you insist on checking if constructor is private, you can use ReflectionClass:getConstructor()

public function testCannotInstantiateExternally() < $reflection = new \ReflectionClass('\My\Namespace\MyClassName'); $constructor = $reflection->getConstructor(); $this->assertFalse($constructor->isPublic()); > 

Another thing to consider is that Singleton classes/objects are an obstacle in TTD since they’re difficult to mock.

Here’s a complete code snippet of Mchl’s answer so people don’t have to go through the docs.

public function testCannotInstantiateExternally() < $reflection = new \ReflectionClass('\My\Namespace\MyClassName'); $constructor = $reflection->getConstructor(); $this->assertFalse($constructor->isPublic()); > 

You can use a concept like PHPUnit’s process-isolation.

This means the test code will be executed in a sub process of php. This example shows how this could work.

In practice, this only works for detecting syntax errors, because (1) a script does not usually survive isolated, (2) it’s unfeasible to bootstrap an entire application like this, (3) it does not create a testing/repeatable context, (4) not having all the context set up could cause false fatal errors like undefined function. Thus, instead of executing php $tempfile it’s better to execute php —no-php-ini —syntax-check $tempfile . php.net/manual/en/features.commandline.options.php

Well, it «works» in the console because I see the fatal error. The $return is always 255 for the six uncatchable errors and always 0 otherwise. I think I need a shutdown handler to get to the error code. — as for PHPUnit, even if I @runInSeparateProcess a single test causing a fatal error, it always appears as an ‘E’. — Your idea is interesting, and I upped you before. But to make it work, I think I need to dig into PHPUnit and write a patch or plugin. I wonder why nobody did it before. Is it unreasonable to expect a script to fail?

Now I got your concerns. Will play around with PHPUnit a little bit, probably write some code and give you a feedback..

I’ve found there is a customizable isolation template. There we need to register_shutdown_function(‘__phpunit_shutdown’, $test, $result) . __phpunit_shutdown($test, $result) (in case of error) only prints a serialized array like usual, but with an added error key set to error_get_last() . Then we can add support for an @expectedShutdownError from PHPUnit_Util_PHP::runTestJob , which would call processChildResult with doctored arguments (mainly stderr = »).

Читайте также:  Learn Jquery Html Method

Источник

How do I catch a PHP fatal (`E_ERROR`) error?

I can use set_error_handler() to catch most PHP errors, but it doesn’t work for fatal ( E_ERROR ) errors, such as calling a function that doesn’t exist. Is there another way to catch these errors? I am trying to call mail() for all errors and am running PHP 5.2.3.

I wrote up a wiki-style Q&A with a complete solution for catching All errors in PHP; which can be viewed/gleaned/stolen/critiqued here on Stack Overflow. The solution includes five methods that wrap all errors PHP can generate that will eventually pass said errors up to an ‘ErrorHandler’ typed object.

18 Answers 18

Log fatal errors using the register_shutdown_function , which requires PHP 5.2+:

register_shutdown_function( "fatal_handler" ); function fatal_handler() < $errfile = "unknown file"; $errstr = "shutdown"; $errno = E_CORE_ERROR; $errline = 0; $error = error_get_last(); if($error !== NULL) < $errno = $error["type"]; $errfile = $error["file"]; $errline = $error["line"]; $errstr = $error["message"]; error_mail(format_error( $errno, $errstr, $errfile, $errline)); >> 

You will have to define the error_mail and format_error functions. For example:

function format_error( $errno, $errstr, $errfile, $errline ) < $trace = print_r( debug_backtrace( false ), true ); $content = " 
ItemDescription
Error
$errstr
Errno
$errno
File $errfile
Line $errline
Trace
$trace

"; return $content; >

Use Swift Mailer to write the error_mail function.

+1 This is the actual correct answer. I don’t know why people are getting hung up on «you cannot recover from fatal errors»—the question didn’t say anything about recovering.

Thanks, good one. Recovering from fatal errors (memory limits for example) is not something that I would try to do, but making these errors discoverable (without customer submitting a support ticket) makes all the difference.

Using basic mail: mail(«myname@myemail.com», «My Site: FATAL ERROR», «Details: » . $errno . ‘ ‘ . $errstr . ‘ ‘ . $errfile . ‘ ‘ . $errline);

@ScottNicol Slava V is correct, because the shutdown function is called every time the script finishes running. With the way the code is written now, an email will be sent on EVERY page load.

Note: this is not a 100% correct answer. Any place that uses an @ symbol to ignore errors will still SET the last error (so you can handle errors). So your script finishes without a problem but the register_shutdown_function still thinks an error happened. Only since PHP 7 though have they had a function error_clear_last().

I just came up with this solution (PHP 5.2.0+):

function shutDownFunction() < $error = error_get_last(); // Fatal error, E_ERROR === 1 if ($error['type'] === E_ERROR) < // Do your stuff >> register_shutdown_function('shutDownFunction'); 

Different error types are defined at Predefined Constants.

This solution does much more for me than top rated answer. The top-rated answer will send you an email every time the script runs, even if there is no error. This one strictly runs on a fatal error.

@Pacerier I’m not sure what you mean with «handled», as errors are not exceptions, but I suppose the answer is «yes»

@Pacerier I see, that’s an interesting question. Have a look at php.net/error_get_last, one of the comments mentions that » If an error handler (see set_error_handler ) successfully handles an error then that error will not be reported by this function. «

Perhaps this is obvious, calling register_shutdown_function() must be earlier than any fatal error. use_1T_memory(); /* memory exhausted error here! */ register_shutdown_function(‘shutDownFunction’); won’t work as expected.

PHP doesn’t provide conventional means for catching and recovering from fatal errors. This is because processing should not typically be recovered after a fatal error. String matching an output buffer (as suggested by the original post the technique described on PHP.net) is definitely ill-advised. It’s simply unreliable.

Calling the mail() function from within an error handler method prove to be problematic, too. If you had a lot of errors, your mail server would be loaded with work, and you could find yourself with a gnarly inbox. To avoid this, you might consider running a cron to scan error logs periodically and send notifications accordingly. You might also like to look into system monitoring software, such as Nagios.

To speak to the bit about registering a shutdown function:

It’s true that you can register a shutdown function, and that’s a good answer.

The point here is that we typically shouldn’t try to recover from fatal errors, especially not by using a regular expression against your output buffer. I was responding to the accepted answer, which linked to a suggestion on php.net which has since been changed or removed.

That suggestion was to use a regex against the output buffer during exception handling, and in the case of a fatal error (detected by the matching against whatever configured error text you might be expecting), try to do some sort of recovery or continued processing. That would not be a recommended practice (I believe that’s why I can’t find the original suggestion, too. I’m either overlooking it, or the php community shot it down).

It might be worth noting that the more recent versions of PHP (around 5.1) seem to call the shutdown function earlier, before the output buffering callback is envoked. In version 5 and earlier, that order was the reverse (the output buffering callback was followed by the shutdown function). Also, since about 5.0.5 (which is much earlier than the questioner’s version 5.2.3), objects are unloaded well before a registered shutdown function is called, so you won’t be able to rely on your in-memory objects to do much of anything.

So registering a shutdown function is fine, but the sort of tasks that ought to be performed by a shutdown function are probably limited to a handful of gentle shutdown procedures.

The key take-away here is just some words of wisdom for anyone who stumbles upon this question and sees the advice in the originally accepted answer. Don’t regex your output buffer.

Источник

TheMLJI9i – Sierj Khaletski Blog

Программисты, которым не лень сделать пару кликов и ввести пару строк в файл .htaccess, на production окружении отключают вывод ошибок. Но а как быть, когда нужно вывести красивое сообщение пользователю, что что-то пошло не так, а разработчику, например, вывести trace выполненых операций?

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

  • Get link
  • Facebook
  • Twitter
  • Pinterest
  • Email
  • Other Apps

Labels

  • Get link
  • Facebook
  • Twitter
  • Pinterest
  • Email
  • Other Apps

Comments

Post a Comment

Турция, Олюдениз (Фетхие). Пару слов про отдых.

Июнь 2016. Если бы кто-то мне сказал, что Турция может быть такой, я бы ни за что не поверил. Да так оно и было. Для меня, наверное, как и для многих, Турция представлялась как доступный отдых, в районах Мармарис, Кемер, Анталия и другие. В тот момент, когда рассматривались варианты на отпуск, о Турции и близко никто не думал. Испания, Греция и другие. На все это еще накладывались события 2016. Одним днем я получил сообщение с фотографией моря голубого-голубого цвета. Просто райский уголок. Я тогда и подумать не мог, где это на самом-то деле. Турция, Олюдениз (Фетхие). Я стал просматривать все больше и больше фото, не мог остановиться — красота. Словно мир перевернулся, Турция больше не та курортная страна с ‘all inclusive’, переполнеными пляжами и кучей пьяных невоспитанных туристов.

  • Get link
  • Facebook
  • Twitter
  • Pinterest
  • Email
  • Other Apps

Немного о том, как средствами Google создать форму регистрации на мероприятие с последующей рассылкой.

Когда встала проблема создания формы регистрации на вебинар с последующей рассылкой уведомлений всем зарегестрированным, я прикинул возможные средства, которые помогут решить проблему. Процесс прост: создаем форму, сохраняем данные, отправленные из формы, делаем рассылку, когда это необходимо. Все казалось бы просто. Но зачем городить свой велосипед c клиентской и серверной частями, если изначально известно, что это будет простая регистрация с последующей рассылкой?! Для данной задачи вполне могут сгодиться и инструменты Google, с некоторыми специальными дополнениями.

  • Get link
  • Facebook
  • Twitter
  • Pinterest
  • Email
  • Other Apps

Источник

Оцените статью