Skip to content
This repository was archived by the owner on Jan 3, 2022. It is now read-only.

Commit 495bbb1

Browse files
committed
feat: ✨ Add exception and change start session
1 parent 60f7509 commit 495bbb1

13 files changed

+273
-90
lines changed

.env.example

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
APP_KEY=
1+
APP_ENV=production
2+
APP_NAME=XK-PHP
3+
APP_URL=http://localhost
24

35
DB_CONNECTION=mysql
46
DB_HOST=127.0.0.1

app/Application.php

+14-4
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace App;
44

55
use App\Bootstrap\BootProviders;
6+
use App\Bootstrap\HandleExceptions;
67
use App\Bootstrap\LoadConfiguration;
78
use App\Bootstrap\LoadEnvironmentVariables;
89
use App\Bootstrap\RegisterFacades;
@@ -11,13 +12,11 @@
1112
use App\Kernel\ProviderManager;
1213
use App\Kernel\Container;
1314
use App\Kernel\RouteManager;
14-
use Laminas\HttpHandlerRunner\Emitter\SapiEmitter;
15-
use Psr\Http\Message\ResponseInterface;
1615
use function app_path;
1716
use function array_walk;
1817
use function base_path;
19-
use function config;
2018
use function config_path;
19+
use function env;
2120
use function public_path;
2221
use function realpath;
2322
use function storage_path;
@@ -43,6 +42,8 @@ class Application extends Container
4342
LoadEnvironmentVariables::class,
4443
// 加载配置
4544
LoadConfiguration::class,
45+
// 注册异常处理
46+
HandleExceptions::class,
4647
// 注册门面
4748
RegisterFacades::class,
4849
// 注册服务提供者管理器
@@ -104,7 +105,7 @@ protected function dispatchToEmit(): void
104105
$response = $this->make(RouteManager::class)->dispatch($request);
105106

106107
// 发送响应
107-
(new SapiEmitter())->emit($response);
108+
$response->send();
108109
}
109110

110111
/**
@@ -141,4 +142,13 @@ public static function setInstance(Application $application): void
141142
{
142143
self::$app = $application;
143144
}
145+
146+
public function environment(string $env = null)
147+
{
148+
$app_env = env('APP_ENV', 'production');
149+
if ($env === null) {
150+
return $app_env;
151+
}
152+
return $app_env === $env;
153+
}
144154
}

app/Bootstrap/HandleExceptions.php

+95
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
<?php
2+
3+
namespace App\Bootstrap;
4+
5+
use App\Exceptions\Exception;
6+
use App\Http\Request;
7+
use App\Http\Response;
8+
use ErrorException;
9+
use Throwable;
10+
use function in_array;
11+
use function response;
12+
use function view;
13+
14+
class HandleExceptions extends Bootstrap
15+
{
16+
public function boot(): void
17+
{
18+
if (!$this->app->environment('testing')) {
19+
error_reporting(-1);
20+
set_error_handler([$this, 'handleError']);
21+
set_exception_handler([$this, 'handleException']);
22+
register_shutdown_function([$this, 'handleDown']);
23+
ini_set('display_errors', 'Off');
24+
}
25+
}
26+
27+
public function handleError(
28+
$level,
29+
$message,
30+
$file = '',
31+
$line = 0,
32+
$context = []
33+
): void {
34+
if (error_reporting() & $level) {
35+
throw new ErrorException($message, 0, $level, $file, $line);
36+
}
37+
}
38+
39+
public function handleException(Throwable $e): void
40+
{
41+
$this->renderResponse($e)->send();
42+
}
43+
44+
protected function renderResponse(Throwable $e): Response
45+
{
46+
$request = $this->app->make(Request::class);
47+
if ($e instanceof Exception) {
48+
return $e->render();
49+
}
50+
return $this->renderExceptionResponse($request, $e);
51+
}
52+
53+
protected function renderExceptionResponse(
54+
Request $request,
55+
Throwable $e
56+
): Response {
57+
$code = $e->getCode() === 0 ? 500 : $e->getCode();
58+
$message =
59+
$e->getMessage() === ''
60+
? Response::$phrases[$code]
61+
: $e->getMessage();
62+
$content = [
63+
'status' => $code,
64+
'message' => $message,
65+
'errors' => $message
66+
];
67+
if (!$request->ajax()) {
68+
$content = view('errors/errors', $content);
69+
}
70+
return response($content, $code);
71+
}
72+
73+
public function handleDown(): void
74+
{
75+
$error = error_get_last();
76+
if (
77+
$error !== null &&
78+
in_array(
79+
$error['type'],
80+
[E_COMPILE_ERROR, E_CORE_ERROR, E_ERROR, E_PARSE],
81+
true
82+
)
83+
) {
84+
$this->handleException(
85+
new ErrorException(
86+
$error['message'],
87+
$error['type'],
88+
0,
89+
$error['file'],
90+
$error['line']
91+
)
92+
);
93+
}
94+
}
95+
}

app/Controllers/HomeController.php

+12
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
use App\Annotations\Route;
1212
use App\Annotations\Autowired\Autowired;
1313
use ReflectionClass;
14+
use RuntimeException;
1415

1516
class HomeController
1617
{
@@ -66,4 +67,15 @@ public function get(Request $request): bool
6667
{
6768
return true;
6869
}
70+
71+
/**
72+
* @param Request $request
73+
* @return bool
74+
*
75+
* @Route\Get("/exce")
76+
*/
77+
public function exception(Request $request): bool
78+
{
79+
throw new RuntimeException('Error');
80+
}
6981
}

