CakePHP
  • Documentation
    • Book
    • API
    • Videos
    • Logos & Trademarks
  • Business Solutions
  • Swag
  • Road Trip
  • Team
  • Community
    • Community
    • Team
    • Issues (Github)
    • YouTube Channel
    • Get Involved
    • Bakery
    • Featured Resources
    • Newsletter
    • Certification
    • My CakePHP
    • CakeFest
    • Facebook
    • Twitter
    • Help & Support
    • Forum
    • Stack Overflow
    • IRC
    • Slack
    • Paid Support
CakePHP

C CakePHP 3.8 Red Velvet API

  • Overview
  • Tree
  • Deprecated
  • Version:
    • 3.8
      • 3.8
      • 3.7
      • 3.6
      • 3.5
      • 3.4
      • 3.3
      • 3.2
      • 3.1
      • 3.0
      • 2.10
      • 2.9
      • 2.8
      • 2.7
      • 2.6
      • 2.5
      • 2.4
      • 2.3
      • 2.2
      • 2.1
      • 2.0
      • 1.3
      • 1.2

Namespaces

  • Cake
    • Auth
      • Storage
    • Cache
      • Engine
    • Collection
      • Iterator
    • Command
    • Console
      • Exception
    • Controller
      • Component
      • Exception
    • Core
      • Configure
        • Engine
      • Exception
      • Retry
    • Database
      • Driver
      • Exception
      • Expression
      • Schema
      • Statement
      • Type
    • Datasource
      • Exception
    • Error
      • Middleware
    • Event
      • Decorator
    • Filesystem
    • Form
    • Http
      • Client
        • Adapter
        • Auth
      • Cookie
      • Exception
      • Middleware
      • Session
    • I18n
      • Formatter
      • Middleware
      • Parser
    • Log
      • Engine
    • Mailer
      • Exception
      • Transport
    • Network
      • Exception
    • ORM
      • Association
      • Behavior
        • Translate
      • Exception
      • Locator
      • Rule
    • Routing
      • Exception
      • Filter
      • Middleware
      • Route
    • Shell
      • Helper
      • Task
    • TestSuite
      • Fixture
      • Stub
    • Utility
      • Exception
    • Validation
    • View
      • Exception
      • Form
      • Helper
      • Widget
  • None

Classes

  • BaseErrorHandler
  • Debugger
  • ErrorHandler
  • ExceptionRenderer

Interfaces

  • ExceptionRendererInterface

