swoft2 教程系列-HTTP Server

Http 生命週期
瞭解請求生命週期, 有利於理解HTTP服務各組件, 編寫出更好代碼.


配置參數
在應用下的 app/bean.php 配置 server,在這個文件裏,你可以看到 Http Server數組裏麪包含了 Http Server 的基本信息。下面列舉了一些簡單的配置,你也可以自由組合同時提供多種服務。

'httpServer' => [
 'class' => HttpServer::class,
 'port' => 18306,
 'listener' => [
 'rpc' => bean('rpcServer')
 ],
 'process' => [
 //  'monitor' => bean(MonitorProcess::class)
 //  'crontab' => bean(CrontabProcess::class)
 ],
 'on' => [
 // Enable task must task and finish event
 SwooleEvent::TASK   => bean(TaskListener::class), 
 SwooleEvent::FINISH => bean(FinishListener::class)
 ],
 /* @see HttpServer::$setting */
 'setting' => [
 'task_worker_num' => 12,
 'task_enable_coroutine' => true,
 'worker_num' => 6,
 // Enable Https 這個是配置https證書的可以不設置
 'ssl_cert_file' => '/my/certs/2288803_www.domain.com.pem',
 'ssl_key_file' => '/my/certs/2288803_www.domain.com.key',
 ]
 ],
 //Enable Https
 'type' => SWOOLE_SOCK_TCP | SWOOLE_SSL,


配置項 http server 除了 class 其他都是 http server 的屬性。
配置介紹
class 指定 Http Server 的處理類
port 指定 Http Server 的端口
listener 指定其他一同啓動的服務,添加端口服務監聽,可以多個。
rpc 啓動 RPC 服務
process 啓動自定義用戶進程
on 配置監聽的事件 註冊事件、設置對應事件的處理監聽,事件觸發組件調用,在任務裏面使用
setting 這裏是參考 Swoole Server 配置選項

  • pidFile 設置進程 pid 文件 位置,默認值 @runtime/swoft.pid
  • mode 運行的模式,參考 Swoole Server 構造函數 第三個參數
  • type 指定Socket的類型,支持TCP、UDP、TCP6、UDP6、UnixSocket Stream/Dgram 等 Swoole Server 構造函數 第四個參數
  • 啓用 Https 支持 注意: 你必須安裝 OpenSSL 庫,並且確保安裝 swoole 時是啓用了 ssl 選項的。同時,需要設置 ‘type’ => SWOOLE_SOCK_TCP | SWOOLE_SSL

Controller 控制器
控制器作爲HTTP服務的核心組件,串接起一次請求的整個生命週期. 通過 註解 的方式,相較於傳統的 Controller,代碼更簡潔,用戶可以更關注業務邏輯。
創建控制器
主要通過 @Controller 註解實現。代碼可以放置任意位置,不過爲了統一標準,建議放在 app/Http/Controller 下

namespace App\Http\Controller;

use Swoft\Http\Message\ContentType;
use Swoft\Http\Message\Response;
use Swoft\Http\Server\Annotation\Mapping\Controller;
use Swoft\Http\Server\Annotation\Mapping\RequestMapping;
use Swoft\View\Annotation\Mapping\View;
use Throwable;

/**
 * Class ViewController
 *
 * @since 2.0
 *
 * @Controller(prefix="view")
 */
class ViewController
{
 /**
     * @RequestMapping("index")
     *
     * @param Response $response
     *
     * @return Response
     */
 public function index(Response $response): Response
 {
        $response = $response->withContent('<html lang="en"><h1>Swoft framework</h1></html>');
        $response = $response->withContentType(ContentType::HTML);
 return $response;
 }
}


代碼分析
@Controller 註解
Http 控制器類註解 @Controller
註解類:Swoft\Http\Server\Annotation\Mapping\Controller

  • 作用範圍:CLASS
  • 擁有屬性:
  • prefix 指定路由前綴

通常僅有 @Controller 是沒有什麼效果的,它需要配合接下來的 @RequestMapping 一起才能正確的工作。

路由規則
顯式指定路由前綴:@Controller(prefix=”/index”) 或 @Controller(“/index”)。
隱式指定路由前綴:@Controller() 默認自動使用 小駝峯 格式解析 controller class 的名稱。
示例:class IndexController 對應路由 /index
一個完整的路由規則是通過 @Controller + @RequestMapping 註解實現,通常前者定義前綴,後者定義後綴。關於 @RequestMapping 註解將在稍後 路由-@RequestMapping 章節將會詳細介紹。

在 Swoft 裏不要按照傳統的 fpm 框架繼承父類控制器的成員屬性在其他控制器使用,這種做法是錯誤的。
錯誤示範:

/**
 * @Controller()
 */
class BaseController
{
 protected $num;
}

/**
 * @Controller(prefix="/v1/index")
 */
