컨트롤러
새 컨트롤러 파일 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을 반환합니다.
물론 라우트 구성을 통해 라우트 규칙을 변경할 수 있습니다. 라우트를 참조하세요.
팁
404 오류가 발생하면config/app.php를 열어controller_suffix를Controller로 설정하고 다시 시작하세요.
컨트롤러 접미사
webman 1.3부터 config/app.php에서 컨트롤러 접미사를 설정할 수 있습니다. config/app.php에서 controller_suffix가 빈 문자열 ''로 설정되어 있다면, 컨트롤러는 다음과 같이 작성됩니다.
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은 컨트롤러 메서드 매개변수에 요청 매개변수를 자동으로 바인딩합니다. 예를 들어:
<?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로 전달할 수 있으며, 라우트 매개변수로도 전달할 수 있습니다. 예:
Route::any('/user/{name}/{age}', [app\controller\UserController::class, 'create']);
우선순위는 라우트 매개변수 > 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, 클래스 인스턴스 등입니다. 예:
<?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
컨트롤러 라이프사이클
config/app.php에서 controller_reuse가 false로 설정되어 있을 때, 각 요청마다 해당 컨트롤러 인스턴스가 한 번 초기화되고, 요청 종료 후 컨트롤러 인스턴스가 파괴됩니다. 이것은 전통적인 프레임워크의 작동 방식과 동일합니다.
config/app.php에서 controller_reuse가 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)
{
// 이 메서드는 첫 번째 요청 update?id=1 후에 model을 유지합니다
// delete?id=2를 요청하면 id=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()에서 각 요청에 대한 초기화를 수행하는 것을 선호합니다. 이 경우 컨트롤러 재사용을 사용할 수 없습니다. 현재 프로세스에서 생성자는 한 번만 호출되며 각 요청마다 호출되지 않기 때문입니다.