Contrôleur
Créez un fichier de contrôleur 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');
}
}
Lorsque vous accédez à http://127.0.0.1:8787/foo
, la page renvoie hello index
.
Lorsque vous accédez à http://127.0.0.1:8787/foo/hello
, la page renvoie hello webman
.
Bien sûr, vous pouvez modifier les règles de routage via la configuration des routes, voir Routage.
Avertissement
Si un 404 apparaît et que vous ne pouvez pas accéder, ouvrezconfig/app.php
, définissezcontroller_suffix
surController
, puis redémarrez.
Suffixe du contrôleur
webman à partir de la version 1.3 prend en charge la définition du suffixe du contrôleur dans config/app.php
, si controller_suffix
est défini comme vide ''
dans config/app.php
, le contrôleur ressemblera à ceci
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');
}
}
Il est fortement recommandé de définir le suffixe du contrôleur sur Controller
, cela permet d'éviter les conflits de noms entre les contrôleurs et les modèles, tout en augmentant la sécurité.
Remarques
- Le framework transmet automatiquement un objet
support\Request
au contrôleur, à travers lequel vous pouvez obtenir les données saisies par l'utilisateur (données get post header cookie, etc.), voir Requête - Le contrôleur peut retourner des nombres, des chaînes ou des objets
support\Response
, mais ne peut pas retourner d'autres types de données. - L'objet
support\Response
peut être créé via les fonctions d'assistanceresponse()
,json()
,xml()
,jsonp()
,redirect()
, etc.
Liaison des paramètres du contrôleur
Exemple
webman prend en charge la liaison automatique des paramètres de requête via les paramètres de méthode du contrôleur, par exemple
<?php
namespace app\controller;
use support\Response;
class UserController
{
public function create(string $name, int $age): Response
{
return json(['name' => $name, 'age' => $age]);
}
}
Vous pouvez transmettre les valeurs name
et age
via les méthodes GET
ou POST
, ou les transmettre via des paramètres de route, par exemple
Route::any('/user/{name}/{age}', [app\controller\UserController::class, 'create']);
La priorité est paramètres de route
> GET
> paramètres POST
Valeurs par défaut
Supposons que nous accédions à /user/create?name=tom
, nous obtiendrons l'erreur suivante
Missing input parameter age
La raison en est que nous n'avons pas transmis le paramètre age
, ce problème peut être résolu en définissant une valeur par défaut pour le paramètre, par exemple
<?php
namespace app\controller;
use support\Response;
class UserController
{
public function create(string $name, int $age = 18): Response
{
return json(['name' => $name, 'age' => $age]);
}
}
Type de paramètre
Lorsque nous accédons à /user/create?name=tom&age=not_int
, nous obtiendrons l'erreur suivante
Avertissement
Ici, pour des raisons de commodité de test, nous avons directement saisi les paramètres dans la barre d'adresse du navigateur, dans un développement réel, les paramètres devraient être transmis par la méthodePOST
Input age must be of type int, string given
C'est parce que les données acceptées seront converties en fonction du type, et si la conversion échoue, une exception support\exception\InputTypeException
sera levée,
comme le paramètre age
transmis ne peut pas être converti en type int
, l'erreur ci-dessus est donc renvoyée.
Erreurs personnalisées
Nous pouvons personnaliser des erreurs comme Missing input parameter age
et Input age must be of type int, string given
en utilisant plusieurs langues, voir la commande suivante
composer require symfony/translation
mkdir resource/translations/zh_CN/ -p
echo "<?php
return [
'Input :parameter must be of type :exceptType, :actualType given' => 'Le paramètre d’entrée :parameter doit être de type :exceptType, :actualType donné',
'Missing input parameter :parameter' => 'Paramètre d’entrée manquant :parameter',
];" > resource/translations/zh_CN/messages.php
php start.php restart
Autres types
Les types de paramètres supportés par webman comprennent int
, float
, string
, bool
, array
, object
, instances de classe
, etc., par exemple
<?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,
]);
}
}
Lorsque nous accédons à /user/create?name=tom&age=18&balance=100.5&vip=true&extension[foo]=bar
, nous obtiendrons le résultat suivant
{
"name": "tom",
"age": 18,
"balance": 100.5,
"vip": true,
"extension": {
"foo": "bar"
}
}
Instances de classe
webman prend en charge le passage d'instances de classe via des indices de type de paramètre, par exemple
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());
}
}
Lorsque vous accédez à /blog/create?blog[title]=hello&blog[content]=world
, nous allons obtenir le résultat suivant
{
"title": "hello",
"content": "world"
}
Instance de modèle
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;
// Ici, il faut ajouter les champs remplissables pour éviter que des champs non sécurisés soient transmis par le front-end
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;
}
}
Lorsque nous accédons à /user/create?user[name]=tom&user[age]=18
, nous obtiendrons un résultat similaire à celui-ci
1
Cycle de vie du contrôleur
Lorsque controller_reuse
dans config/app.php
est false
, chaque requête initialise une fois l'instance de contrôleur correspondante, une fois la requête terminée, l'instance de contrôleur est détruite, ce qui est identique au mécanisme d'exécution des frameworks traditionnels.
Lorsque controller_reuse
dans config/app.php
est true
, toutes les requêtes réutiliseront l'instance de contrôleur, ce qui signifie que l'instance de contrôleur, une fois créée, restera en mémoire, toutes les requêtes la réutilisent.
Avertissement
Lorsque la réutilisation du contrôleur est activée, les requêtes ne doivent pas modifier les propriétés du contrôleur, car ces modifications affecteront les requêtes suivantes, par exemple
<?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)
{
// Cette méthode conservera le modèle après la première requête update?id=1
// Si une requête delete?id=2 est faite par la suite, cela supprimera les données de 1
if (!$this->model) {
$this->model = Model::find($id);
}
return $this->model;
}
}
Avertissement
Dans le constructeur__construct()
du contrôleur, retourner des données n'aura aucun effet, par exemple
<?php
namespace app\controller;
use support\Request;
class FooController
{
public function __construct()
{
// Retourner des données dans le constructeur n'a aucun effet, le navigateur ne recevra pas cette réponse
return response('hello');
}
}
Différence entre non-réutilisation et réutilisation du contrôleur
Les différences sont les suivantes
Non-réutilisation du contrôleur
Chaque requête crée une nouvelle instance de contrôleur, l'instance est libérée après la fin de la requête et la mémoire est récupérée. La non-réutilisation du contrôleur est conforme à la plupart des habitudes des développeurs, similaire aux frameworks traditionnels. En raison de la création et de la destruction répétées du contrôleur, les performances sont légèrement inférieures à celles des contrôleurs réutilisés (environ 10% de différence sur le test de performance helloworld, négligeable en cas de charge métier).
Réutilisation du contrôleur
Avec la réutilisation, une instance de contrôleur n'est créée qu'une seule fois par processus, et après la fin de la requête, cette instance de contrôleur n'est pas libérée, les requêtes suivantes du processus actuel réutiliseront cette instance. La réutilisation des contrôleurs offre de meilleures performances, mais ne correspond pas à la plupart des habitudes des développeurs.
Situations où la réutilisation du contrôleur ne peut pas être utilisée
Lorsque les requêtes modifient les propriétés du contrôleur, la réutilisation du contrôleur ne doit pas être activée, car ces modifications affecteront les requêtes suivantes.
Certains développeurs aiment effectuer certaines initialisations pour chaque requête dans le constructeur du contrôleur __construct()
, dans ce cas, le contrôleur ne peut pas être réutilisé, car le constructeur de l'actuel processus ne sera appelé qu'une seule fois, pas à chaque requête.