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, apri config/app.php, imposta controller_suffix su Controller, 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 helper response(), 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 metodo POST.

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.