Skip to content

Commit f0d643d

Browse files
committed
web 0.5
0 parents  commit f0d643d

23 files changed

+2359
-0
lines changed

.editorconfig

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# EditorConfig is awesome: http://EditorConfig.org
2+
root = true
3+
4+
[*]
5+
end_of_line = lf
6+
indent_style = space
7+
indent_size = 4
8+
trim_trailing_whitespace = true

.gitattributes

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
* text=auto
2+
3+
/tests export-ignore
4+
/.* export-ignore
5+
/*.xml export-ignore

.gitignore

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
!.gitkeep
2+
vendor/*
3+
composer.lock
4+
.scannerwork/*
5+
build/*
6+
sonar-project.properties

LICENSE

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) ueaner <[email protected]>
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

+58
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
Soli PHP Web
2+
----------------
3+
4+
Soli Web Component.
5+
6+
## 安装
7+
8+
使用 `composer` 进行安装:
9+
10+
composer require soliphp/web
11+
12+
## 使用
13+
14+
如下我们编写 `index.php` 文件,内容为:
15+
16+
```php
17+
<?php
18+
19+
// 默认控制器命名空间
20+
namespace App\Controllers;
21+
22+
include __DIR__ . "/vendor/autoload.php";
23+
24+
class IndexController extends \Soli\Controller
25+
{
26+
public function index()
27+
{
28+
return 'Hello, Soli.';
29+
}
30+
}
31+
32+
$app = new \Soli\Web\App();
33+
34+
// 处理请求,输出响应内容
35+
$app->handle()->send();
36+
37+
$app->terminate();
38+
```
39+
40+
1. 使用 php -S 启动 webserver
41+
42+
```
43+
php -S localhost:8000
44+
```
45+
46+
2. 浏览器访问 `http://localhost:8000/`,即可看到如下信息:
47+
48+
```
49+
Hello, Soli.
50+
```
51+
52+
53+
## License
54+
55+
[MIT License]
56+
57+
58+
[MIT License]: LICENSE

composer.json

+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
{
2+
"name": "soliphp/web",
3+
"description": "Soli PHP web.",
4+
"type": "library",
5+
"keywords": ["web", "http", "soliphp", "soli"],
6+
"homepage": "https://github.com/soliphp/web",
7+
"support": {
8+
"issues": "https://github.com/soliphp/web/issues",
9+
"source": "https://github.com/soliphp/web"
10+
},
11+
"license": "MIT",
12+
"authors": [
13+
{
14+
"name": "ueaner",
15+
"email": "[email protected]"
16+
}
17+
],
18+
"require": {
19+
"php": ">=7.0",
20+
"ext-json": "*",
21+
"soliphp/framework": "dev-master",
22+
"soliphp/helpers": "^1.1",
23+
"soliphp/view": "^1.0",
24+
"nikic/fast-route": "^1.3",
25+
"vlucas/phpdotenv": "^2.6"
26+
},
27+
"autoload": {
28+
"psr-4": {
29+
"Soli\\": "src/"
30+
}
31+
},
32+
"autoload-dev": {
33+
"psr-4": {
34+
"Soli\\Tests\\": "tests/"
35+
}
36+
},
37+
"repositories": {
38+
"packagist": {
39+
"type": "composer",
40+
"url": "https://packagist.laravel-china.org"
41+
}
42+
},
43+
"extra": {
44+
"branch-alias": {
45+
"dev-master": "1.0-dev"
46+
}
47+
},
48+
"minimum-stability": "dev",
49+
"prefer-stable": true
50+
}

phpcs.xml

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?xml version="1.0"?>
2+
<ruleset name="Soli Coding Standard">
3+
<description>Soli Coding Standard</description>
4+
5+
<!-- display progress -->
6+
<arg value="p"/>
7+
<!-- display sniff codes -->
8+
<arg value="s"/>
9+
<!-- use colors in output -->
10+
<arg name="colors"/>
11+
<!-- file extensions -->
12+
<arg name="extensions" value="php"/>
13+
14+
<!-- inherit rules from: -->
15+
<rule ref="PSR2"/>
16+
<rule ref="Generic.Arrays.DisallowLongArraySyntax"/>
17+
<rule ref="PSR1">
18+
<exclude name="PSR1.Files.SideEffects.FoundWithSymbols"/>
19+
</rule>
20+
21+
<!-- Paths to check -->
22+
<file>src</file>
23+
<file>tests</file>
24+
</ruleset>

phpunit.xml

+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<phpunit backupGlobals="false"
3+
backupStaticAttributes="false"
4+
colors="true"
5+
convertErrorsToExceptions="true"
6+
convertNoticesToExceptions="true"
7+
convertWarningsToExceptions="true"
8+
processIsolation="false"
9+
stopOnFailure="false"
10+
verbose="true"
11+
bootstrap="vendor/autoload.php"
12+
>
13+
<php>
14+
<ini name="xdebug.show_exception_trace" value="0"/>
15+
<ini name="error_reporting" value="-1"/>
16+
<ini name="display_errors" value="1"/>
17+
</php>
18+
19+
<testsuites>
20+
<testsuite name="Soli Test Suite">
21+
<directory suffix="Test.php">tests</directory>
22+
</testsuite>
23+
</testsuites>
24+
25+
<filter>
26+
<whitelist processUncoveredFilesFromWhitelist="true">
27+
<directory suffix=".php">src</directory>
28+
</whitelist>
29+
</filter>
30+
31+
<logging>
32+
<log type="coverage-html" target="build/coverage" lowUpperBound="35" highLowerBound="70"/>
33+
<log type="coverage-clover" target="build/logs/clover.xml"/>
34+
<log type="coverage-crap4j" target="build/logs/crap4j.xml"/>
35+
<log type="junit" target="build/logs/junit.xml"/>
36+
</logging>
37+
38+
<listeners>
39+
<listener class="JohnKary\PHPUnit\Listener\SpeedTrapListener">
40+
<arguments>
41+
<array>
42+
<element key="slowThreshold">
43+
<integer>10</integer>
44+
</element>
45+
<element key="reportLength">
46+
<integer>8</integer>
47+
</element>
48+
</array>
49+
</arguments>
50+
</listener>
51+
</listeners>
52+
</phpunit>

src/Web/App.php

+127
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
<?php
2+
/**
3+
* @author ueaner <[email protected]>
4+
*/
5+
namespace Soli\Web;
6+
7+
use Soli\App as BaseApp;
8+
use Throwable;
9+
10+
/**
11+
* 应用
12+
*
13+
* @property \Soli\RouterInterface $router
14+
* @property \Soli\Dispatcher $dispatcher
15+
* @property \Soli\Web\Request $request
16+
* @property \Soli\Web\Response $response
17+
* @property \Soli\Web\Session $session
18+
* @property \Soli\Web\Flash $flash
19+
* @property \Soli\ViewInterface $view
20+
*/
21+
class App extends BaseApp
22+
{
23+
/**
24+
* 默认注册服务
25+
*/
26+
protected $coreServices = [
27+
'router' => [\Soli\Web\Router::class, \Soli\RouterInterface::class],
28+
'dispatcher' => [\Soli\Dispatcher::class, \Soli\DispatcherInterface::class],
29+
'events' => [\Soli\Events\EventManager::class, \Soli\Events\EventManagerInterface::class],
30+
'request' => [\Soli\Web\Request::class],
31+
'response' => [\Soli\Web\Response::class],
32+
'session' => [\Soli\Web\Session::class],
33+
'flash' => [\Soli\Web\Flash::class],
34+
];
35+
36+
/**
37+
* 应用程序启动方法
38+
*
39+
* @noinspection PhpDocMissingThrowsInspection
40+
* @param string $uri
41+
* @return \Soli\Web\Response
42+
*/
43+
public function handle($uri = null)
44+
{
45+
try {
46+
$returnedResponse = parent::handle($uri);
47+
return $this->handleWeb($returnedResponse);
48+
} catch (Throwable $e) {
49+
/** @noinspection PhpUnhandledExceptionInspection */
50+
return $this->handleException($e);
51+
}
52+
}
53+
54+
protected function handleWeb($returnedResponse)
55+
{
56+
// 不自动渲染视图的四种方式:
57+
// 1. 返回 Response 实例
58+
// 2. 返回 string 类型作为响应内容
59+
// 3. 返回 false
60+
// 4. 禁止自动渲染视图 $view->disable()
61+
62+
if ($returnedResponse instanceof Response) {
63+
$response = $returnedResponse;
64+
} else {
65+
$response = $this->response;
66+
if (is_string($returnedResponse)) {
67+
// 作为响应内容
68+
$response->setContent($returnedResponse);
69+
} elseif ($returnedResponse !== false) {
70+
// 渲染视图
71+
$response->setContent($this->viewRender());
72+
}
73+
}
74+
75+
return $response;
76+
}
77+
78+
/**
79+
* 获取视图自动渲染内容
80+
*
81+
* @codeCoverageIgnore
82+
* @return string
83+
*/
84+
protected function viewRender()
85+
{
86+
if (!$this->container->has('view')) {
87+
return null;
88+
}
89+
90+
// 视图实例
91+
$view = $this->view;
92+
93+
// 禁止自动渲染视图
94+
if ($view->isDisabled()) {
95+
return null;
96+
}
97+
98+
// 获取模版文件路径
99+
$controller = $this->dispatcher->getHandlerName();
100+
$action = $this->dispatcher->getActionName();
101+
$template = "$controller/$action";
102+
103+
// 将 Flash 服务添加到 View
104+
$view->setVar('flash', $this->flash);
105+
106+
// 自动渲染视图
107+
return $view->render($template);
108+
}
109+
110+
/**
111+
* @noinspection PhpDocMissingThrowsInspection
112+
* @param Throwable $e
113+
* @return mixed|Response
114+
*/
115+
protected function handleException(Throwable $e)
116+
{
117+
// trigger 返回 true/false 表示是否有且执行了事件监听
118+
$handled = $this->trigger('app.exception', $e);
119+
// 将处理信息写入 response
120+
if ($handled) {
121+
return $this->response;
122+
}
123+
124+
/** @noinspection PhpUnhandledExceptionInspection */
125+
throw $e;
126+
}
127+
}

0 commit comments

Comments
 (0)