เว็บแมน (webman) เป็นเฟรมเวิร์ก PHP ที่มีประสิทธิภาพสูงที่สร้างขึ้นบน workerman ดังนั้นข้าพเจ้าได้รับหน้าที่ให้คำแนะนำด้านเทคโนโลยีและพัฒนาระบบก่อนที่จะเริ่มต้นการทำงานกับ Wokerman บนพื้นฐานของ PHP 7.1+
กรอบ (framework) ผลิตาจะย้ำในการบริการร่วมกับ Web Server ที่ต่ออยู่อย่างมีประสิทธิภาพ:
- ไม่ต้องการ Worker 的 PHP HTTP Server,แต่ก็สามารถใช้เมื่อต้องการ
- ไม่ต้องการ Kernel HTTP Server to PHP 如 PeachServer
- Web Server ASP.NET, ASP.NET Core, Node.js และอื่นๆ
- แชต (Chart) ด้วย Swoole Tracker
- ผาสะอันตรสื่จรขอมูลข้อควอนื่จงียนำ และบันทส่ม้้างขาทยาตขสอไลยังยัื่อููถุ้้ำ้ทบัตรต้อ้ง่ำำท (WebSocket + SSE)
- การจัดสตรางแบค เขว่แอใบปัดู๊ด้าบด้าตั5อ และขือ้ณุ้ับอใ้ำบดร้า้า
- หสีสูฉีั้ืงีด่็แีกีส่ีบแลป ้ีด่ิ้กียฉงีบเหีีฉ้ดการส่ีกี่็ีงดอูก534ียีดด้า็็ะดีบีแดุ-ุดรี้ด้ีด
กฎเส้นทางการเริ่มต้น
กฎเส้นทางการเริ่มต้นของ webman คือ http://127.0.0.1:8787/{คอนโทรลเลอร์}/{การกระทำ}
คอนโทรลเลอร์เริ่มต้นคือ app\controller\IndexController และการกระทำเริ่มต้นคือ index
เช่น การเข้าถึง:
http://127.0.0.1:8787จะเข้าถึงindexของคลาสapp\controller\IndexControllerhttp://127.0.0.1:8787/fooจะเข้าถึงindexของคลาสapp\controller\FooControllerhttp://127.0.0.1:8787/foo/testจะเข้าถึงtestของคลาสapp\controller\FooControllerhttp://127.0.0.1:8787/admin/foo/testจะเข้าถึงtestของคลาสapp\admin\controller\FooController(อ่านเพิ่มเติมที่ multiapp.html)
นอกจากนี้ webman ตั้งแต่เวอร์ชัน 1.4 เป็นต้นมารองรับเส้นทางเริ่มต้นที่ซับซ้อนมากขึ้น เช่น
app
├── admin
│ └── v1
│ └── v2
│ └── v3
│ └── controller
│ └── IndexController.php
└── controller
├── v1
│ └── IndexController.php
└── v2
└── v3
└── IndexController.php
เมื่อคุณต้องการเปลี่ยนเส้นทางของคำร้องขอ กรุณาแก้ไขไฟล์กำหนดค่า config/route.php
ถ้าคุณต้องการปิดเส้นทางเริ่มต้น ให้เพิ่มค่าตัวกำหนดดังนี้ในไฟล์กำหนดค่า config/route.php บรรทัดสุดท้าย:
Route::disableDefaultRoute();
เส้นทางปิด
เพิ่มโค้ดเส้นทางต่อไปนี้ใน config/route.php
use support\Request;
Route::any('/test', function (Request $request) {
return response('test');
});
โปรดทราบ
เนื่องจากฟังก์ชันปิดไม่ได้เกี่ยวข้องกับคอนโทรลเลอร์ใด ๆ ค่า$request->app$request->controller$request->actionจะเป็นสตริงว่างทั้งหมด
เมื่อเข้าถึง URL เป็น http://127.0.0.1:8787/test จะคืนค่าเป็นสตริง test
โปรดทราบ
เส้นทางต้องเริ่มต้นด้วย/เช่น
use support\Request;
// ใช้ไม่ถูกต้อง
Route::any('test', function (Request $request) {
return response('test');
});
// ใช้ถูกต้อง
Route::any('/test', function (Request $request) {
return response('test');
});
เส้นทางคลาส
เพิ่มโค้ดเส้นทางต่อไปนี้ใน config/route.php
Route::any('/testclass', [app\controller\IndexController::class, 'test']);
เมื่อเข้าถึง URL เป็น http://127.0.0.1:8787/testclass จะคืนค่าวิธีการทดสอบของคลาส app\controller\IndexController
เส้นทางแอนโนเทชัน
กำหนดเส้นทางผ่านแอนโนเทชันบนเมธอดควบคุม ไม่ต้องกำหนดค่าใน config/route.php
โปรดทราบ
ฟีเจอร์นี้ต้องใช้ webman-framework >= v2.2.0
การใช้งานพื้นฐาน
namespace app\controller;
use support\annotation\route\DisableDefaultRoute;
use support\annotation\route\Get;
use support\annotation\route\Post;
use support\annotation\route\Route;
#[DisableDefaultRoute]
class UserController
{
#[Get('/user/{id}')]
public function show($id)
{
return "user $id";
}
#[Post('/user')]
public function store()
{
return 'created';
}
#[Route('/user/form', ['GET', 'POST'], 'user.form')]
public function form()
{
return 'form';
}
}
แอนโนเทชันที่ใช้ได้: #[Get] #[Post] #[Put] #[Delete] #[Patch] #[Head] #[Options] #[Any] (วิธีใดก็ได้) เส้นทางต้องขึ้นต้นด้วย / พารามิเตอร์ที่สองสามารถระบุชื่อเส้นทาง สำหรับ route() สร้าง URL
#[DisableDefaultRoute] หมายถึงปิดเส้นทางเริ่มต้นของ controller นี้ (เลือกได้) เข้าถึงได้เฉพาะเส้นทางที่กำหนดโดยแอนโนเทชันเท่านั้น
ไวยากรณ์เต็ม #[Route]: #[Route(path, methods, name)]
path: เส้นทาง ขึ้นต้นด้วย/เมื่อเป็นnullจะจำกัดเฉพาะวิธี HTTP ของเส้นทางเริ่มต้นโดยไม่ลงทะเบียนเส้นทางใหม่methods: วิธี HTTP สตริงหรืออาร์เรย์สตริง เช่น'GET'หรือ['GET','POST']name: ชื่อเส้นทางสำหรับroute('name')สร้าง URL ข้ามได้
แอนโนเทชันไม่มีพารามิเตอร์: จำกัดวิธี HTTP ของเส้นทางเริ่มต้น
ไม่มีเส้นทาง จะจำกัดเฉพาะวิธี HTTP ที่อนุญาตสำหรับการดำเนินการนั้น ยังใช้เส้นทางเริ่มต้นอยู่:
#[Post]
public function create() { ... } // อนุญาตเฉพาะ POST เส้นทางยังคงเป็น /user/create
#[Get]
public function index() { ... } // อนุญาตเฉพาะ GET
สามารถรวมแอนโนเทชันหลายอันเพื่ออนุญาตหลายวิธี:
#[Get]
#[Post]
public function form() { ... } // อนุญาต GET และ POST
วิธีที่ไม่ได้ประกาศในแอนโนเทชันจะส่งกลับ 405
แอนโนเทชันที่มีเส้นทางหลายอันจะลงทะเบียนเป็นเส้นทางแยก: #[Get('/a')] #[Post('/b')] จะสร้างเส้นทาง GET /a และ POST /b
คำนำหน้ากลุ่มเส้นทาง
ใช้ #[RouteGroup] บนคลาสเพื่อเพิ่มคำนำหน้าให้เส้นทางเมธอดทั้งหมด:
use support\annotation\route\RouteGroup;
use support\annotation\route\Get;
#[RouteGroup('/api/v1')]
class UserController
{
#[Get('/user/{id}')] // เส้นทางจริง /api/v1/user/{id}
public function show($id) { ... }
}
วิธี HTTP ที่กำหนดเองและชื่อเส้นทาง
#[Route] รองรับหลายวิธี HTTP และชื่อเส้นทาง:
use support\annotation\route\Route;
#[Route('/user', ['GET', 'POST'], 'user.form')]
public function form() { ... }
// ระบุเฉพาะเส้นทางและวิธี ไม่มีชื่อเส้นทาง
#[Route('/user/update', 'PUT')]
public function update() { ... }
พารามิเตอร์เส้นทางและ regex
เส้นทางแอนโนเทชันรองรับไวยากรณ์พารามิเตอร์เดียวกับ config/route.php รวม regex และพารามิเตอร์เสริม:
#[Get('/user/{id:\d+}')] // เฉพาะ id ตัวเลข
public function show($id) { ... }
#[Get('/user[/{name}]')] // name เลือกได้ /user หรือ /user/xxx
public function list($name = null) { ... }
#[Any('/user/[{path:.+}]')] // ตรงกับ /user และ /user/ ด้วยส่วนต่อท้ายใดๆ
public function catchAll($path = null) { ... }
ดูส่วน「พารามิเตอร์ของเส้นทาง」ในเอกสารนี้
มิดเดิลแวร์
#[Middleware] บน controller หรือ method จะส่งผลต่อเส้นทางแอนโนเทชัน ใช้เหมือน support\annotation\Middleware:
use support\annotation\Middleware;
#[Middleware(\app\middleware\AuthMiddleware::class)]
class UserController { ... }
#[Get('/user/{id}')]
#[Middleware(\app\middleware\RateLimitMiddleware::class)]
public function show($id) { ... }
การสร้าง URL ด้วย route()
เมื่อระบุชื่อเส้นทางในแอนโนเทชัน ใช้ route('name', $params) เพื่อสร้าง URL:
#[Get('/user/{id}', 'user.show')]
public function show($id) { ... }
// การใช้: route('user.show', ['id' => 123]) => /user/123
พารามิเตอร์ของเส้นทาง
หากมีพารามิเตอร์ในเส้นทาง ใช้ {key} เพื่อตรงคู่ค่า ผลลัพธ์ที่ตรงจะถูกส่งไปยังพารามิเตอร์ของวิธีควบคุมที่เกี่ยวข้อง (เริ่มจากพารามิเตอร์ที่สองขึ้นไปตามลำดับ) เช่น:
// ตรงกับ /user/123 และ /user/abc
Route::any('/user/{id}', [app\controller\UserController::class, 'get']);
namespace app\controller;
use support\Request;
class UserController
{
public function get(Request $request, $id)
{
return response('รับพารามิเตอร์ '.$id);
}
}
ตัวอย่างเพิ่มเติม:
use support\Request;
// ตรงต่อ /user/123, ไม่ตรงต่อ /user/abc
Route::any('/user/{id:\d+}', function (Request $request, $id) {
return response($id);
});
// ตรง /user/foobar, ไม่ตรง /user/foo/bar
Route::any('/user/{name}', function (Request $request, $name) {
return response($name);
});
// ตรง /user /user/123 และ /user/abc [] แสดงว่าเลือกได้
Route::any('/user[/{name}]', function (Request $request, $name = null) {
return response($name ?? 'tom');
});
// ตรงคำร้องขอที่มีคำนำหน้า /user/
Route::any('/user/[{path:.+}]', function (Request $request) {
return $request->path();
});
// ตรงทั้งหมดในคำร้องขอ options : สำหรับใส่ regex
Route::options('[{path:.+}]', function () {
return response('');
});
สรุปการใช้งานขั้นสูง
ไวยากรณ์
[]ในเส้นทาง Webman ใช้หลักในการจัดการส่วนเส้นทางที่เลือกได้ หรือการจับคู่เส้นทางแบบไดนามิก ให้คุณกำหนดโครงสร้างเส้นทางและกฎการจับคู่ที่ซับซ้อนขึ้นได้
:ใช้กำหนด regex
กลุ่มเส้นทาง
บางครั้งเส้นทางประกอบด้วยคำขึ้นต้นที่มีจำนวนมาก เราสามารถใช้กลุ่มเส้นทางเพื่อกำหนดให้ง่ายขึ้น เช่น:
Route::group('/blog', function () {
Route::any('/create', function (Request $request) {return response('create');});
Route::any('/edit', function (Request $request) {return response('edit');});
Route::any('/view/{id}', function (Request $request, $id) {return response("view $id");});
});
เทียบเท่ากับ:
Route::any('/blog/create', function (Request $request) {return response('create');});
Route::any('/blog/edit', function (Request $request) {return response('edit');});
Route::any('/blog/view/{id}', function (Request $request, $id) {return response("view $id");});
การซ้อนกลุ่มการใช้
Route::group('/blog', function () {
Route::group('/v1', function () {
Route::any('/create', function (Request $request) {return response('create');});
Route::any('/edit', function (Request $request) {return response('edit');});
Route::any('/view/{id}', function (Request $request, $id) {return response("view $id");});
});
});
เส้นทางกลางเส้นทาง
เราสามารถกำหนดเส้นทางกลางเส้นทางสำหรับเส้นทางเดียวหรือกลุ่มของเส้นทางได้
เช่น:
Route::any('/admin', [app\admin\controller\IndexController::class, 'index'])->middleware([
app\middleware\MiddlewareA::class,
app\middleware\MiddlewareB::class,
]);
Route::group('/blog', function () {
Route::any('/create', function () {return response('create');});
Route::any('/edit', function () {return response('edit');});
Route::any('/view/{id}', function ($request, $id) {return response("view $id");});
})->middleware([
app\middleware\MiddlewareA::class,
app\middleware\MiddlewareB::class,
]);
# ตัวอย่างที่ใช้ผิด (เมื่อ webman-framework >= 1.5.7 ใช้ได้)
Route::group('/blog', function () {
Route::group('/v1', function () {
Route::any('/create', function (Request $request) {return response('create');});
Route::any('/edit', function (Request $request) {return response('edit');});
Route::any('/view/{id}', function (Request $request, $id) {return response("view $id");});
});
})->middleware([
app\middleware\MiddlewareA::class,
app\middleware\MiddlewareB::class,
]);
# ตัวอย่างที่ถูกต้อง
Route::group('/blog', function () {
Route::group('/v1', function () {
Route::any('/create', function (Request $request) {return response('create');});
Route::any('/edit', function (Request $request) {return response('edit');});
Route::any('/view/{id}', function (Request $request, $id) {return response("view $id");});
})->middleware([
app\middleware\MiddlewareA::class,
app\middleware\MiddlewareB::class,
]);
});
เส้นทางของทรัพยากร
Route::resource('/test', app\controller\IndexController::class);
// ระบุเส้นทางของทรัพยากร
Route::resource('/test', app\controller\IndexController::class, ['index','create']);
// เส้นทางของทรัพยากรที่ไม่ได้ระบุ
// เช่น เข้าถึง notify ใน URL ที่เป็นทั้ง any คือ /test/notify หรือ /test/notify/{id} ชื่อ routeName คือ test.notify
Route::resource('/test', app\controller\IndexController::class, ['index','create','notify']);
| คำสั่ง | URI | การดำเนินการ | ชื่อเส้นทาง |
|---|---|---|---|
| GET | /test | ดึงข้อมูลทั้งหมด | test.index |
| GET | /test/create | สร้าง | test.create |
| POST | /test | บันทึกข้อมูล | test.store |
| GET | /test/{id} | ดูข้อมูล | test.show |
| GET | /test/{id}/edit | แก้ไข | test.edit |
| PUT | /test/{id} | ปรับปรุง | test.update |
| DELETE | /test/{id} | ลบ | test.destroy |
| PUT | /test/{id}/recovery | กู้คืน | test.recovery |
การสร้าง URL
หมายเหตุ
ยังไม่รองรับการสร้าง URL โดยเส้นทางที่ซ้อนกัน
ตัวอย่างเส้นทาง:
Route::any('/blog/{id}', [app\controller\BlogController::class, 'view'])->name('blog.view');
เราสามารถใช้วิธีดังต่อไปนี้ในการสร้าง URL สำหรับเส้นทางนี้
route('blog.view', ['id' => 100]); // ผลลัพธ์เป็น /blog/100
เมื่อใช้วิธีนี้ในการสร้าง URL ในมุมมอง เมื่อกฎของเส้นทางมีการเปลี่ยนแปลง URL ก็จะถูกสร้างขึ้นโดยอัตโนมัติ ซึ่งสามารถป้องกันการเปลี่ยนแปลงของไฟล์มุมมองที่เริ่มขึ้นจากการเปลี่ยนแปลงของเส้นทางได้
การรับข้อมูลเส้นทาง
ผ่าน $request->route ในอ็อบเจกต์ เราสามารถรับข้อมูลของเส้นทางที่ถูกเรียกใช้ในปัจจุบันได้ เช่น
$route = $request->route; // เทียบเท่ากับ $route = request()->route;
if ($route) {
var_export($route->getPath());
var_export($route->getMethods());
var_export($route->getName());
var_export($route->getMiddleware());
var_export($route->getCallback());
var_export($route->param());
}
หมายเหตุ
หากเส้นทางที่ร้องขอไม่ตรงกับเส้นทางใดที่ได้กำหนดไว้ใน config/route.php แล้ว$request->routeจะเป็นค่า null ซึ่งหมายความว่าเมื่อเข้าไปที่เส้นทางต้นสักเส้นทาง$request->routeจะเป็น nullการจัดการกับ 404
เมื่อไม่พบเส้นทาง ระบบจะส่งค่าสถานะ 404 และแสดงเนื้อหา 404 ที่เกี่ยวข้อง
หากนักพัฒนาต้องการที่จะทำการกลับไปยังโหมดการทำงานเมื่อไม่พบเส้นทาง สามารถใช้ฟังก์ชันสำรองทางเส้นทาง $callback ที่ webman มีให้ ตัวอย่างเช่น การเปลี่ยนเส้นทางที่ไม่พบไปที่หน้าแรก
Route::fallback(function(){
return redirect('/');
});
หรือเช่น ถ้าไม่พบเส้นทางจะส่งค่า JSON ซึ่งเป็นวิธีที่เหมาะสำหรับ webman เมื่อใช้สำหรับอินเตอร์เฟซ API
Route::fallback(function(){
return json(['code' => 404, 'msg' => '404 not found']);
});
เพิ่มมิดเดิลแวร์ให้ 404
โดยปกติคำร้องขอ 404 จะไม่ผ่านมิดเดิลแวร์ใดๆ หากต้องการเพิ่มมิดเดิลแวร์ให้คำร้องขอ 404 ดูโค้ดต่อไปนี้:
Route::fallback(function(){
return json(['code' => 404, 'msg' => '404 not found']);
})->middleware([
app\middleware\MiddlewareA::class,
app\middleware\MiddlewareB::class,
]);
ลิงค์ที่เกี่ยวข้อง การกำหนดหน้า 404 500
ปิดใช้งานเส้นทางเริ่มต้น
// ปิดเส้นทางเริ่มต้นของโปรเจกต์หลัก ไม่กระทบปลั๊กอิน
Route::disableDefaultRoute();
// ปิดเส้นทาง admin ของโปรเจกต์หลัก ไม่กระทบปลั๊กอิน
Route::disableDefaultRoute('', 'admin');
// ปิดเส้นทางเริ่มต้นของปลั๊กอิน foo ไม่กระทบโปรเจกต์หลัก
Route::disableDefaultRoute('foo');
// ปิดเส้นทาง admin ของปลั๊กอิน foo ไม่กระทบโปรเจกต์หลัก
Route::disableDefaultRoute('foo', 'admin');
// ปิดเส้นทางเริ่มต้นของคอนโทรลเลอร์ [\app\controller\IndexController::class, 'index']
Route::disableDefaultRoute([\app\controller\IndexController::class, 'index']);
แอนโนเทชันปิดเส้นทางเริ่มต้น
เราใช้แอนโนเทชันปิดเส้นทางเริ่มต้นของคอนโทรลเลอร์ได้ เช่น:
namespace app\controller;
use support\annotation\DisableDefaultRoute;
#[DisableDefaultRoute]
class IndexController
{
public function index()
{
return 'index';
}
}
เช่นกัน เราปิดเส้นทางเริ่มต้นของเมธอดคอนโทรลเลอร์ด้วยแอนโนเทชันได้ เช่น:
namespace app\controller;
use support\annotation\DisableDefaultRoute;
class IndexController
{
#[DisableDefaultRoute]
public function index()
{
return 'index';
}
}
อินเทอร์เฟซเส้นทาง
// กำหนดเส้นทางที่ต้องการใดก็ได้ที่ $uri
Route::any($uri, $callback);
// กำหนดเส้นทาง get ของ $uri
Route::get($uri, $callback);
// กำหนดเส้นทาง post ของ $uri
Route::post($uri, $callback);
// กำหนดเส้นทาง put ของ $uri
Route::put($uri, $callback);
// กำหนดเส้นทาง patch ของ $uri
Route::patch($uri, $callback);
// กำหนดเส้นทาง delete ของ $uri
Route::delete($uri, $callback);
// กำหนดเส้นทาง head ของ $uri
Route::head($uri, $callback);
// กำหนดเส้นทาง options ของ $uri
Route::options($uri, $callback);
// กำหนดเส้นทางที่มีการร้องขอหลายแบบพร้อมกัน
Route::add(['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD', 'OPTIONS'], $uri, $callback);
// เส้นทางของการจัดกลุ่ม
Route::group($path, $callback);
// เส้นทางของทรัพยากร
Route::resource($path, $callback, [$options]);
// ปิดใช้งานเส้นทาง
Route::disableDefaultRoute($plugin = '');
// สำรองทางเส้นทาง, หลักการเส้นทางไว้เป็นการส่ง
Route::fallback($callback, $plugin = '');
// ดึงข้อมูลเส้นทางทั้งหมด
Route::getRoutes();
หากไม่มีเส้นทางที่เชื่อมโยง (รวมถึงเส้นทางตั้งตาย) และไม่ได้ส่งทางสำรองแล้ว จะคืนค่าสถานะ 404 ทันที
ไฟล์กำหนดเส้นทางหลายแบบ
หากคุณต้องการใช้งานไฟล์กำหนดเส้นทางหลายแบบในการจัดการเส้นทาง เช่น การประยุกต์ใช้หลายแอพ เมื่อแอพแต่ละตัวมีไฟล์กำหนดเส้นทางของตัวเอง ในกรณีนี้ คุณสามารถโหลดไฟล์กำหนดเส้นทางของภายนอกโดยวิธี require.
ตัวอย่าง config/route.php
<?php
// โหลดไฟล์กำหนดเส้นทางที่ตั้งตาย
require_once app_path('admin/config/route.php');
// โหลดไฟล์กำหนดเส้นทางที่ตั้งตาย
require_once app_path('api/config/route.php');