Controller
Erstellen Sie die Controller-Datei 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');
}
}
Wenn Sie http://127.0.0.1:8787/foo
aufrufen, wird die Seite hello index
zurückgeben.
Wenn Sie http://127.0.0.1:8787/foo/hello
aufrufen, wird die Seite hello webman
zurückgeben.
Natürlich können Sie die Routing-Regeln durch die Routen-Konfiguration ändern, siehe Routing.
Hinweis
Wenn ein 404-Fehler auftritt und der Zugriff nicht möglich ist, öffnen Sieconfig/app.php
und setzen Siecontroller_suffix
aufController
und starten Sie neu.
Controller-Suffix
Webman unterstützt seit Version 1.3 das Setzen des Controller-Suffixes in config/app.php
. Wenn controller_suffix
in config/app.php
leer ''
eingestellt ist, sieht der Controller wie folgt aus:
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');
}
}
Es wird dringend empfohlen, das Controller-Suffix auf Controller
zu setzen, um Konflikte zwischen Controller- und Modellklassen zu vermeiden und die Sicherheit zu erhöhen.
Erläuterungen
- Das Framework übergibt automatisch ein
support\Request
-Objekt an den Controller, mit dem Sie Benutzereingabedaten (GET, POST, Header, Cookie usw.) abrufen können, siehe Anfrage. - Im Controller können Zahlen, Strings oder
support\Response
-Objekte zurückgegeben werden, jedoch keine anderen Datentypen. - Das
support\Response
-Objekt kann mit den Hilfsfunktionenresponse()
,json()
,xml()
,jsonp()
,redirect()
usw. erstellt werden.
Parameterbindung im Controller
Beispiel
Webman unterstützt die automatische Bindung von Anfrageparametern an die Parameter von Controller-Methoden, zum Beispiel:
<?php
namespace app\controller;
use support\Response;
class UserController
{
public function create(string $name, int $age): Response
{
return json(['name' => $name, 'age' => $age]);
}
}
Sie können die Werte für name
und age
sowohl über den GET
als auch den POST
-Methoden übergeben oder durch Routenparameter übergeben, zum Beispiel:
Route::any('/user/{name}/{age}', [app\controller\UserController::class, 'create']);
Die Priorität ist Routenparameter
> GET
> POST
.
Standardwerte
Angenommen, wir rufen /user/create?name=tom
auf, erhalten wir folgenden Fehler:
Missing input parameter age
Der Grund ist, dass wir den Parameter age
nicht übergeben haben. Dies kann durch das Setzen eines Standardwertes für den Parameter behoben werden, zum Beispiel:
<?php
namespace app\controller;
use support\Response;
class UserController
{
public function create(string $name, int $age = 18): Response
{
return json(['name' => $name, 'age' => $age]);
}
}
Parametertypen
Wenn wir /user/create?name=tom&age=not_int
aufrufen, erhalten wir folgenden Fehler:
Hinweis
Hier haben wir der Einfachheit halber die Parameter direkt in der Adressleiste des Browsers eingegeben. In der praktischen Entwicklung sollten Parameter überPOST
übergeben werden.
Input age must be of type int, string given
Dies liegt daran, dass die empfangenen Daten nach Typ umgewandelt werden, und wenn die Umwandlung fehlschlägt, wird die Ausnahme support\exception\InputTypeException
ausgelöst. Da der übergebene Parameter age
nicht in den Typ int
konvertiert werden kann, erhalten wir den oben genannten Fehler.
Benutzerdefinierte Fehler
Wir können die mehrsprachige Unterstützung verwenden, um Fehler wie Missing input parameter age
und Input age must be of type int, string given
anzupassen, siehe den folgenden Befehl:
composer require symfony/translation
mkdir resource/translations/zh_CN/ -p
echo "<?php
return [
'Input :parameter must be of type :exceptType, :actualType given' => 'Eingabeparameter :parameter muss vom Typ :exceptType sein, übergebener Typ ist :actualType',
'Missing input parameter :parameter' => 'Eingabeparameter :parameter fehlt',
];" > resource/translations/zh_CN/messages.php
php start.php restart
Andere Typen
Webman unterstützt Parameter vom Typ int
, float
, string
, bool
, array
, object
und Klasseninstanzen
, zum Beispiel:
<?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,
]);
}
}
Wenn wir /user/create?name=tom&age=18&balance=100.5&vip=true&extension[foo]=bar
aufrufen, erhalten wir folgendes Ergebnis:
{
"name": "tom",
"age": 18,
"balance": 100.5,
"vip": true,
"extension": {
"foo": "bar"
}
}
Klasseninstanzen
Webman unterstützt das Übergeben von Klasseninstanzen durch Typ-Hinweise, zum Beispiel:
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());
}
}
Wenn wir /blog/create?blog[title]=hello&blog[content]=world
aufrufen, erhalten wir folgendes Ergebnis:
{
"title": "hello",
"content": "world"
}
Modellinstanz
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;
// Hier müssen füllbare Felder hinzugefügt werden, um zu verhindern, dass ungesicherte Felder vom Frontend übergeben werden
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;
}
}
Wenn wir /user/create?user[name]=tom&user[age]=18
aufrufen, erhalten wir ein ähnliches Ergebnis:
1
Lebenszyklus des Controllers
Wenn controller_reuse
in config/app.php
auf false
steht, wird bei jeder Anfrage eine neue Instanz des entsprechenden Controllers initialisiert. Nach dem Ende der Anfrage wird die Instanz des Controllers zerstört, was dem Verhalten traditioneller Frameworks entspricht.
Wenn controller_reuse
in config/app.php
auf true
steht, werden alle Anfragen die Controller-Instanz wiederverwenden, das heißt, die Controller-Instanz bleibt im Speicher, sobald sie erstellt wurde, und wird von allen Anfragen wiederverwendet.
Hinweis
Wenn die Wiederverwendung des Controllers aktiviert ist, sollten Anfragen keine Eigenschaften des Controllers ändern, da diese Änderungen die nachfolgenden Anfragen beeinflussen könnten, zum Beispiel:
<?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)
{
// Diese Methode wird beim ersten Aufruf von update?id=1 model beibehalten
// Wenn delete?id=2 erneut aufgerufen wird, werden die Daten von 1 gelöscht
if (!$this->model) {
$this->model = Model::find($id);
}
return $this->model;
}
}
Hinweis
Rückgaben im Konstruktor__construct()
des Controllers haben keine Wirkung, zum Beispiel:
<?php
namespace app\controller;
use support\Request;
class FooController
{
public function __construct()
{
// Rückgaben im Konstruktor haben keine Wirkung, der Browser erhält diese Antwort nicht
return response('hello');
}
}
Unterschiede zwischen nicht wiederverwendbaren und wiederverwendbaren Controllern
Die Unterschiede sind wie folgt:
Nicht wiederverwendbare Controller
Jede Anfrage erzeugt eine neue Controller-Instanz, die nach Beendigung der Anfrage freigegeben und der Speicher zurückgegeben wird. Die nicht wiederverwendbaren Controller verhalten sich wie in traditionellen Frameworks und entsprechen den Gewohnheiten der meisten Entwickler. Aufgrund der häufigen Erstellung und Zerstörung des Controllers ist die Leistung im Vergleich zu wiederverwendbaren Controllern leicht schlechter (die Leistung bei einem HelloWorld-Test liegt etwa 10 % zurück, was bei geschäftlichen Anwendungen im Grunde vernachlässigbar ist).
Wiederverwendbare Controller
Bei der Wiederverwendung wird ein Controller nur einmal pro Prozess erstellt, und die Controller-Instanz wird nach Abschluss der Anfrage nicht freigegeben. Die nachfolgenden Anfragen im aktuellen Prozess verwenden diese Instanz wieder. Wiederverwendbare Controller bieten eine bessere Leistung, entsprechen jedoch nicht den Gewohnheiten der meisten Entwickler.
Folgende Fälle sollten keine Wiederverwendung von Controllern verwenden
Wenn Anfragen Eigenschaften des Controllers ändern, sollte die Wiederverwendung des Controllers nicht aktiviert werden, da diese Änderungen die nachfolgenden Anfragen beeinflussen.
Einige Entwickler ziehen es vor, im Konstruktor __construct()
des Controllers für jede Anfrage einige Initialisierungen vorzunehmen. In diesem Fall kann der Controller nicht wiederverwendet werden, da der Konstruktor für den aktuellen Prozess nur einmal aufgerufen wird und nicht für jede Anfrage erneut aufgerufen wird.