S
In general, your mechanic is correct, because I don't understand the criticism of your comrade. It would be nice to see his decision.It's essentially the same. In fact, the error processing class:class ErrorHandler
{
protected $format = '{{message}} {{class}}::{{method}} {{file}} on line {{line}}';
/**
* @var HandlerInterface
*/
protected $displayHandler;
/**
* @var integer the size of the reserved memory. A portion of memory is pre-allocated so that
* when an out-of-memory issue occurs, the error handler is able to handle the error with
* the help of this reserved memory. If you set this value to be 0, no memory will be reserved.
* Defaults to 256KB.
*/
protected $memoryReserveSize = 262144;
/**
* @var string Used to reserve memory for fatal error handler.
*/
private $_memoryReserve;
/**
* Register this error handler.
*/
public function register()
{
// Catch errors
set_error_handler([$this, 'handleError']);
if ($this->memoryReserveSize > 0) {
$this->_memoryReserve = str_repeat('x', $this->memoryReserveSize);
}
// Start buffer
ob_start();
// Catch fatal errors
register_shutdown_function([$this, 'handleShutdown']);
}
/**
* Unregisters this error handler by restoring the PHP error handlers.
*/
public function unregister()
{
restore_error_handler();
}
/**
* Error handler.
*
* @param int $code
* @param string $msg
* @param string $file
* @param int $line
* @return bool
* @throws \ErrorException
*/
public function handleError($code, $msg, $file, $line)
{
if (~error_reporting() & $code) {
return false;
}
switch ($code) {
case E_USER_WARNING:
case E_WARNING:
$exception = new \ErrorException("[E_WARNING] {$msg}", Log::WARNING, $code, $file, $line);
break;
case E_USER_NOTICE:
case E_NOTICE:
case E_STRICT:
$exception = new \ErrorException("[E_NOTICE] {$msg}", Log::NOTICE, $code, $file, $line);
break;
case E_RECOVERABLE_ERROR:
$exception = new \ErrorException("[E_CATCHABLE] {$msg}", Log::ERROR, $code, $file, $line);
break;
default:
$exception = new \ErrorException("[E_UNKNOWN] {$msg}", Log::CRITICAL, $code, $file, $line);
}
throw $exception;
}
/**
* Fatal handler.
*
* @return void
*/
public function handleShutdown()
{
unset($this->_memoryReserve);
$error = error_get_last();
if (
isset($error['type']) &&
($error['type'] == E_ERROR ||
$error['type'] == E_PARSE ||
$error['type'] == E_COMPILE_ERROR ||
$error['type'] == E_CORE_ERROR)
) {
$type = "";
switch ($error['type']) {
case E_ERROR:
$type = '[E_ERROR]';
break;
case E_PARSE:
$type = '[E_PARSE]';
break;
case E_COMPILE_ERROR:
$type = '[E_COMPILE_ERROR]';
break;
case E_CORE_ERROR:
$type = '[E_CORE_ERROR]';
break;
}
$exception = new \ErrorException("$type {$error['message']}", Log::CRITICAL, $error['type'], $error['file'], $error['line']);
if (APP_LOG) {
Log::log(Log::CRITICAL, $this->convertExceptionToString($exception));
}
$this->display($exception);
} else {
if (ob_get_length() !== false) {
// Display buffer, complete work buffer
ob_end_flush();
}
}
}
/**
* Sets a display handler.
* @param HandlerInterface $handler
*/
public function setDisplayHandler(HandlerInterface $handler)
{
$this->displayHandler = $handler;
}
/**
* Sets a format message log.
* @param string $format
*/
public function setFormat($format)
{
$this->format = $format;
}
/**
* Sets a size memory.
* @param int $size
*/
public function setMemoryReserve($size)
{
$this->memoryReserveSize = $size;
}
/**
* @param \Exception $exception
*/
public function display(\Exception $exception)
{
// display Whoops
if (APP_DEBUG === true) {
if (!isset($this->displayHandler)) {
$this->displayHandler = new PrettyPageHandler();
}
$run = new Run();
$run->pushHandler($this->displayHandler);
$run->handleException($exception);
return;
}
die('This site is temporarily unavailable. Please, visit the page later.');
}
/**
* Converts an exception into a simple string.
*
* @param \Exception $exception the exception being converted
* @return string the string representation of the exception.
*/
public function convertExceptionToString(\Exception $exception)
{
$trace = $exception->getTrace();
$placeholders = [
'{{class}}' => isset($trace[0]['class']) ? $trace[0]['class'] : '',
'{{method}}' => isset($trace[0]['function']) ? $trace[0]['function'] : '',
'{{message}}' => $exception->getMessage(),
'{{file}}' => $exception->getFile(),
'{{line}}' => $exception->getLine(),
];
return strtr($this->format, $placeholders);
}
}
The class may be static (i.e. static methods and properties). Doesn't matter.A well-known library is responsible for displaying exceptions and errors in a beautiful interface. https://github.com/filp/whoops and logic is made by https://github.com/Seldaek/monolog (Here is an easy wrapper above it)There are various nuances, for example, to catch the fatal of the overcrowded memory.Allowed memory size of...There is a need to reserve a certain volume. The experimental path was calculated at 256KB. That's what I learned at one of the conferences. https://github.com/samdark (Evangelist and Maintainer, yii). In fact, in the Freworth Processor. https://github.com/yiisoft/yii2/blob/master/framework/base/ErrorHandler.php ♪ If the processing code is to be analyzed the yii2, other nuances, for example, related to the treatment of HHVM errors/offs.At a single point, in your annex.index.php) Specify:defined('APP_DEBUG') or define('APP_DEBUG', true);
defined('APP_LOG') or define('APP_LOG', true);
$errorHandler = new ErrorHandler;
$errorHandler->register();
try {
// ... bootstrap вашего приложения
} catch (\Exception $e) {
if (APP_LOG) {
$msg = $errorHandler->convertExceptionToString($e);
Log::log($e->getCode() ? : Log::CRITICAL, $msg);
}
$errorHandler->display($e);
}
The application itself can catch local exceptions and do anything to them. For example, catch and log:try {
// ... некая локальная логика приложения
} catch (\Exception $e) {
Log::log(Log::ERROR, (new ErrorHandler())->convertExceptionToString($e));
}
In any case, any exception to be issued will be taken into account. index.php and according to the specified constantsAPP_DEBUG and APP_LOG() Submitted in a beautiful interface and added to the log. Of course, we have to cancel the debag regime.With regard to Whoops processors:Known in what formatcontent typeYou need to give the data to the user, you can choose a suitable processor.For example, verification is ajax requestif (isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] === 'XMLHttpRequest') {
$errorHandler->setDisplayHandler(new JsonResponseHandler());
}
The debag information will be presented as json-a, which is easy to view through the browser console.Ideally, there is a need to have HTTP a shell (Request Classes) and all of this is to be found at the level of the rolling stock or filters/contentNegotiator or something.P.S. Look. http://devconf.ru/ru/news/detail/29 about the operator of misrepresentation @ c devconf. Very exciting.UPDATEI'm personally trying to retrieve the right http-status. No one's stopping you from giving the user a specially designed 404 pages with similar status.if (headers_sent()) { // проверка: не отправлены ли уже заголовоки
return;
}
$version = isset($_SERVER['SERVER_PROTOCOL']) && $_SERVER['SERVER_PROTOCOL'] === 'HTTP/1.0' ? '1.0' : '1.1'
$statusCode = 404;
$statusText = 'Not Found';
header("HTTP/$version $statusCode $statusText");
As I mentioned earlier, it is best to use the class questionnaire response on negative functions.It's easy to do with the roughing:$route = new Route();
$route->get('/items/{id:\d+}/', ['\namespace\ItemsController', 'actionOne']);
$route->post('/items/', ['\namespace\ItemsController', 'actionCreate']);
//... другие правила
$route->any('', ['\namespace\ItemsController', 'actionNotFound']);
// т.е. если вышеприведенные правила не выполнились, то выполнится последнее правило.
For ajax request, it is sufficient in the answer to indicate the headline without the body:$route->any('', function(Route $route) {
$route->response->status404();
return $route->response;
});
403 - if access to a resource (some URL-y) is prohibited for a non-authorised user or user with a different role/right, for example, not authorized by the administrator. Look. https://ru.wikipedia.org/wiki/%D0%A3%D0%BF%D1%80%D0%B0%D0%B2%D0%BB%D0%B5%D0%BD%D0%B8%D0%B5_%D0%B4%D0%BE%D1%81%D1%82%D1%83%D0%BF%D0%BE%D0%BC_%D0%BD%D0%B0_%D0%BE%D1%81%D0%BD%D0%BE%D0%B2%D0%B5_%D1%80%D0%BE%D0%BB%D0%B5%D0%B9 ♪ In yii, such a mechanism is implemented through conduct/filters to counter-aller exchenes.201 is a successful resource. For example, a comment or post may be issued when the user is registered.204 - the request for OBD has been successfully completed, but no data are available for some reason. For example, a new section has been opened on the website, but the articles are not yet written.422 I will use if data validation, for example form. In this case, through $statusText (see above) An explanation: Validation failure♪429 is the classic rate limiter. Most often applied to REST API. If there is a certain limit on demand to grant this status.302 for reinstatement. For example, if the data from the form are correct and the recording in the OBD system has been successfully performed, the page will be recirculated or the current page with the status.500, if you could see, ErrorHandler yes die('This site is temporarily unavailable. Please, visit the page later.');♪ You can, in lieu of this "old" recording, give the user a statistical specimen page with a pre-status 500. die(file_get_contents('/path/to/stub.html'));
In order to implement its RESTful API, reference is made to corrects of http-methods, status, headings (ready read https://en.wikipedia.org/wiki/HATEOAS (a) Mandatory. https://ru.wikipedia.org/wiki/%D0%A1%D0%BF%D0%B8%D1%81%D0%BE%D0%BA_%D0%BA%D0%BE%D0%B4%D0%BE%D0%B2_%D1%81%D0%BE%D1%81%D1%82%D0%BE%D1%8F%D0%BD%D0%B8%D1%8F_HTTP So you'll have the Whoops on the debag mode, with the glass traction, and the user will be shown on the sale (both server). Logate or there's no error/exclusion on your discretion. For example, in many default braces, information logic (level) is produced. Log::INFOThat is, every connection to the OBD, the success of the transaction, the authorisation of the user, etc., that can make your reservservoir so hard. There is a need to improve error logic before errors are made Log::WARNING or Log::ERRORas well as the use of state-level utili log rotations. For example, in Linux this is https://www.opennet.ru/man.shtml?topic=logrotate&category=8 ♪If I've touched on a lot of topics, then let me my open source of the library: https://github.com/romeOz/rock-route - Rooting with flexible rules, grouping (separation of rules into space/modules for example ajax, backend/adminca, etc., as in laravel) and REST support. Facilitated regexp pathters were taken from the library https://github.com/nikic/FastRoute Nikita Popov (ent to core team PHP). Detailed documentation is available. https://github.com/romeOz/rock-response/ - Fork yii2 response, which is completely separated from the fraimvor. No documentation, unfortunately, but there is an official https://github.com/yiisoft/yii2/blob/master/docs/guide/runtime-responses.md ♪ Really, too.
As we know, yii2 is a monolithic frimetre. https://github.com/romeOz/rock-request/ - similar fork, but with my library. https://github.com/romeOz/rock-sanitize ♪All these libraries go without extra dependence - all that is necessary for their work.