Exceptions

  • FatalErrorException
  • PHP7ErrorException
  1: <?php
  2: /**
  3:  * CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
  4:  * Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
  5:  *
  6:  * Licensed under The MIT License
  7:  * For full copyright and license information, please see the LICENSE.txt
  8:  * Redistributions of files must retain the above copyright notice.
  9:  *
 10:  * @copyright     Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
 11:  * @link          https://cakephp.org CakePHP(tm) Project
 12:  * @since         2.0.0
 13:  * @license       https://opensource.org/licenses/mit-license.php MIT License
 14:  */
 15: namespace Cake\Error;
 16: 
 17: use Cake\Core\Configure;
 18: use Cake\Log\Log;
 19: use Cake\Routing\Router;
 20: use Error;
 21: use Exception;
 22: 
 23: /**
 24:  * Base error handler that provides logic common to the CLI + web
 25:  * error/exception handlers.
 26:  *
 27:  * Subclasses are required to implement the template methods to handle displaying
 28:  * the errors in their environment.
 29:  */
 30: abstract class BaseErrorHandler
 31: {
 32:     /**
 33:      * Options to use for the Error handling.
 34:      *
 35:      * @var array
 36:      */
 37:     protected $_options = [];
 38: 
 39:     /**
 40:      * @var bool
 41:      */
 42:     protected $_handled = false;
 43: 
 44:     /**
 45:      * Display an error message in an environment specific way.
 46:      *
 47:      * Subclasses should implement this method to display the error as
 48:      * desired for the runtime they operate in.
 49:      *
 50:      * @param array $error An array of error data.
 51:      * @param bool $debug Whether or not the app is in debug mode.
 52:      * @return void
 53:      */
 54:     abstract protected function _displayError($error, $debug);
 55: 
 56:     /**
 57:      * Display an exception in an environment specific way.
 58:      *
 59:      * Subclasses should implement this method to display an uncaught exception as
 60:      * desired for the runtime they operate in.
 61:      *
 62:      * @param \Exception $exception The uncaught exception.
 63:      * @return void
 64:      */
 65:     abstract protected function _displayException($exception);
 66: 
 67:     /**
 68:      * Register the error and exception handlers.
 69:      *
 70:      * @return void
 71:      */
 72:     public function register()
 73:     {
 74:         $level = -1;
 75:         if (isset($this->_options['errorLevel'])) {
 76:             $level = $this->_options['errorLevel'];
 77:         }
 78:         error_reporting($level);
 79:         set_error_handler([$this, 'handleError'], $level);
 80:         set_exception_handler([$this, 'wrapAndHandleException']);
 81:         register_shutdown_function(function () {
 82:             if ((PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') && $this->_handled) {
 83:                 return;
 84:             }
 85:             $megabytes = Configure::read('Error.extraFatalErrorMemory');
 86:             if ($megabytes === null) {
 87:                 $megabytes = 4;
 88:             }
 89:             if ($megabytes > 0) {
 90:                 $this->increaseMemoryLimit($megabytes * 1024);
 91:             }
 92:             $error = error_get_last();
 93:             if (!is_array($error)) {
 94:                 return;
 95:             }
 96:             $fatals = [
 97:                 E_USER_ERROR,
 98:                 E_ERROR,
 99:                 E_PARSE,
100:             ];
101:             if (!in_array($error['type'], $fatals, true)) {
102:                 return;
103:             }
104:             $this->handleFatalError(
105:                 $error['type'],
106:                 $error['message'],
107:                 $error['file'],
108:                 $error['line']
109:             );
110:         });
111:     }
112: 
113:     /**
114:      * Set as the default error handler by CakePHP.
115:      *
116:      * Use config/error.php to customize or replace this error handler.
117:      * This function will use Debugger to display errors when debug mode is on. And
118:      * will log errors to Log, when debug mode is off.
119:      *
120:      * You can use the 'errorLevel' option to set what type of errors will be handled.
121:      * Stack traces for errors can be enabled with the 'trace' option.
122:      *
123:      * @param int $code Code of error
124:      * @param string $description Error description
125:      * @param string|null $file File on which error occurred
126:      * @param int|null $line Line that triggered the error
127:      * @param array|null $context Context
128:      * @return bool True if error was handled
129:      */
130:     public function handleError($code, $description, $file = null, $line = null, $context = null)
131:     {
132:         if (error_reporting() === 0) {
133:             return false;
134:         }
135:         $this->_handled = true;
136:         list($error, $log) = static::mapErrorCode($code);
137:         if ($log === LOG_ERR) {
138:             return $this->handleFatalError($code, $description, $file, $line);
139:         }
140:         $data = [
141:             'level' => $log,
142:             'code' => $code,
143:             'error' => $error,
144:             'description' => $description,
145:             'file' => $file,
146:             'line' => $line,
147:         ];
148: 
149:         $debug = Configure::read('debug');
150:         if ($debug) {
151:             $data += [
152:                 'context' => $context,
153:                 'start' => 3,
154:                 'path' => Debugger::trimPath($file)
155:             ];
156:         }
157:         $this->_displayError($data, $debug);
158:         $this->_logError($log, $data);
159: 
160:         return true;
161:     }
162: 
163:     /**
164:      * Checks the passed exception type. If it is an instance of `Error`
165:      * then, it wraps the passed object inside another Exception object
166:      * for backwards compatibility purposes.
167:      *
168:      * @param \Exception|\Error $exception The exception to handle
169:      * @return void
170:      */
171:     public function wrapAndHandleException($exception)
172:     {
173:         if ($exception instanceof Error) {
174:             $exception = new PHP7ErrorException($exception);
175:         }
176:         $this->handleException($exception);
177:     }
178: 
179:     /**
180:      * Handle uncaught exceptions.
181:      *
182:      * Uses a template method provided by subclasses to display errors in an
183:      * environment appropriate way.
184:      *
185:      * @param \Exception $exception Exception instance.
186:      * @return void
187:      * @throws \Exception When renderer class not found
188:      * @see https://secure.php.net/manual/en/function.set-exception-handler.php
189:      */
190:     public function handleException(Exception $exception)
191:     {
192:         $this->_displayException($exception);
193:         $this->_logException($exception);
194:         $this->_stop($exception->getCode() ?: 1);
195:     }
196: 
197:     /**
198:      * Stop the process.
199:      *
200:      * Implemented in subclasses that need it.
201:      *
202:      * @param int $code Exit code.
203:      * @return void
204:      */
205:     protected function _stop($code)
206:     {
207:         // Do nothing.
208:     }
209: 
210:     /**
211:      * Display/Log a fatal error.
212:      *
213:      * @param int $code Code of error
214:      * @param string $description Error description
215:      * @param string $file File on which error occurred
216:      * @param int $line Line that triggered the error
217:      * @return bool
218:      */
219:     public function handleFatalError($code, $description, $file, $line)
220:     {
221:         $data = [
222:             'code' => $code,
223:             'description' => $description,
224:             'file' => $file,
225:             'line' => $line,
226:             'error' => 'Fatal Error',
227:         ];
228:         $this->_logError(LOG_ERR, $data);
229: 
230:         $this->handleException(new FatalErrorException($description, 500, $file, $line));
231: 
232:         return true;
233:     }
234: 
235:     /**
236:      * Increases the PHP "memory_limit" ini setting by the specified amount
237:      * in kilobytes
238:      *
239:      * @param int $additionalKb Number in kilobytes
240:      * @return void
241:      */
242:     public function increaseMemoryLimit($additionalKb)
243:     {
244:         $limit = ini_get('memory_limit');
245:         if (!strlen($limit) || $limit === '-1') {
246:             return;
247:         }
248:         $limit = trim($limit);
249:         $units = strtoupper(substr($limit, -1));
250:         $current = (int)substr($limit, 0, strlen($limit) - 1);
251:         if ($units === 'M') {
252:             $current *= 1024;
253:             $units = 'K';
254:         }
255:         if ($units === 'G') {
256:             $current = $current * 1024 * 1024;
257:             $units = 'K';
258:         }
259: 
260:         if ($units === 'K') {
261:             ini_set('memory_limit', ceil($current + $additionalKb) . 'K');
262:         }
263:     }
264: 
265:     /**
266:      * Log an error.
267:      *
268:      * @param string $level The level name of the log.
269:      * @param array $data Array of error data.
270:      * @return bool
271:      */
272:     protected function _logError($level, $data)
273:     {
274:         $message = sprintf(
275:             '%s (%s): %s in [%s, line %s]',
276:             $data['error'],
277:             $data['code'],
278:             $data['description'],
279:             $data['file'],
280:             $data['line']
281:         );
282:         if (!empty($this->_options['trace'])) {
283:             $trace = Debugger::trace([
284:                 'start' => 1,
285:                 'format' => 'log'
286:             ]);
287: 
288:             $request = Router::getRequest();
289:             if ($request) {
290:                 $message .= $this->_requestContext($request);
291:             }
292:             $message .= "\nTrace:\n" . $trace . "\n";
293:         }
294:         $message .= "\n\n";
295: 
296:         return Log::write($level, $message);
297:     }
298: 
299:     /**
300:      * Handles exception logging
301:      *
302:      * @param \Exception $exception Exception instance.
303:      * @return bool
304:      */
305:     protected function _logException(Exception $exception)
306:     {
307:         $config = $this->_options;
308:         $unwrapped = $exception instanceof PHP7ErrorException ?
309:             $exception->getError() :
310:             $exception;
311: 
312:         if (empty($config['log'])) {
313:             return false;
314:         }
315: 
316:         if (!empty($config['skipLog'])) {
317:             foreach ((array)$config['skipLog'] as $class) {
318:                 if ($unwrapped instanceof $class) {
319:                     return false;
320:                 }
321:             }
322:         }
323: 
324:         return Log::error($this->_getMessage($exception));
325:     }
326: 
327:     /**
328:      * Get the request context for an error/exception trace.
329:      *
330:      * @param \Cake\Http\ServerRequest $request The request to read from.
331:      * @return string
332:      */
333:     protected function _requestContext($request)
334:     {
335:         $message = "\nRequest URL: " . $request->getRequestTarget();
336: 
337:         $referer = $request->getEnv('HTTP_REFERER');
338:         if ($referer) {
339:             $message .= "\nReferer URL: " . $referer;
340:         }
341:         $clientIp = $request->clientIp();
342:         if ($clientIp && $clientIp !== '::1') {
343:             $message .= "\nClient IP: " . $clientIp;
344:         }
345: 
346:         return $message;
347:     }
348: 
349:     /**
350:      * Generates a formatted error message
351:      *
352:      * @param \Exception $exception Exception instance
353:      * @return string Formatted message
354:      */
355:     protected function _getMessage(Exception $exception)
356:     {
357:         $message = $this->getMessageForException($exception);
358: 
359:         $request = Router::getRequest();
360:         if ($request) {
361:             $message .= $this->_requestContext($request);
362:         }
363: 
364:         return $message;
365:     }
366: 
367:     /**
368:      * Generate the message for the exception
369:      *
370:      * @param \Exception $exception The exception to log a message for.
371:      * @param bool $isPrevious False for original exception, true for previous
372:      * @return string Error message
373:      */
374:     protected function getMessageForException($exception, $isPrevious = false)
375:     {
376:         $exception = $exception instanceof PHP7ErrorException ?
377:             $exception->getError() :
378:             $exception;
379:         $config = $this->_options;
380: 
381:         $message = sprintf(
382:             '%s[%s] %s in %s on line %s',
383:             $isPrevious ? "\nCaused by: " : '',
384:             get_class($exception),
385:             $exception->getMessage(),
386:             $exception->getFile(),
387:             $exception->getLine()
388:         );
389:         $debug = Configure::read('debug');
390: 
391:         if ($debug && method_exists($exception, 'getAttributes')) {
392:             $attributes = $exception->getAttributes();
393:             if ($attributes) {
394:                 $message .= "\nException Attributes: " . var_export($exception->getAttributes(), true);
395:             }
396:         }
397: 
398:         if (!empty($config['trace'])) {
399:             $message .= "\nStack Trace:\n" . $exception->getTraceAsString() . "\n\n";
400:         }
401: 
402:         $previous = $exception->getPrevious();
403:         if ($previous) {
404:             $message .= $this->getMessageForException($previous, true);
405:         }
406: 
407:         return $message;
408:     }
409: 
410:     /**
411:      * Map an error code into an Error word, and log location.
412:      *
413:      * @param int $code Error code to map
414:      * @return array Array of error word, and log location.
415:      */
416:     public static function mapErrorCode($code)
417:     {
418:         $levelMap = [
419:             E_PARSE => 'error',
420:             E_ERROR => 'error',
421:             E_CORE_ERROR => 'error',
422:             E_COMPILE_ERROR => 'error',
423:             E_USER_ERROR => 'error',
424:             E_WARNING => 'warning',
425:             E_USER_WARNING => 'warning',
426:             E_COMPILE_WARNING => 'warning',
427:             E_RECOVERABLE_ERROR => 'warning',
428:             E_NOTICE => 'notice',
429:             E_USER_NOTICE => 'notice',
430:             E_STRICT => 'strict',
431:             E_DEPRECATED => 'deprecated',
432:             E_USER_DEPRECATED => 'deprecated',
433:         ];
434:         $logMap = [
435:             'error' => LOG_ERR,
436:             'warning' => LOG_WARNING,
437:             'notice' => LOG_NOTICE,
438:             'strict' => LOG_NOTICE,
439:             'deprecated' => LOG_NOTICE,
440:         ];
441: 
442:         $error = $levelMap[$code];
443:         $log = $logMap[$error];
444: 
445:         return [ucfirst($error), $log];
446:     }
447: }
448: 
Follow @CakePHP
#IRC
OpenHub
Rackspace
  • Business Solutions
  • Showcase
  • Documentation
  • Book
  • API
  • Videos
  • Logos & Trademarks
  • Community
  • Team
  • Issues (Github)
  • YouTube Channel
  • Get Involved
  • Bakery
  • Featured Resources
  • Newsletter
  • Certification
  • My CakePHP
  • CakeFest
  • Facebook
  • Twitter
  • Help & Support
  • Forum
  • Stack Overflow
  • IRC
  • Slack
  • Paid Support

Generated using CakePHP API Docs