Skip to content

Commit

Permalink
Merge pull request #232 from elecena/handleException/support-throwable
Browse files Browse the repository at this point in the history
Handle throwable errors
  • Loading branch information
macbre authored May 9, 2023
2 parents 183589e + b10974a commit e46c8e4
Show file tree
Hide file tree
Showing 10 changed files with 205 additions and 81 deletions.
78 changes: 39 additions & 39 deletions classes/NanoApp.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,40 +20,37 @@
class NanoApp
{
// cache object
protected $cache = false;
protected ?Cache $cache = null;

// config
protected $config;
protected Config $config;

// debug logging
protected $debug;
protected Debug $debug;

// database connection
protected $database = false;
protected ?Database $database = null;

// events handler
protected $events;
protected Events $events;

// response
protected $response;
protected Response $response;

// HTTP request
protected $request;
protected Request $request;

// router
protected $router;
protected Router $router;

// skin
protected $skin = false;

// an array of loaded modules
protected $modules;
protected ?Skin $skin = null;

// application's working directory
protected $dir = '';
protected string $dir = '';

// current application instance
protected static $app;
protected static ?NanoApp $app = null;

/**
* Return the current instance of NanoApp
Expand Down Expand Up @@ -329,14 +326,14 @@ public function render($controllerName, $methodName = '', array $params = [])
* Will render HTTP 500 page with error details
*
* @param callable $fn function to call
* @param callable|bool $handler custom exception handling function to call
* @return mixed|Exception value return by function called or exception that was thrown
* @param callable|null $handler custom exception handling function to call
* @return mixed|Throwable value return by function called or exception that was thrown
*/
public function handleException(callable $fn, $handler = false)
public function handleException(callable $fn, ?callable $handler = null)
{
try {
return $fn();
} catch (\Exception $e) {
} catch (\Throwable $e) {
$response = $this->getResponse();
$response->setResponseCode(Response::INTERNAL_SERVER_ERROR);
$response->setContentType('text/plain');
Expand Down Expand Up @@ -367,19 +364,18 @@ public function handleException(callable $fn, $handler = false)
/**
* Return path to application
*/
public function getDirectory()
public function getDirectory(): string
{
return $this->dir;
}

/**
* Return cache
*
* @return Cache
* Lazy-load the cache instance
* @throws Exception
*/
public function getCache()
public function getCache(): Cache
{
if ($this->cache === false) {
if (is_null($this->cache)) {
// setup cache (using default driver if none provided)
$cacheSettings = $this->config->get('cache', [
'driver' => 'file',
Expand All @@ -394,22 +390,25 @@ public function getCache()
/**
* Return config
*/
public function getConfig()
public function getConfig(): Config
{
return $this->config;
}

/**
* Return database
*
* @return Database
* Lazy-load the database instance
* @throws Exception
*/
public function getDatabase()
public function getDatabase(): Database
{
// lazy connection handling
if ($this->database === false) {
if (is_null($this->database)) {
// set connection to database (using db.default config entry)
$this->database = Database::connect($this);

if (is_null($this->database)) {
throw new Exception(__METHOD__ . ': unable to create a database instance!');
}
}

return $this->database;
Expand All @@ -418,31 +417,31 @@ public function getDatabase()
/**
* Return debug
*/
public function getDebug()
public function getDebug(): Debug
{
return $this->debug;
}

/**
* Return events
*/
public function getEvents()
public function getEvents(): Events
{
return $this->events;
}

/**
* Return response
*/
public function getResponse()
public function getResponse(): Response
{
return $this->response;
}

/**
* Return request
*/
public function getRequest()
public function getRequest(): Request
{
return $this->request;
}
Expand All @@ -451,15 +450,15 @@ public function getRequest()
* Set a request for this NanoApp, used by tests
* @param Request $request
*/
public function setRequest(Request $request)
public function setRequest(Request $request): void
{
$this->request = $request;
}

/**
* Return router
*/
public function getRouter()
public function getRouter(): Router
{
return $this->router;
}
Expand All @@ -468,13 +467,14 @@ public function getRouter()
* Return skin
*
* @return Skin
* @throws Exception
*/
public function getSkin()
public function getSkin(): Skin
{
// lazy load the skin
if ($this->skin === false) {
if (is_null($this->skin)) {
// use the default skin
$skinName = $this->config->get('skin', 'default');
$skinName = (string) $this->config->get('skin', 'default');

// allow to override the default choice
$this->events->fire('NanoAppGetSkin', [$this, &$skinName]);
Expand Down
3 changes: 1 addition & 2 deletions classes/NanoBaseTest.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@
*/
class NanoBaseTest extends TestCase
{
/* @var $app \NanoApp */
protected $app;
protected \NanoApp $app;

/* @see https://github.com/postmanlabs/httpbin */
const HTTPBIN_HOST = 'http://0.0.0.0:5555';
Expand Down
24 changes: 24 additions & 0 deletions classes/NanoCliApp.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,28 @@ public function __construct($dir, $configSet = 'default', $logFile = 'script')
require $bootstrapFile;
}
}

/**
* Wrap your script logic with the method below to exceptions logging added.
*/
public function handleException(callable $fn, ?callable $handler = null)
{
try {
return $fn();
} catch (\Throwable $ex) {
// log the exception
$logger = NanoLogger::getLogger('nano.app.exception');
$logger->error($ex->getMessage(), [
'exception' => $ex,
]);

if (is_callable($handler)) {
$handler($ex);
return $ex;
}

echo get_class($ex) . ": {$ex->getMessage()}\n{$ex->getTraceAsString()}\n";
die(1);
}
}
}
12 changes: 4 additions & 8 deletions classes/NanoObject.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,6 @@ abstract class NanoObject

protected $logger;

// DB connection
protected $database;

// config
protected $config;

Expand All @@ -42,15 +39,14 @@ public function __construct()
$this->debug = $this->app->getDebug();
$this->logger = NanoLogger::getLogger('nano.' . get_class($this));
$this->events = $this->app->getEvents();

// use lazy-resolving
$this->database = static::getDatabase($this->app);
}

/**
* Allow models and services to use different database
*
* @throws \Exception
*/
protected static function getDatabase(\NanoApp $app)
protected static function getDatabase(\NanoApp $app): \Database
{
return $app->getDatabase();
}
Expand Down
11 changes: 0 additions & 11 deletions classes/healtcheck/HealtcheckBase.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,17 +28,6 @@ public function __construct()
$this->response->setContentType('text/plain');
}

/**
* Do not connect to the database be default!
*
* @param \NanoApp $app
* @return \Database|null
*/
protected static function getDatabase(\NanoApp $app)
{
return null;
}

/**
* @param string $msg
*/
Expand Down
5 changes: 5 additions & 0 deletions tests/app/classes/SkinTestApp.class.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?php

class SkinTestApp extends Skin
{
}
1 change: 1 addition & 0 deletions tests/app/config/default.config.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
$config['test'] = 'value';
$config['home'] = 'http://example.org/site/';
$config['index'] = '/foo/index';
$config['skin'] = 'TestApp'; /* @see SkinTestApp */
$config['cache'] = [
'driver' => 'file',
];
Expand Down
Loading

0 comments on commit e46c8e4

Please sign in to comment.