Controller
Crea un nuovo file di controller 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');
}
}
Quando accedi a http://127.0.0.1:8787/foo
, la pagina restituisce hello index
.
Quando accedi a http://127.0.0.1:8787/foo/hello
, la pagina restituisce hello webman
.
Certo, puoi modificare le regole di routing tramite la configurazione delle rotte, vedi Routing.
Suggerimento
Se appare un errore 404 e non puoi accedere, apriconfig/app.php
, impostacontroller_suffix
suController
, e riavvia.
Suffisso del Controller
A partire dalla versione 1.3, Webman supporta la configurazione del suffisso del controller in config/app.php
. Se controller_suffix
è impostato a vuoto ''
, allora il controller sarà simile a questo
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');
}
}
Si consiglia vivamente di impostare il suffisso del controller su Controller
, in questo modo si evita conflitti tra il nome del controller e il nome della classe modello, aumentando al contempo la sicurezza.
Note
- Il framework passerà automaticamente un oggetto
support\Request
al controller, attraverso il quale è possibile ottenere i dati di input dell'utente (dati get, post, intestazioni, cookie, ecc.), vedi Richiesta - Il controller può restituire numeri, stringhe o oggetti
support\Response
, ma non altri tipi di dati. - Gli oggetti
support\Response
possono essere creati tramite le funzioni helperresponse()
,json()
,xml()
,jsonp()
,redirect()
, ecc.
Binding dei Parametri del Controller
Esempio
Webman supporta il binding automatico dei parametri della richiesta ai parametri del metodo del controller. Ad esempio:
<?php
namespace app\controller;
use support\Response;
class UserController
{
public function create(string $name, int $age): Response
{
return json(['name' => $name, 'age' => $age]);
}
}
Puoi passare i valori di name
e age
tramite il metodo GET
o POST
, oppure puoi passare i parametri name
e age
tramite i parametri della rotta, ad esempio:
Route::any('/user/{name}/{age}', [app\controller\UserController::class, 'create']);
La priorità è: parametri della rotta
> GET
> parametri POST
Valori Predefiniti
Supponiamo di accedere a /user/create?name=tom
, riceveremo il seguente errore:
Missing input parameter age
Il motivo è che non abbiamo passato il parametro age
, possiamo risolvere il problema impostando un valore predefinito per il parametro, ad esempio:
<?php
namespace app\controller;
use support\Response;
class UserController
{
public function create(string $name, int $age = 18): Response
{
return json(['name' => $name, 'age' => $age]);
}
}
Tipo di Parametri
Quando accediamo a /user/create?name=tom&age=not_int
, riceveremo il seguente errore:
Suggerimento
Qui per facilitare i test, abbiamo direttamente inserito i parametri nella barra degli indirizzi del browser; in sviluppo reale, i parametri dovrebbero essere passati tramite il metodoPOST
.
Input age must be of type int, string given
Questo errore è dovuto al fatto che i dati ricevuti vengono convertiti in base al tipo, se non possono essere convertiti viene sollevata l'eccezione support\exception\InputTypeException
, poiché il parametro age
passato non può essere convertito in tipo int
, quindi si ottiene l'errore sopra.
Errori Personalizzati
Possiamo utilizzare il supporto multilingue per personalizzare errori come Missing input parameter age
e Input age must be of type int, string given
, fare riferimento al seguente comando:
composer require symfony/translation
mkdir resource/translations/zh_CN/ -p
echo "<?php
return [
'Input :parameter must be of type :exceptType, :actualType given' => 'Input parameter :parameter must be of type :exceptType, :actualType given',
'Missing input parameter :parameter' => 'Missing input parameter :parameter',
];" > resource/translations/zh_CN/messages.php
php start.php restart
Altri Tipi
I tipi di parametri supportati da webman includono int
, float
, string
, bool
, array
, object
, istanza di classe
, ecc., ad esempio:
<?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,
]);
}
}
Quando accediamo a /user/create?name=tom&age=18&balance=100.5&vip=true&extension[foo]=bar
, riceveremo il seguente risultato:
{
"name": "tom",
"age": 18,
"balance": 100.5,
"vip": true,
"extension": {
"foo": "bar"
}
}
Istanza di Classe
Webman supporta il passaggio delle istanze di classe tramite il prompt per il tipo di parametro, ad esempio:
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());
}
}
Quando si accede a /blog/create?blog[title]=hello&blog[content]=world
, riceveremo il seguente risultato:
{
"title": "hello",
"content": "world"
}
Istanza di Modello
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;
// Qui è necessario aggiungere i campi riempibili per evitare che i campi non sicuri vengano passati dal frontend
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;
}
}
Quando accediamo a /user/create?user[name]=tom&user[age]=18
, riceveremo un risultato simile a questo:
1
Ciclo di Vita del Controller
Quando controller_reuse
in config/app.php
è impostato su false
, ogni richiesta inizializza nuovamente l'istanza del controller corrispondente, e l'istanza del controller viene distrutta alla fine della richiesta, esattamente come nel meccanismo di funzionamento di un framework tradizionale.
Quando controller_reuse
in config/app.php
è impostato su true
, tutte le richieste riutilizzeranno l'istanza del controller, ciò significa che l'istanza del controller, una volta creata, rimarrà in memoria e tutte le richieste la riutilizzeranno.
Attenzione
Quando il riutilizzo del controller è attivato, le richieste non dovrebbero modificare nessuna proprietà del controller, poiché queste modifiche influenzeranno le richieste successive. Ad esempio:
<?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)
{
// Questo metodo manterrà il model dopo la prima richiesta update?id=1
// Se si richiede nuovamente delete?id=2, si elimineranno i dati di 1
if (!$this->model) {
$this->model = Model::find($id);
}
return $this->model;
}
}
Suggerimento
Restituire dati nel costruttore__construct()
del controller non avrà alcun effetto, ad esempio:
<?php
namespace app\controller;
use support\Request;
class FooController
{
public function __construct()
{
// Restituire dati nel costruttore non avrà alcun effetto, il browser non riceverà questa risposta
return response('hello');
}
}
Differenza tra Non Riutilizzo e Riutilizzo del Controller
La differenza è la seguente:
Non Riutilizzare il Controller
Ogni richiesta creerà un nuovo istanza del controller; alla fine della richiesta, l'istanza viene rilasciata e la memoria viene recuperata. Non riutilizzare il controller è simile ai framework tradizionali, conforme alle abitudini della maggior parte degli sviluppatori. Dal momento che il controller viene creato e distrutto ripetutamente, le prestazioni saranno leggermente inferiori rispetto al riutilizzo del controller (le prestazioni di helloworld mostrano un calo del 10%, mentre per altre logiche aziendali è praticamente trascurabile).
Riutilizzare il Controller
Con il riutilizzo, un processo crea il controller una sola volta; alla fine della richiesta, non rilascia l'istanza del controller, le richieste successive nel processo attuale riutilizzeranno quest'istanza. Il riutilizzo del controller offre prestazioni migliori, ma non è conforme alle abitudini della maggior parte degli sviluppatori.
Le seguenti situazioni non consentono il riutilizzo del controller
Quando le richieste modificano le proprietà del controller, il riutilizzo del controller non può essere attivato, poiché queste modifiche influenzeranno le richieste successive.
Alcuni sviluppatori preferiscono effettuare alcune inizializzazioni in base a ogni richiesta nel costruttore del controller __construct()
, in tal caso non è possibile riutilizzare il controller, poiché il costruttore verrà chiamato solo una volta per il processo corrente e non per ogni richiesta.