sdpmlab/codeigniter4-roadrunner

使Codeigniter4在Roadrunner服务器上运行。

v1.3.1 2022-06-15 13:41 UTC

README

logo

Latest Stable Version Total Downloads Latest Unstable Version License

Codeigniter4-RoadRunner提供了Roadrunner-Worker和Codeigniter4之间请求和响应对象的同步。由于Codeigniter4没有完全实现PSR-7标准,您需要使用此库以允许您的Codeigniter4项目在RoadRunner服务器上运行。

正體中文說明書

安装

先决条件

  1. CodeIgniter框架4.2.0^
  2. Composer
  3. 启用php-curl扩展
  4. 启用php-zip扩展
  5. 启用php-sockets扩展

Composer安装

使用"Composer"下载库及其依赖项到项目

composer require sdpmlab/codeigniter4-roadrunner

使用库内置命令初始化Roadrunner和文件

php spark ciroad:init

运行

在项目根目录运行命令

  1. 在Windows上使用Roadrunner命令
rr.exe serve -d
  1. 在MacOS/Linux上使用Roadrunner命令
./rr serve -d

服务器设置

服务器设置都在项目根目录的".rr.yaml"中。默认文件看起来像这样

version: "2.7"

rpc:
  listen: tcp://127.0.0.1:6001

server:
  command: "php psr-worker.php"
  # env:
  #   XDEBUG_SESSION: 1

http:
  address: "0.0.0.0:8080"
  static:
    dir: "./public"
    forbid: [".htaccess", ".php"]
  pool:
    num_workers: 1
    # max_jobs: 64
    # debug: true

# reload:
#   interval: 1s
#   patterns: [ ".php" ]
#   services:
#     http:
#       recursive: true
#       ignore: [ "vendor" ]
#       patterns: [ ".php", ".go", ".md" ]
#       dirs: [ "." ]

您可以根据Roadrunner文档创建自己的配置文件。

开发建议

自动重新加载

在RoadRunner的默认情况下,每次您修改任何PHP文件后都必须重新启动服务器,以便您的修改生效。这在开发过程中似乎并不友好。

您可以通过修改.rr.yaml配置文件,添加以下设置,并用-d启动开发模式。RoadRunner服务器将自动检测PHP文件是否已修改,并立即重新加载Worker。

reload:
  interval: 1s
  patterns: [ ".php" ]
  services:
    http:
      recursive: true
      ignore: [ "vendor" ]
      patterns: [ ".php", ".go", ".md" ]
      dirs: [ "." ]

reload功能非常消耗资源,请勿在正式环境中激活此选项。

使用Codeigniter4请求和响应对象

Codeigniter4没有完全实现HTTP消息接口,因此此库专注于PSR-7接口Codeigniter4 HTTP接口的同步。

基于上述原因,您应使用Codeigniter4提供的$this->request或全局函数/Config/Services::('request')来获取正确的请求对象;使用$this->response/Config/Services::('response')来获取正确的响应对象。

请注意,在开发过程中构建响应时,您应避免使用PHP内置方法进行headerset-cookies设置。使用由Codeigniter4响应对象提供的setHeader()setCookie()进行设置。

使用return停止控制器逻辑

在控制器内部,尝试使用return停止控制器逻辑。无论是对视图还是API的响应,减少echo输出的使用可以避免许多错误,就像这样

<?php namespace App\Controllers;

use CodeIgniter\API\ResponseTrait;

class Home extends BaseController
{
  use ResponseTrait;

  public function index()
  {
    // Don't use:
    // echo view('welcome_message');
    return view('welcome_message');
  }

  /**
   * send header
   */
   public function sendHeader()
   {
     $this->response->setHeader("X-Set-Auth-Token", uniqid());
     return $this->respond(["status"=>true]);
   }

}

使用内置的Session库

我们只专注于支持Codeigniter4内置的Session库,并无法保证使用session_start()$_SEEEION可以正常工作。因此,您应避免使用PHP内置的Session方法,改用Codeigniter4框架内置的库。

在仅有一个Worker的环境中开发和调试

