Skip to content

Commit b5d9117

Browse files
authored
Merge pull request #11 from SDPM-lab/dev
New version V1.0.0
2 parents 8b64f41 + a91dea2 commit b5d9117

19 files changed

Lines changed: 347 additions & 84 deletions

README.md

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@
88

99
Codeigniter4-RoadRunner provides the synchroniztion of the Request and Response object between Roadrunner-Worker and Codeigniter4. Since Codeigniter4 doesn't implement [PSR-7 standard](https://codeigniter.tw/user_guide/intro/psr.html) completely, you need to use this library to allow your Codeigniter4 project to run using RoadRunner Server.
1010

11-
> This library is currently under development, and its functions are not yet stable. Do not use it in production environment.
12-
1311
[正體中文說明書](https://github.com/SDPM-lab/Codeigniter4-Roadrunner/blob/dev/README_zh-TW.md)
1412

1513
## Install
@@ -23,7 +21,7 @@ Codeigniter4-RoadRunner provides the synchroniztion of the Request and Response
2321
### Composer Install
2422
Use "Composer" to download the library and its dependencies to the project
2523
```
26-
composer require sdpmlab/codeigniter4-roadrunner "v1.0.0-beta.2"
24+
composer require sdpmlab/codeigniter4-roadrunner
2725
```
2826
Initialize Roadrunner and files using built-in commands in the library
2927

@@ -55,7 +53,7 @@ http:
5553
command: "php psr-worker.php"
5654
# pool:
5755
# numWorkers: 50
58-
# maxJobs: 10
56+
# maxJobs: 500
5957

6058
static:
6159
enable: true
@@ -142,7 +140,21 @@ http:
142140
command: "php psr-worker.php"
143141
pool:
144142
numWorkers: 1
145-
maxJobs: 1
143+
# maxJobs: 500
144+
```
145+
146+
### Database Connection
147+
148+
We only focus on supporting the Codeigniter4 built-in [Database Library](https://codeigniter.com/user_guide/database/index.html), hence we do not guarantee if using the PHP
149+
built-in method should work as normal. Therefore, you should avoid using the PHP built-in database connection method but
150+
pick the Codeigniter4 framework built-in library.
151+
152+
Under the default situation, DB of the Worker should be lasting, and will try to reconnect once the connection is failed.
153+
Every Request that goes into Worker is using a same DB connection instance. If you don't want this default setting but expecting
154+
every Request to use the reconnect DB connection instance. You can add the configuration down below into the `.env` file under the root directory.
155+
156+
```env
157+
CIROAD_DB_AUTOCLOSE = true
146158
```
147159

148160
# Global Methods

README_zh-TW.md

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@
88

99
Codeigniter4-RoadRunner 提供的是 Roadrunner-Worker 與 Codeigniter4 在 Request 與 Response 物件上的同步,因為 Codeigniter4 並沒有完整實作 [PSR-7 規範](https://codeigniter.tw/user_guide/intro/psr.html)。所以你需要使用這個程式庫才能讓你的 Codeigniter4 專案透過 RoadRunner Server 運作。
1010

11-
> 這個程式庫目前處於開發版,功能尚未穩定。請不要將它運用在正式環境中。
12-
1311
## 安裝
1412

1513
### 需求
@@ -23,7 +21,7 @@ Codeigniter4-RoadRunner 提供的是 Roadrunner-Worker 與 Codeigniter4 在 Requ
2321
於專案根目錄下,使用 Composer 下載程式庫與其所需之依賴。
2422

2523
```
26-
composer require sdpmlab/codeigniter4-roadrunner "v1.0.0-beta.2"
24+
composer require sdpmlab/codeigniter4-roadrunner
2725
```
2826

2927
使用程式庫提供的內建指令初始化 Roadrunner 與其所需的檔案。
@@ -60,7 +58,7 @@ http:
6058
command: "php psr-worker.php"
6159
# pool:
6260
# numWorkers: 50
63-
# maxJobs: 10
61+
# maxJobs: 500
6462

6563
static:
6664
enable: true
@@ -146,7 +144,17 @@ http:
146144
command: "php psr-worker.php"
147145
pool:
148146
numWorkers: 1
149-
maxJobs: 1
147+
# maxJobs: 500
148+
```
149+
150+
### 資料庫連線
151+
152+
我們只針對 Codeigniter4 內建 [Database 程式庫](https://codeigniter.tw/user_guide/database/index.html) 進行支援,並不保證 PHP 內建的方法是否能照常運作。所以,你應該避免使用內建的 PHP 資料庫連線方法,而是以 Codeigniter4 框架內建的程式庫為主。
153+
154+
預設的情況下,在 Worker 中的 DB 連線是持久的,並會在連線失效時自動重新連線。所有進入 Worker 的 Request 都使用同一個 DB 連線實體。如果你不想要這個預設設定,希望每個進入 Worker 的 Request 都使用重新連線的 DB 連線實體。你可以在專案根目錄下的 `.env` 檔案加入以下設定。
155+
156+
```env
157+
CIROAD_DB_AUTOCLOSE = true
150158
```
151159

152160
## 全域方法

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
"require": {
1919
"php" : "^7.2",
2020
"codeigniter4/framework": "^4",
21-
"spiral/roadrunner": "1.8.1",
21+
"spiral/roadrunner": "^1.8.1",
2222
"spiral/dumper": "^1.1"
2323
},
2424
"autoload": {

src/Commands/file/.rr.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ http:
44
command: "php psr-worker.php"
55
# pool:
66
# numWorkers: 50
7-
# maxJobs: 10
7+
# maxJobs: 500
88

99
static:
1010
enable: true

src/Commands/file/psr-worker.php

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use SDPMlab\Ci4Roadrunner\Debug\Toolbar;
1515
use SDPMlab\Ci4Roadrunner\Debug\Dumper;
1616
use SDPMlab\Ci4Roadrunner\UploadedFileBridge;
17+
use SDPMlab\Ci4Roadrunner\HandleDBConnection;
1718

1819
// codeigniter4 public/index.php
1920
$minPHPVersion = '7.2';
@@ -56,25 +57,19 @@ function dump($value,string $target = "ERROR_LOG") : ?string{
5657
return Dumper::getInstance()->dump($value,$target);
5758
}
5859

59-
$count = 0;
6060
while ($req = $psr7->acceptRequest()) {
61-
//記憶體控制
62-
if ($count++ > 500) {
63-
break;
64-
}
6561

66-
//請求物件相容
62+
//handle request object
6763
try {
68-
$requestBridge = new RequestBridge($req);
69-
$ci4Req = $requestBridge->getRequest();
64+
$ci4Req = RequestBridge::setRequest($req);
7065
} catch (
7166
\Throwable $e
7267
){
7368
dump((string)$e);
7469
$psr7->getWorker()->error((string)$e);
7570
}
7671

77-
//處理除錯工具列
72+
//handle debug-bar
7873
try{
7974
if(ENVIRONMENT === 'development'){
8075
$toolbar = new Toolbar(config('Toolbar'),$ci4Req);
@@ -89,8 +84,9 @@ function dump($value,string $target = "ERROR_LOG") : ?string{
8984
$psr7->getWorker()->error((string)$e);
9085
}
9186

92-
//執行框架邏輯與錯誤處理
87+
//run framework and error handling
9388
try{
89+
if(!env("CIROAD_DB_AUTOCLOSE")) HandleDBConnection::reconnect();
9490
$ci4Response = $app->setRequest($ci4Req)->run();
9591
}catch(
9692
\Throwable $e
@@ -102,12 +98,10 @@ function dump($value,string $target = "ERROR_LOG") : ?string{
10298
continue;
10399
}
104100

105-
//響應物件轉換
101+
//handle response object
106102
try {
107103
$response = new ResponseBridge($ci4Response,$req);
108-
//傳遞處理結果
109104
$psr7->respond($response);
110-
//初始化 CI4 以及 PHP 輸出輸入內容
111105
init();
112106
} catch (
113107
\Throwable $e
@@ -127,8 +121,15 @@ function init()
127121
try {
128122
ob_end_clean();
129123
} catch (\Throwable $th) {}
124+
130125
\CodeIgniter\Config\Services::reset(true);
126+
131127
UploadedFileBridge::reset();
128+
129+
if(env("CIROAD_DB_AUTOCLOSE")){
130+
HandleDBConnection::closeConnect();
131+
}
132+
132133
$appConfig = config(\Config\App::class);
133134
$app = new \CodeIgniter\CodeIgniter($appConfig);
134135
$app->initialize();

src/HandleDBConnection.php

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?php
2+
namespace SDPMlab\Ci4Roadrunner;
3+
4+
class HandleDBConnection
5+
{
6+
public static function closeConnect()
7+
{
8+
$dbInstances = \Config\Database::getConnections();
9+
foreach ($dbInstances as $connection) {
10+
$connection->close();
11+
}
12+
}
13+
14+
public static function reconnect()
15+
{
16+
$dbInstances = \Config\Database::getConnections();
17+
foreach ($dbInstances as $connection) {
18+
if($connection->DBDriver == "MySQLi"){
19+
try {
20+
$connection->mysqli->ping();
21+
} catch (\Throwable $th) {
22+
$connection->reconnect();
23+
}
24+
}else{
25+
$connection->reconnect();
26+
}
27+
}
28+
}
29+
}
30+
31+
?>

src/RequestBridge.php

Lines changed: 27 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -7,78 +7,63 @@
77

88
class RequestBridge
99
{
10-
private $_rRequest;
10+
private static $_rRequest;
1111

12-
public function __construct(ServerRequest $rRequest)
12+
public static function setRequest(ServerRequest $rRequest)
1313
{
14-
$this->_rRequest = $rRequest;
15-
$this->setFile();
16-
$_SERVER['HTTP_USER_AGENT'] = $this->_rRequest->getHeaderLine("User-Agent");
14+
self::$_rRequest = $rRequest;
15+
self::setFile();
16+
$_SERVER['HTTP_USER_AGENT'] = self::$_rRequest->getHeaderLine("User-Agent");
1717
\CodeIgniter\Config\Services::request(new \Config\App(),false);
1818
\CodeIgniter\Config\Services::request()->getUserAgent()->parse($_SERVER['HTTP_USER_AGENT']);
19-
$this->setUri();
20-
\CodeIgniter\Config\Services::request()->setBody($this->getBody());
21-
$this->setParams();
22-
$this->setHeader();
19+
UriBridge::setUri(self::$_rRequest->getUri());
20+
\CodeIgniter\Config\Services::request()->setBody(self::getBody());
21+
self::setParams();
22+
self::setHeader();
23+
return \CodeIgniter\Config\Services::request();
2324
}
2425

25-
private function setFile(){
26-
if(count($this->_rRequest->getUploadedFiles()) > 0){
27-
UploadedFileBridge::getPsr7UploadedFiles($this->_rRequest->getUploadedFiles(),true);
26+
protected static function setFile(){
27+
if(count(self::$_rRequest->getUploadedFiles()) > 0){
28+
UploadedFileBridge::getPsr7UploadedFiles(self::$_rRequest->getUploadedFiles(),true);
2829
}
2930
}
3031

31-
private function getBody(){
32+
protected static function getBody(){
3233
$body = "";
33-
if(strpos($this->_rRequest->getHeaderLine("content-type"), "application/json") === 0){
34-
$body = $this->_rRequest->getBody();
35-
}else if(
36-
strpos($this->_rRequest->getHeaderLine("content-type"), "text/plain") === 0 ||
37-
strpos($this->_rRequest->getHeaderLine("content-type"), "application/javascript") === 0 ||
38-
strpos($this->_rRequest->getHeaderLine("content-type"), "text/html") === 0 ||
39-
strpos($this->_rRequest->getHeaderLine("content-type"), "application/xml") === 0
40-
){
41-
$body = $this->_rRequest->getBody()->getContents();
34+
if(strpos(self::$_rRequest->getHeaderLine("content-type"), "application/json") === 0){
35+
$body = self::$_rRequest->getBody();
4236
}else{
43-
$body = http_build_query($this->_rRequest->getParsedBody()??[]);
37+
$body = self::$_rRequest->getBody()->getContents();
4438
}
4539
return $body;
4640
}
4741

48-
private function setParams(){
49-
\CodeIgniter\Config\Services::request()->setMethod($this->_rRequest->getMethod());
50-
\CodeIgniter\Config\Services::request()->setGlobal("get",$this->_rRequest->getQueryParams());
51-
if($this->_rRequest->getMethod() == "POST"){
52-
\CodeIgniter\Config\Services::request()->setGlobal("post",$this->_rRequest->getParsedBody());
42+
protected static function setParams(){
43+
\CodeIgniter\Config\Services::request()->setMethod(self::$_rRequest->getMethod());
44+
\CodeIgniter\Config\Services::request()->setGlobal("get",self::$_rRequest->getQueryParams());
45+
if(self::$_rRequest->getMethod() == "POST"){
46+
\CodeIgniter\Config\Services::request()->setGlobal("post",self::$_rRequest->getParsedBody());
5347
}
5448
$_COOKIE = [];
55-
\CodeIgniter\Config\Services::request()->setGlobal("cookie",$this->_rRequest->getCookieParams());
56-
foreach ($this->_rRequest->getCookieParams() as $key => $value) {
49+
\CodeIgniter\Config\Services::request()->setGlobal("cookie",self::$_rRequest->getCookieParams());
50+
foreach (self::$_rRequest->getCookieParams() as $key => $value) {
5751
$_COOKIE[$key] = $value;
5852
}
5953
if(isset($_COOKIE[config(App::class)->sessionCookieName])){
6054
session_id($_COOKIE[config(App::class)->sessionCookieName]);
6155
}
62-
\CodeIgniter\Config\Services::request()->setGlobal("server",$this->_rRequest->getServerParams());
56+
\CodeIgniter\Config\Services::request()->setGlobal("server",self::$_rRequest->getServerParams());
6357
}
6458

65-
private function setHeader(){
66-
$rHeader = $this->_rRequest->getHeaders();
59+
protected static function setHeader(){
60+
$rHeader = self::$_rRequest->getHeaders();
6761
foreach ($rHeader as $key => $datas) {
6862
foreach ($datas as $values) {
6963
\CodeIgniter\Config\Services::request()->setHeader($key,$values);
7064
}
7165
}
7266
}
7367

74-
private function setUri(){
75-
$uriBridge = new UriBridge($this->_rRequest->getUri());
76-
$uriBridge->setUri();
77-
}
78-
79-
public function getRequest(){
80-
return \CodeIgniter\Config\Services::request();
81-
}
82-
8368
}
8469
?>

src/UriBridge.php

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,17 @@
33

44
class UriBridge
55
{
6-
private $_rURI;
6+
private static $_rURI;
77

8-
public function __construct(\Laminas\Diactoros\Uri $rURI)
9-
{
8+
public static function setUri(\Laminas\Diactoros\Uri $rURI){
109
\CodeIgniter\Config\Services::uri(null,false);
11-
$this->_rURI = $rURI;
10+
self::$_rURI = $rURI;
11+
self::transferPath();
12+
self::transferQuery();
1213
}
1314

14-
public function setUri(){
15-
$this->transferPath();
16-
$this->transferQuery();
17-
}
18-
19-
private function transferPath(){
20-
$rPath = $this->_rURI->getPath();
15+
protected static function transferPath(){
16+
$rPath = self::$_rURI->getPath();
2117

2218
if($rPath == "/"){
2319
\CodeIgniter\Config\Services::uri()->setPath($rPath);
@@ -38,8 +34,8 @@ private function transferPath(){
3834

3935
}
4036

41-
private function transferQuery(){
42-
\CodeIgniter\Config\Services::uri()->setQuery($this->_rURI->getQuery());
37+
protected static function transferQuery(){
38+
\CodeIgniter\Config\Services::uri()->setQuery(self::$_rURI->getQuery());
4339
}
4440

4541
}

test/.rr.yaml

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,17 @@ http:
44
command: "php psr-worker.php"
55
pool:
66
numWorkers: 1
7-
maxJobs: 1
7+
# maxJobs: 500
88

99
static:
1010
enable: true
1111
dir: "public"
12-
forbid: [".php", ".htaccess"]
12+
forbid: [".php", ".htaccess"]
13+
14+
# reload:
15+
# interval: 1s
16+
# patterns: [".php"]
17+
# services:
18+
# http:
19+
# dirs: [""]
20+
# recursive: true

0 commit comments

Comments
 (0)