class IndexController extends BaseController
{
 /**
     * @RequestMapping(route="index")
     */
 public function index()
 {
        $this->num++;
        echo $this->num."\n";//這裏每次訪問輸出的都不一樣
 }
}


此時每次訪問num數字都會增1,這個是錯誤的使用方式,和傳統的 php-fpm 有很大區別.傳統的 fpm 每次執行過後都會釋放內存,而 swoft 是常駐內存的 大家一定要注意
路由
Swoft 與傳統的 PHP 框架不一樣,並沒有採用配置文件的方式來配置路由,而採用了註解。在 Swoft 裏我們可以使用 @RequestMapping 註解快速的添加路由。
@RequestMapping 註解
Http 控制器類中方法路由註解 @RequestMapping

  • route 路由規則path
  • method 請求方式(GET、POST、PUT、PATCH、DELETE、OPTIONS、HEAD)
  • params 可以通過它爲path變量添加正則匹配限制

每個方法上儘量只寫一個 @RequestMapping 註解,以免出現紊亂。
路由規則
通常情況,一個完整的路由 path 等於 @Controller 的 prefix + @RequestMapping 的 route 顯示指定路由後綴:@RequestMapping(“index”) 或 @RequestMapping(route=”index”)
隱式指定路由後綴: 使用 @RequestMapping() 默認解析方法名爲後綴
特殊的,當你的 @RequestMapping 上的路由以 / 開頭時,那完整的路由就是它,即不會再將 prefix 添加到它的前面
允許的請求方法爲默認爲 GET 和 POST 當設置跨域是需要手動指定允許 OPTIONS
綁定路由 path 參數
指定路由參數: @RequestMapping(route=”index/{name}”),Action 方法中可以直接使用 $name 作爲方法參數
當路由參數被 [] 包起來則 URL path 傳遞參數是可選的。注意,可選符只能用在最後面

  • 示例1: @RequestMapping(“/index[/{name}]”) 這樣 /index /index/tom 都可以訪問到
  • 示例2: @RequestMapping(“/about[.html]”) 相當於僞靜態,/about /about.html 都可以訪問到

設置路由請求方式
如果想要設置允許請求控制器的 HTTP 請求方式。 可以使用方法在控制器中的 @RequestMapping 註解配置 method 參數,可以是 GET、POST、PUT、PATCH、DELETE、OPTIONS、HEAD 中的一個或多個。

@RequestMapping(route="index",method={RequestMethod::GET,RequestMethod::POST})


請切記要引入相關的註解類

Swoft\Http\Server\Annotation\Mapping\RequestMapping
Swoft\Http\Server\Annotation\Mapping\RequestMethod


Http 請求對象
Swoft 的請求與響應實現於 PSR-7 規範。請求與響應對象存在於每次 HTTP 請求。

  • 請求對象 Request 爲 Swoft\Http\Message\Request
  • 響應對象 Response 爲 Swoft\Http\Message\Response

獲取請求對象

$request = context()->getRequest();


示例: 獲取請求的 URI

$uri=$request->getUri();


請求對象的 URI 本身就是一個對象,它提供了下列方法檢查 HTTP 請求的 URL 部分

$uri->getScheme()

$uri->getAuthority()

$uri->getUserInfo()

$uri->getHost()

$uri->getPort()

$uri->getPath()

$uri->getQuery() (例如 a=1&b=2)

$uri->getFragment()


示例: 獲取請求 Headers
全部的 Headers

$headers = $request->getHeaders();


指定的 Header

$host = $request->getHeaderLine("host");


示例: 獲取請求的數據
GET 數據

$data = $request->query();

$some = $request->query('key', 'default value')

$data = $request->get();

$some = $request->get('key','default value');


POST 數據

$data = $request->post();

$some = $request->post('key', 'default value')


無需關心請求的數據格式,json xml 請求都會自動解析爲 php 的數組數據。都可以通過 $request->post() 獲取。
同時獲取 GET & POST 數據

$data = $request->input();

$some = $request->input('key', 'default value')


RAW 數據

$data = $request->raw();


SERVER 數據

$data = $request->getServerParams();

$some = $request->server('key', 'default value')


獲取上傳文件

$file = $request->getUploadedFiles();


獲取的結果是一維數組或者二位數組,數據結構如下。 若表單中上傳的是單文件則返回的是一個一維數組,數組內容是 Swoft\Http\Message\Upload\UploadedFile 文件對象,例如文件字段名爲 file 則數據結構如下
注意這個 UploadedFile 對象的屬性都是私有屬性,withdata過濾了私有屬性所以直接輸出 $file這個對象輸出的是個空數組,而不是上傳未接受到數據.
獲取的結果是一維數組或者二位數組,數據結構如下。 若表單中上傳的是單文件則返回的是一個一維數組,數組內容是 Swoft\Http\Message\Upload\UploadedFile 文件對象,例如文件字段名爲 file 則數據結構如下