由于RoadRunner与其它服务器软件(例如Nginx、Apache)在本质上存在差异,每个Codeigniter4实例都将作为Worker形式存在于RAM中。HTTP请求会复用这些Worker来处理。因此,我们最好在只有一个Worker的环境下开发和测试稳定性,以证明它也能在正式环境下的多个Worker中正常运行。

您可以参考以下.rr.yaml设置来将Worker的数量降至最低

http:
  address: "0.0.0.0:8080"
  static:
    dir: "./public"
    forbid: [".htaccess", ".php"]
  pool:
    num_workers: 1
    # max_jobs: 64
    # debug: true

数据库连接

我们只关注支持Codeigniter4内置的数据库库,因此我们不保证使用PHP内置方法是否能够正常工作。因此,您应该避免使用PHP内置的数据库连接方法,而是选择Codeigniter4框架内置的库。

在默认情况下,Worker的数据库连接应该是持久的,并在连接失败时尝试重新连接。每个进入Worker的请求都会使用相同的数据库连接实例。如果您不想使用此默认设置,而是希望每个请求都使用重新连接的数据库连接实例,您可以将在根目录下的.env文件中添加以下配置。

CIROAD_DB_AUTOCLOSE = true

全局方法

我们提供了一些全局方法,以帮助您更顺畅地开发项目。

处理文件上传

由于RoadRunner Worker无法传递正确的$_FILES上下文,Codeigniter4文件上传类将无法正常工作。为了解决这个问题,我们为您提供了一个符合PSR-7标准的文件上传类,以便您在RoadRunner中正确处理文件上传。即使您将项目切换到另一个服务器环境(例如spark serve、Apache、Nginx),这个类仍然可以正常工作,且不需要任何代码修改。

您可以通过控制器(或任何其他位置)中的SDPMlab\Ci4Roadrunner\UploadedFileBridge::getPsr7UploadedFiles()来获取上传的文件。此方法将返回一个数组,其中包含上传文件对象。该对象的方法与PSR-7 上传文件接口的规定相同。

<?php

namespace App\Controllers;

use CodeIgniter\API\ResponseTrait;
use SDPMlab\Ci4Roadrunner\UploadedFileBridge;

class FileUploadTest extends BaseController
{
    use ResponseTrait;

    protected $format = "json";

    /**
     * form-data 
     */
    public function fileUpload()
    {
        $files = UploadedFileBridge::getPsr7UploadedFiles();
        $data = [];
        foreach ($files as $file) {
            $fileNameArr = explode('.', $file->getClientFilename());
            $fileEx = array_pop($fileNameArr);
            $newFileName = uniqid(rand()) . "." . $fileEx;
            $newFilePath = WRITEPATH . 'uploads' . DIRECTORY_SEPARATOR . $newFileName;
            $file->moveTo($newFilePath);
            $data[$file->getClientFilename()] = md5_file($newFilePath);
        }
        return $this->respondCreated($data);
    }

    /**
     * form-data multiple upload
     */
    public function fileMultipleUpload()
    {
        $files = UploadedFileBridge::getPsr7UploadedFiles()["data"];
        $data = [];
        foreach ($files as $file) {
            $fileNameArr = explode('.', $file->getClientFilename());
            $fileEx = array_pop($fileNameArr);
            $newFileName = uniqid(rand()) . "." . $fileEx;
            $newFilePath = WRITEPATH . 'uploads' . DIRECTORY_SEPARATOR . $newFileName;
            $file->moveTo($newFilePath);
            $data[$file->getClientFilename()] = md5_file($newFilePath);
        }
        return $this->respondCreated($data);
    }
}

处理抛出的错误

如果您在-d开发模式下遇到了需要确认的一些变量或对象内容,您可以使用全局函数dump()在程序任何位置将错误抛出到终端。

可用命令

ciroad:init

初始化RoadRunner及其所需文件。

  • 使用
    $ php spark ciroad:init
    

RoadRunner服务器命令

有关可用命令,您可以参考RoadRunner 官方文档中的说明。