app/Exceptions/Exception.php

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?php
2+
3+
namespace App\Exceptions;
4+
5+
use App\Http\Response;
6+
use RuntimeException;
7+
8+
abstract class Exception extends RuntimeException
9+
{
10+
abstract public function render(): Response;
11+
}

app/Exceptions/HttpException.php

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<?php
2+
3+
namespace App\Exceptions;
4+
5+
use App\Http\Response;
6+
use Throwable;
7+
8+
class HttpException extends Exception
9+
{
10+
/**
11+
* @var Response
12+
*/
13+
protected $response;
14+
15+
public function __construct(
16+
Response $response,
17+
$message = '',
18+
$code = 0,
19+
Throwable $previous = null
20+
) {
21+
$this->response = $response;
22+
parent::__construct($message, $code, $previous);
23+
}
24+
25+
public function getResponse(): Response
26+
{
27+
return $this->response;
28+
}
29+
30+
public function render(): Response
31+
{
32+
return $this->getResponse();
33+
}
34+
}

app/Http/CookieManager.php

-8
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,6 @@ class CookieManager
1414
*/
1515
private $response_cookies = [];
1616

17-
/**
18-
* @return CookieManager
19-
*/
20-
public static function make(): CookieManager
21-
{
22-
return new static();
23-
}
24-
2517
/**
2618
* 判断 Cookie 是否存在,并是否为空
2719
*

app/Http/Response.php

+9-22
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
use App\Facades\App;
66
use App\Kernel\View;
7+
use Laminas\HttpHandlerRunner\Emitter\SapiEmitter;
78
use Psr\Http\Message\ResponseInterface;
89
use Psr\Http\Message\StreamInterface;
910
use function get_class;
@@ -109,11 +110,6 @@ class Response implements ResponseInterface
109110
*/
110111
private $cookies;
111112

112-
/**
113-
* @var int[]
114-
*/
115-
private $accept_code = [];
116-
117113
/**
118114
* Response constructor.
119115
* @param string|StreamInterface $content
@@ -141,12 +137,6 @@ public function __construct(
141137
$this->stream = $content;
142138
}
143139
$this->cookies = Cookie::makeFromArray($this->getHeader('Set-Cookie'));
144-
// Has session
145-
$session_cookie = SessionManager::makeCookie();
146-
if ($session_cookie !== null) {
147-
$this->cookies[$session_cookie->getName()] = $session_cookie;
148-
$this->updateCookieHeader();
149-
}
150140
}
151141

152142
/**
@@ -234,6 +224,11 @@ public static function make(
234224
return new static($content, $status, $headers);
235225
}
236226

227+
public function send(): void
228+
{
229+
(new SapiEmitter())->emit($this);
230+
}
231+
237232
/**
238233
* @inheritDoc
239234
*/
@@ -357,10 +352,10 @@ public function hasCookie(string $name): bool
357352
* @param Cookie $cookie
358353
* @return Response
359354
*/
360-
public function withCookie(string $name, Cookie $cookie): Response
355+
public function withCookie(Cookie $cookie): Response
361356
{
362357
$new = clone $this;
363-
$new->cookies[$name] = $cookie;
358+
$new->cookies[$cookie->getName()] = $cookie;
364359
$new->updateCookieHeader();
365360
return $new;
366361
}
@@ -398,7 +393,6 @@ public function cookie(
398393
bool $http_only = false
399394
): Response {
400395
return $this->withCookie(
401-
$name,
402396
Cookie::make($name, $value)
403397
->withMaxAge($expire)
404398
->withPath($path)
@@ -416,7 +410,7 @@ public function withCookies(array $cookies): Response
416410
{
417411
$result = clone $this;
418412
foreach ($cookies as $cookie) {
419-
$result = $result->withCookie($cookie->getName(), $cookie);
413+
$result = $result->withCookie($cookie);
420414
}
421415
return $result;
422416
}
@@ -430,13 +424,6 @@ public function withCookies(array $cookies): Response
430424
*/
431425
private function convert($content): string
432426
{
433-
if (
434-
!in_array($this->status, $this->accept_code) &&
435-
$this->status >= 400 &&
436-
!App::make(Request::class)->ajax()
437-
) {
438-
return view('errors/errors', $content)->render();
439-
}
440427
if ($content === null) {
441428
return '';
442429
}

0 commit comments

Comments
 (0)