array(1) {
 ["file"]=>
 object(Swoft\Http\Message\Upload\UploadedFile)#6510 (7) {
 ["size":"Swoft\Http\Message\Upload\UploadedFile":private]=>
 int(1319)
 ["errorCode":"Swoft\Http\Message\Upload\UploadedFile":private]=>
 int(0)
 ["file":"Swoft\Http\Message\Upload\UploadedFile":private]=>
 string(25) "/tmp/swoole.upfile.f7p2EL"
 ["clientFilename":"Swoft\Http\Message\Upload\UploadedFile":private]=>
 string(6) "at.png"
 ["clientMediaType":"Swoft\Http\Message\Upload\UploadedFile":private]=>
 string(9) "image/png"
 ["moved":"Swoft\Http\Message\Upload\UploadedFile":private]=>
    NULL
 ["path":"Swoft\Http\Message\Upload\UploadedFile":private]=>
    NULL
 }
}


若表單中是一個字段數組上傳多個文件如 file[] 則返回的是一個二維數組,數組內容依然是 Swoft\Http\Message\Upload\UploadedFile 文件對象,數據結構如下

array(1) {
 ["file"]=>
  array(2) {
 [0]=>
 object(Swoft\Http\Message\Upload\UploadedFile)#6516 (7) {
 ["size":"Swoft\Http\Message\Upload\UploadedFile":private]=>
 int(1319)
 ["errorCode":"Swoft\Http\Message\Upload\UploadedFile":private]=>
 int(0)
 ["file":"Swoft\Http\Message\Upload\UploadedFile":private]=>
 string(25) "/tmp/swoole.upfile.TVKdOS"
 ["clientFilename":"Swoft\Http\Message\Upload\UploadedFile":private]=>
 string(6) "at.png"
 ["clientMediaType":"Swoft\Http\Message\Upload\UploadedFile":private]=>
 string(9) "image/png"
 ["moved":"Swoft\Http\Message\Upload\UploadedFile":private]=>
      NULL
 ["path":"Swoft\Http\Message\Upload\UploadedFile":private]=>
      NULL
 }
 ...
 }
}


文件操作方法
moveTo() 將上傳的文件移動到新位置。
getSize() 獲取文件大小,單位 byte。
getError() 獲取上傳文件相關的錯誤信息,若無錯將必須返回 UPLOAD_ERR_OK 常量,若又錯誤將返回 UPLOAD_ERR_XXX 相關常量。
getClientFilename() 獲取文件上傳時客戶端本地的文件名,不要相信此方法返回的值。客戶端可能會發送惡意虛假文件名,意圖破壞或破解您的應用程序。
getClientMediaType() 獲取客戶端中文件的 MediaType 類型,不要相信此方法返回的值。客戶端可能會發送惡意虛假文件名,意圖破壞或破解您的應用程序。
其他常用輔助方法

if ($request->isAjax()) {
 // Do something
}
if ($request->isGet()) {
 // Do something
}
if ($request->isPost()) {
 // Do something
}


Http 響應對象
根據 PSR-7 對象的不可變性(immutable),所有的 with* 方法都是克隆對象然後返回,必須接收新對象來做進一步處理,或使用鏈式調用
例如:

return $response->withContentType(ContentType::HTML)->withContent('<html lang="en"><h1>Swoft framework</h1></html>');


獲取響應對象

$response=context()->getResponse()


設置響應狀態碼

return $response->withStatus(404)


示例: 輸出字符串內容響應

return $response->withContent("Hello Swoft2.0");


示例: 輸出數組內容響應

$data = ['name'=>'Swoft2.0'];

return $response->withData($data);


示例: 設置響應頭信息

return $response->withHeader("name","Swoft2.0");


示例: 重定向

// 302
return $response->redirect("http://www.swoft.org",302);

// 404 page
return $response->redirect('/404');


示例: 文件下載

return $response->file(\alias('@runtime/1.zip'), "application/octet-stream");


示例: 設置 Cookies

$response = $response->withCookie('name', 'value');

$response = $response->withCookie('name', [
 'value' => 'value3',
 'httpOnly' => true
]);
來源:https://8code.net/index/index/article/id/47

以上內容希望幫助到大家,更多PHP大廠PDF面試文檔,PHP進階架構視頻資料,PHP精彩好文免費獲取可以微信搜索關注公衆號:PHP開源社區,或者訪問:

2021金三銀四大廠面試真題集錦,必看!

四年精華PHP技術文章整理合集——PHP框架篇

四年精華PHP技術文合集——微服務架構篇

四年精華PHP技術文合集——分佈式架構篇

四年精華PHP技術文合集——高併發場景篇

四年精華PHP技術文章整理合集——數據庫篇

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章