คอนโทรลเลอร์
สร้างไฟล์คอนโทรลเลอร์ใหม่ app/controller/FooController.php
。
<?php
namespace app\controller;
use support\Request;
class FooController
{
public function index(Request $request)
{
return response('hello index');
}
public function hello(Request $request)
{
return response('hello webman');
}
}
เมื่อเข้าถึง http://127.0.0.1:8787/foo
หน้าจะตอบกลับด้วย hello index
。
เมื่อเข้าถึง http://127.0.0.1:8787/foo/hello
หน้าจะตอบกลับด้วย hello webman
。
แน่นอนว่าคุณสามารถเปลี่ยนแปลงกฎการ routing ผ่านการตั้งค่า routing ได้ โปรดอ้างอิงที่การ routing。
提示
หากเกิดข้อผิดพลาด 404 ไม่สามารถเข้าถึงได้ โปรดเปิดconfig/app.php
และตั้งค่าcontroller_suffix
เป็นController
จากนั้นรีสตาร์ท。
คอนโทรลเลอร์ ซัฟฟิกซ์
webman ตั้งแต่เวอร์ชัน 1.3 เป็นต้นไป รองรับการตั้งค่าซัฟฟิกซ์ของคอนโทรลเลอร์ใน config/app.php
ถ้าหาก controller_suffix
ใน config/app.php
ตั้งค่าเป็นค่าว่าง ''
คอนโทรลเลอร์จะมีรูปร่างดังต่อไปนี้
app\controller\Foo.php
。
<?php
namespace app\controller;
use support\Request;
class Foo
{
public function index(Request $request)
{
return response('hello index');
}
public function hello(Request $request)
{
return response('hello webman');
}
}
ขอแนะนำอย่างยิ่งให้ตั้งค่าซัฟฟิกซ์ของคอนโทรลเลอร์ให้เป็น Controller
เพื่อหลีกเลี่ยงความขัดแย้งระหว่างชื่อคอนโทรลเลอร์และโมเดล พร้อมกับเพิ่มความปลอดภัย。
คำอธิบาย
- เฟรมเวิร์กจะส่งวัตถุ
support\Request
ไปยังคอนโทรลเลอร์โดยอัตโนมัติ ซึ่งสามารถใช้เพื่อดึงข้อมูลที่ผู้ใช้ส่งมา (เช่น get post header cookie ฯลฯ) โปรดอ้างอิงที่การร้องขอ - คอนโทรลเลอร์สามารถคืนค่าหมายเลข สตริง หรือวัตถุ
support\Response
ได้ แต่ไม่สามารถคืนค่าเป็นชนิดข้อมูลอื่น ๆ ได้ - วัตถุ
support\Response
สามารถสร้างได้โดยใช้ฟังก์ชันช่วยเช่นresponse()
json()
xml()
jsonp()
redirect()
เป็นต้น
การจับคู่พารามิเตอร์ของคอนโทรลเลอร์
ตัวอย่าง
webman สนับสนุนการจับคู่พารามิเตอร์ request โดยอัตโนมัติผ่านพารามิเตอร์ของฟังก์ชันของคอนโทรลเลอร์ เช่น
<?php
namespace app\controller;
use support\Response;
class UserController
{
public function create(string $name, int $age): Response
{
return json(['name' => $name, 'age' => $age]);
}
}
คุณสามารถส่งค่าของ name
และ age
ผ่านวิธี GET
หรือ POST
หรือผ่านพารามิเตอร์ routing เช่น
Route::any('/user/{name}/{age}', [app\controller\UserController::class, 'create']);
ลำดับความสำคัญคือ พารามิเตอร์ routing
> GET
> พารามิเตอร์ POST
ค่าตั้งต้น
สมมุติว่าเราถึง /user/create?name=tom
เราจะได้รับข้อผิดพลาดดังนี้
Missing input parameter age
สาเหตุเพราะเราไม่ได้ส่งพารามิเตอร์ age
สามารถแก้ปัญหานี้ได้โดยการตั้งค่าตัวแปรพารามิเตอร์ที่มีค่าเริ่มต้น เช่น
<?php
namespace app\controller;
use support\Response;
class UserController
{
public function create(string $name, int $age = 18): Response
{
return json(['name' => $name, 'age' => $age]);
}
}
ประเภทของพารามิเตอร์
เมื่อเข้าถึง /user/create?name=tom&age=not_int
เราจะได้รับข้อผิดพลาดดังนี้
提示
ที่นี่เพื่อความสะดวกในการทดสอบ เราจะป้อนพารามิเตอร์ในแถบที่อยู่ของเบราว์เซอร์โดยตรง ในการพัฒนาจริงควรส่งพารามิเตอร์ผ่านวิธีPOST
Input age must be of type int, string given
เนื่องจากข้อมูลที่รับจะถูกแปลงตามประเภท หากไม่สามารถแปลงได้จะเกิด support\exception\InputTypeException
ขึ้น เนื่องจากพารามิเตอร์ age
ที่ส่งเข้าไม่สามารถแปลงเป็นประเภท int
ได้ จึงได้รับข้อผิดพลาดดังกล่าว。
ข้อผิดพลาดที่กำหนดเอง
เราสามารถใช้การแปลหลายภาษาเพื่อตั้งค่าข้อผิดพลาด Missing input parameter age
และ Input age must be of type int, string given
ได้ ดูคำสั่งด้านล่าง
composer require symfony/translation
mkdir resource/translations/zh_CN/ -p
echo "<?php
return [
'Input :parameter must be of type :exceptType, :actualType given' => '输入参数 :parameter 必须是 :exceptType 类型,传递的类型是 :actualType',
'Missing input parameter :parameter' => '缺少输入参数 :parameter',
];" > resource/translations/zh_CN/messages.php
php start.php restart
ประเภทอื่น ๆ
พารามิเตอร์ประเภทต่าง ๆ ที่รองรับโดย webman มี int
float
string
bool
array
object
class instance
เป็นต้น เช่น
<?php
namespace app\controller;
use support\Response;
class UserController
{
public function create(string $name, int $age, float $balance, bool $vip, array $extension): Response
{
return json([
'name' => $name,
'age' => $age,
'balance' => $balance,
'vip' => $vip,
'extension' => $extension,
]);
}
}
เมื่อเข้าถึง /user/create?name=tom&age=18&balance=100.5&vip=true&extension[foo]=bar
เราจะได้รับผลลัพธ์ดังนี้
{
"name": "tom",
"age": 18,
"balance": 100.5,
"vip": true,
"extension": {
"foo": "bar"
}
}
อินสแตนซ์คลาส
webman รองรับการส่งผ่านอินสแตนซ์คลาสผ่านการชี้พารามิเตอร์ประเภท เช่น
app\service\Blog.php
<?php
namespace app\service;
class Blog
{
private $title;
private $content;
public function __construct(string $title, string $content)
{
$this->title = $title;
$this->content = $content;
}
public function get()
{
return [
'title' => $this->title,
'content' => $this->content,
];
}
}
app\controller\BlogController.php
<?php
namespace app\controller;
use app\service\Blog;
use support\Response;
class BlogController
{
public function create(Blog $blog): Response
{
return json($blog->get());
}
}
เมื่อเข้าถึง /blog/create?blog[title]=hello&blog[content]=world
เราจะได้รับผลลัพธ์ดังนี้
{
"title": "hello",
"content": "world"
}
อินสแตนซ์โมเดล
app\model\User.php
<?php
namespace app\model;
use support\Model;
class User extends Model
{
protected $connection = 'mysql';
protected $table = 'user';
protected $primaryKey = 'id';
public $timestamps = false;
// ตรงนี้ต้องเพิ่มฟิลด์ที่สามารถกรอกได้เพื่อป้องกันฟิลด์ที่ไม่ปลอดภัยจากฟรอนต์เอนด์
protected $fillable = ['name', 'age'];
}
app\controller\UserController.php
<?php
namespace app\controller;
use app\model\User;
class UserController
{
public function create(User $user): int
{
$user->save();
return $user->id;
}
}
เมื่อเข้าถึง /user/create?user[name]=tom&user[age]=18
เราจะได้รับผลลัพธ์ที่คล้ายคลึงกันนี้
1
วงจรชีวิตของคอนโทรลเลอร์
เมื่อ controller_reuse
ใน config/app.php
เป็น false
คอนโทรลเลอร์ที่เกี่ยวข้องจะมีการสร้างขึ้นใหม่ในแต่ละคำขอ และจะถูกทำลายเมื่อคำขอสิ้นสุดลง ซึ่งเหมือนกับกลไกการทำงานของเฟรมเวิร์กทั่วไป
เมื่อ controller_reuse
ใน config/app.php
เป็น true
คอนโทรลเลอร์ทั้งหมดจะถูกใช้ซ้ำ ซึ่งคือตัวอย่างคอนโทรลเลอร์จะถูกสร้างขึ้นและอยู่ในหน่วยความจำ คำขอทั้งหมดจะใช้ซ้ำอินสแตนซ์นี้
注意
เมื่อเปิดใช้งานการใช้ซ้ำคอนโทรลเลอร์ คำขอไม่ควรเปลี่ยนแปลงคุณสมบัติใด ๆ ของคอนโทรลเลอร์ เนื่องจากการเปลี่ยนแปลงเหล่านี้จะส่งผลกระทบต่อคำขอถัดไป เช่น
<?php
namespace app\controller;
use support\Request;
class FooController
{
protected $model;
public function update(Request $request, $id)
{
$model = $this->getModel($id);
$model->update();
return response('ok');
}
public function delete(Request $request, $id)
{
$model = $this->getModel($id);
$model->delete();
return response('ok');
}
protected function getModel($id)
{
// วิธีนี้จะเก็บ model ไว้หลังจากคำขอครั้งแรก update?id=1
// หากคำขอ delete?id=2 จะลบข้อมูลของ 1
if (!$this->model) {
$this->model = Model::find($id);
}
return $this->model;
}
}
提示
การคืนค่าข้อมูลในคอนโทรลเลอร์__construct()
จะไม่มีผลใด ๆ เช่น
<?php
namespace app\controller;
use support\Request;
class FooController
{
public function __construct()
{
// การคืนค่าข้อมูลในฟังก์ชันสร้างไม่มีผลใด ๆ เบราว์เซอร์จะไม่ได้รับการตอบสนองนี้
return response('hello');
}
}
ความแตกต่างระหว่างการไม่ใช้งานและการใช้งานซ้ำคอนโทรลเลอร์
ความแตกต่างมีดังนี้
ไม่ใช้งานซ้ำคอนโทรลเลอร์
แต่ละคำขอจะสร้างอินสแตนซ์คอนโทรลเลอร์ใหม่ และเมื่อคำขอสิ้นสุดก็จะปล่อยอินสแตนซ์นั้นและคืนพื้นที่หน่วยความจำ การไม่ใช้ซ้ำนั้นเหมือนกับเฟรมเวิร์กทั่วไป ซึ่งเป็นแนวทางที่สอดคล้องกับนักพัฒนาส่วนใหญ่ เนื่องจากการสร้างและทำลายคอนโทรลเลอร์ซ้ำ ๆ ดังนั้นประสิทธิภาพจะด้อยกว่าการใช้ซ้ำเล็กน้อย (การทดสอบประสิทธิภาพ helloworld มีความแตกต่างประมาณ 10% ส่วนในงานที่มีการใช้งานจริงสามารถละเลยได้)
ใช้งานซ้ำคอนโทรลเลอร์
ในกรณีของการใช้ซ้ำ กระบวนการจะสร้างคอนโทรลเลอร์เพียงครั้งเดียว คำขอจะไม่ทำลายอินสแตนซ์นี้ในครั้งที่สิ้นสุด คำขอถัดไปในกระบวนการปัจจุบันจะใช้ซ้ำอินสแตนซ์นี้ ใช้งานซ้ำคอนโทรลเลอร์มีประสิทธิภาพดีกว่า แต่ไม่สอดคล้องกับแนวทางของนักพัฒนาส่วนใหญ่
กรณีต่อไปนี้ไม่สามารถใช้ซํ้าได้
เมื่อคำขอเปลี่ยนแปลงคุณสมบัติของคอนโทรลเลอร์ จะไม่สามารถเปิดใช้งานการใช้งานซ้ำ เนื่องจากการเปลี่ยนแปลงดังกล่าวจะส่งผลกระทบต่อคำขอถัดไป
นักพัฒนาบางคนชอบทำสิ่งต่าง ๆ ในฟังก์ชันสร้าง __construct()
เพื่อเริ่มต้นสำหรับแต่ละคำขอ ในกรณีนี้ไม่สามารถใช้ซ้ำคอนโทรลเลอร์ได้ เนื่องจากฟังก์ชันสร้างจะถูกเรียกเพียงครั้งเดียวในกระบวนการปัจจุบันและจะไม่ถูกเรียกสำหรับแต่ละคำขอ。