Risposta
La risposta è in realtà un oggetto support\Response
. Per facilitare la creazione di questo oggetto, Webman fornisce alcune funzioni helper.
Restituisce una risposta qualsiasi
Esempio
<?php
namespace app\controller;
use support\Request;
class FooController
{
public function hello(Request $request)
{
return response('hello webman');
}
}
La funzione response è implementata come segue:
function response($body = '', $status = 200, $headers = array())
{
return new Response($status, $headers, $body);
}
Puoi anche creare un oggetto response
vuoto e poi utilizzare $response->cookie()
$response->header()
$response->withHeaders()
$response->withBody()
per impostare il contenuto di ritorno nei luoghi appropriati.
public function hello(Request $request)
{
// Creare un oggetto
$response = response();
// .... Logica aziendale omessa
// Impostare il cookie
$response->cookie('foo', 'value');
// .... Logica aziendale omessa
// Impostare l'intestazione http
$response->header('Content-Type', 'application/json');
$response->withHeaders([
'X-Header-One' => 'Header Value 1',
'X-Header-Tow' => 'Header Value 2',
]);
// .... Logica aziendale omessa
// Impostare i dati da restituire
$response->withBody('Dati restituiti');
return $response;
}
Restituisce json
Esempio
<?php
namespace app\controller;
use support\Request;
class FooController
{
public function hello(Request $request)
{
return json(['code' => 0, 'msg' => 'ok']);
}
}
La funzione json è implementata come segue
function json($data, $options = JSON_UNESCAPED_UNICODE)
{
return new Response(200, ['Content-Type' => 'application/json'], json_encode($data, $options));
}
Restituisce xml
Esempio
<?php
namespace app\controller;
use support\Request;
class FooController
{
public function hello(Request $request)
{
$xml = <<<XML
<?xml version='1.0' standalone='yes'?>
<values>
<truevalue>1</truevalue>
<falsevalue>0</falsevalue>
</values>
XML;
return xml($xml);
}
}
La funzione xml è implementata come segue:
function xml($xml)
{
if ($xml instanceof SimpleXMLElement) {
$xml = $xml->asXML();
}
return new Response(200, ['Content-Type' => 'text/xml'], $xml);
}
Restituisce una vista
Crea un file app/controller/FooController.php
come segue
<?php
namespace app\controller;
use support\Request;
class FooController
{
public function hello(Request $request)
{
return view('foo/hello', ['name' => 'webman']);
}
}
Crea un file app/view/foo/hello.html
come segue
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>webman</title>
</head>
<body>
hello <?=htmlspecialchars($name)?>
</body>
</html>
Reindirizzamento
<?php
namespace app\controller;
use support\Request;
class FooController
{
public function hello(Request $request)
{
return redirect('/user');
}
}
La funzione redirect è implementata come segue:
function redirect($location, $status = 302, $headers = [])
{
$response = new Response($status, ['Location' => $location]);
if (!empty($headers)) {
$response->withHeaders($headers);
}
return $response;
}
Impostazione intestazioni
<?php
namespace app\controller;
use support\Request;
class FooController
{
public function hello(Request $request)
{
return response('hello webman', 200, [
'Content-Type' => 'application/json',
'X-Header-One' => 'Header Value'
]);
}
}
Puoi anche utilizzare i metodi header
e withHeaders
per impostare singolarmente o in massa le intestazioni.
<?php
namespace app\controller;
use support\Request;
class FooController
{
public function hello(Request $request)
{
return response('hello webman')
->header('Content-Type', 'application/json')
->withHeaders([
'X-Header-One' => 'Header Value 1',
'X-Header-Tow' => 'Header Value 2',
]);
}
}
Puoi anche impostare le intestazioni in anticipo, poi impostare i dati da restituire alla fine.
public function hello(Request $request)
{
// Creare un oggetto
$response = response();
// .... Logica aziendale omessa
// Impostare l'intestazione http
$response->header('Content-Type', 'application/json');
$response->withHeaders([
'X-Header-One' => 'Header Value 1',
'X-Header-Tow' => 'Header Value 2',
]);
// .... Logica aziendale omessa
// Impostare i dati da restituire
$response->withBody('Dati restituiti');
return $response;
}
Impostare cookie
<?php
namespace app\controller;
use support\Request;
class FooController
{
public function hello(Request $request)
{
return response('hello webman')
->cookie('foo', 'value');
}
}
Puoi anche impostare i cookie in anticipo e poi impostare i dati da restituire alla fine.
public function hello(Request $request)
{
// Creare un oggetto
$response = response();
// .... Logica aziendale omessa
// Impostare il cookie
$response->cookie('foo', 'value');
// .... Logica aziendale omessa
// Impostare i dati da restituire
$response->withBody('Dati restituiti');
return $response;
}
I parametri completi del metodo cookie sono:
cookie($name, $value = '', $max_age = 0, $path = '', $domain = '', $secure = false, $http_only = false)
Restituisce un flusso di file
<?php
namespace app\controller;
use support\Request;
class FooController
{
public function hello(Request $request)
{
return response()->file(public_path() . '/favicon.ico');
}
}
- Webman supporta l'invio di file di grandi dimensioni
- Per file di grandi dimensioni (superiori a 2M), Webman non carica l'intero file in memoria in una sola volta, ma legge e invia il file a pezzi nel momento opportuno
- Webman ottimizza la velocità di lettura e invio del file in base alla velocità di ricezione del client, garantendo la massima velocità di invio del file mantenendo al minimo l'uso della memoria
- L'invio dei dati è non bloccante e non influisce sul trattamento di altre richieste
- Il metodo file aggiungerà automaticamente l'intestazione
if-modified-since
e nella richiesta successiva controlla l'intestazioneif-modified-since
. Se il file non è stato modificato, verrà restituito direttamente il 304 per risparmiare larghezza di banda - I file inviati verranno automaticamente inviati al browser con la corretta intestazione
Content-Type
- Se il file non esiste, verrà automaticamente convertito in una risposta 404
Scarica file
<?php
namespace app\controller;
use support\Request;
class FooController
{
public function hello(Request $request)
{
return response()->download(public_path() . '/favicon.ico', 'file_name.ico');
}
}
Il metodo download è sostanzialmente simile al metodo file, con la differenza che:
- Impostando il nome del file scaricato, il file verrà scaricato e non visualizzato nel browser
- Il metodo download non controllerà l'intestazione
if-modified-since
Ottieni output
Al alcune librerie stampano direttamente il contenuto del file sull'output standard, quindi i dati verranno stampati nel terminale della riga di comando e non verranno inviati al browser. In questo caso, dobbiamo catturare i dati in una variabile utilizzando ob_start();
ob_get_clean();
e poi inviarli al browser, ad esempio:
<?php
namespace app\controller;
use support\Request;
class ImageController
{
public function get(Request $request)
{
// Creare un'immagine
$im = imagecreatetruecolor(120, 20);
$text_color = imagecolorallocate($im, 233, 14, 91);
imagestring($im, 1, 5, 5, 'Una semplice stringa di testo', $text_color);
// Iniziare a catturare l'output
ob_start();
// Uscita dell'immagine
imagejpeg($im);
// Ottenere il contenuto dell'immagine
$image = ob_get_clean();
// Inviare l'immagine
return response($image)->header('Content-Type', 'image/jpeg');
}
}
Risposta a pezzi
A volte vogliamo inviare una risposta a pezzi, puoi fare riferimento al seguente esempio.
<?php
namespace app\controller;
use support\Request;
use support\Response;
use Workerman\Protocols\Http\Chunk;
use Workerman\Timer;
class IndexController
{
public function index(Request $request): Response
{
// Ottenere la connessione
$connection = $request->connection;
// Inviare pacchetti http a intervalli regolari
$timer = Timer::add(1, function () use ($connection, &$timer) {
static $i = 0;
if ($i++ < 10) {
// Inviare il pacchetto http
$connection->send(new Chunk($i));
} else {
// Rimuovere il timer non più necessario, evitando una fuga di memoria
Timer::del($timer);
// Inviare un pacchetto Chunk vuoto per notificare al client che la risposta è finita
$connection->send(new Chunk(''));
}
});
// Inviare prima un'intestazione http con Transfer-Encoding: chunked, il corpo http verrà inviato in modo asincrono
return response()->withHeaders([
"Transfer-Encoding" => "chunked",
]);
}
}
Se stai chiamando un modello di intelligenza artificiale, puoi fare riferimento al seguente esempio.
composer require webman/openai
<?php
namespace app\controller;
use support\Request;
use Webman\Openai\Chat;
use Workerman\Protocols\Http\Chunk;
class ChatController
{
public function completions(Request $request)
{
$connection = $request->connection;
// https://api.openai.com usa https://api.openai-proxy.com se non è accessibile in Cina
$chat = new Chat(['apikey' => 'sk-xx', 'api' => 'https://api.openai.com']);
$chat->completions(
[
'model' => 'gpt-3.5-turbo',
'stream' => true,
'messages' => [['role' => 'user', 'content' => 'hello']],
], [
'stream' => function($data) use ($connection) {
// Quando l'API OpenAI restituisce i dati, inoltrali al browser
$connection->send(new Chunk(json_encode($data, JSON_UNESCAPED_UNICODE) . "\n"));
},
'complete' => function($result, $response) use ($connection) {
// Controlla se ci sono errori alla fine della risposta
if (isset($result['error'])) {
$connection->send(new Chunk(json_encode($result, JSON_UNESCAPED_UNICODE) . "\n"));
}
// Restituisce un chunk vuoto per rappresentare la fine della risposta
$connection->send(new Chunk(''));
},
]);
// Restituisci prima un'intestazione http, i dati successivi verranno restituiti in modo asincrono
return response()->withHeaders([
"Transfer-Encoding" => "chunked",
]);
}
}