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.7 Red Velvet API

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