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 Sie config/app.php und setzen Sie controller_suffix auf Controller 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 Hilfsfunktionen response(), 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 über POST ü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.