Yanıt
Yanıt aslında bir support\Response
nesnesidir. Bu nesneyi oluşturmayı kolaylaştırmak için webman bazı yardımcı fonksiyonlar sunar.
Herhangi bir yanıt döndürme
Örnek
<?php
namespace app\controller;
use support\Request;
class FooController
{
public function hello(Request $request)
{
return response('hello webman');
}
}
response fonksiyonu aşağıdaki gibi tanımlanmıştır:
function response($body = '', $status = 200, $headers = array())
{
return new Response($status, $headers, $body);
}
Ayrıca önce boş bir response
nesnesi oluşturabilir ve uygun yerlerde $response->cookie()
, $response->header()
, $response->withHeaders()
, $response->withBody()
kullanarak dönecek içeriği ayarlayabilirsiniz.
public function hello(Request $request)
{
// Bir nesne oluştur
$response = response();
// .... İş mantığı atlandı
// Cookie ayarla
$response->cookie('foo', 'value');
// .... İş mantığı atlandı
// HTTP başlıklarını ayarla
$response->header('Content-Type', 'application/json');
$response->withHeaders([
'X-Header-One' => 'Header Value 1',
'X-Header-Tow' => 'Header Value 2',
]);
// .... İş mantığı atlandı
// Dönecek veriyi ayarla
$response->withBody('Dönen veri');
return $response;
}
JSON döndürme
Örnek
<?php
namespace app\controller;
use support\Request;
class FooController
{
public function hello(Request $request)
{
return json(['code' => 0, 'msg' => 'ok']);
}
}
json fonksiyonu aşağıdaki gibi tanımlanmıştır:
function json($data, $options = JSON_UNESCAPED_UNICODE)
{
return new Response(200, ['Content-Type' => 'application/json'], json_encode($data, $options));
}
XML döndürme
Örnek
<?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);
}
}
xml fonksiyonu aşağıdaki gibi tanımlanmıştır:
function xml($xml)
{
if ($xml instanceof SimpleXMLElement) {
$xml = $xml->asXML();
}
return new Response(200, ['Content-Type' => 'text/xml'], $xml);
}
Görünüm döndürme
Yeni bir dosya oluşturun app/controller/FooController.php
aşağıdaki gibi
<?php
namespace app\controller;
use support\Request;
class FooController
{
public function hello(Request $request)
{
return view('foo/hello', ['name' => 'webman']);
}
}
Yeni bir dosya oluşturun app/view/foo/hello.html
aşağıdaki gibi
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>webman</title>
</head>
<body>
hello <?=htmlspecialchars($name)?>
</body>
</html>
Yönlendirme
<?php
namespace app\controller;
use support\Request;
class FooController
{
public function hello(Request $request)
{
return redirect('/user');
}
}
redirect fonksiyonu aşağıdaki gibi tanımlanmıştır:
function redirect($location, $status = 302, $headers = [])
{
$response = new Response($status, ['Location' => $location]);
if (!empty($headers)) {
$response->withHeaders($headers);
}
return $response;
}
Başlık ayarı
<?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'
]);
}
}
Ayrıca header
ve withHeaders
metodlarını kullanarak başlıkları tekil veya toplu olarak ayarlayabilirsiniz.
<?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',
]);
}
}
Başlıkları önceden ayarlayabilir, en son dönecek veriyi ayarlayabilirsiniz.
public function hello(Request $request)
{
// Bir nesne oluştur
$response = response();
// .... İş mantığı atlandı
// HTTP başlıklarını ayarla
$response->header('Content-Type', 'application/json');
$response->withHeaders([
'X-Header-One' => 'Header Value 1',
'X-Header-Tow' => 'Header Value 2',
]);
// .... İş mantığı atlandı
// Dönecek veriyi ayarla
$response->withBody('Dönen veri');
return $response;
}
Cookie ayarı
<?php
namespace app\controller;
use support\Request;
class FooController
{
public function hello(Request $request)
{
return response('hello webman')
->cookie('foo', 'value');
}
}
Ayrıca önceden cookie ayarlayabilir, en son dönecek veriyi ayarlayabilirsiniz.
public function hello(Request $request)
{
// Bir nesne oluştur
$response = response();
// .... İş mantığı atlandı
// Cookie ayarla
$response->cookie('foo', 'value');
// .... İş mantığı atlandı
// Dönecek veriyi ayarla
$response->withBody('Dönen veri');
return $response;
}
cookie metodunun tam parametreleri aşağıdaki gibidir:
cookie($name, $value = '', $max_age = 0, $path = '', $domain = '', $secure = false, $http_only = false)
Dosya akışı döndürme
<?php
namespace app\controller;
use support\Request;
class FooController
{
public function hello(Request $request)
{
return response()->file(public_path() . '/favicon.ico');
}
}
- webman büyük dosyaları göndermeyi destekler
- Büyük dosyalar (2M'den fazla), webman dosyayı tam olarak belleğe almadan, uygun bir zamanda dosyayı parçalar halinde okuyarak gönderir
- webman, istemcinin alma hızına göre dosya okuma ve gönderme hızını optimize eder, en hızlı gönderimi sağlarken bellek kullanımını en düşük seviyeye çeker
- Veri gönderimi engellenmez, diğer istek işleme süreçlerini etkilemez
- file metodu otomatik olarak
if-modified-since
başlığını ekler ve bir sonraki istekteif-modified-since
başlığını kontrol eder; eğer dosya değiştirilmediyse, bant genişliğini tasarruf etmek için doğrudan 304 döndürülür - Gönderilen dosya otomatik olarak uygun
Content-Type
başlığı ile tarayıcıya gönderilir - Eğer dosya yoksa, otomatik olarak 404 yanıtına dönüşür
Dosya indirme
<?php
namespace app\controller;
use support\Request;
class FooController
{
public function hello(Request $request)
{
return response()->download(public_path() . '/favicon.ico', 'dosya_adı.ico');
}
}
download metodu ile file metodu temelde aynıdır; farkları şunlardır:
- İndirilecek dosya adı ayarlandığında, dosya indirilir, tarayıcıda gösterilmez
- download metodu
if-modified-since
başlığını kontrol etmez
Çıktıyı alma
Bazı kütüphaneler dosya içeriğini doğrudan standart çıktıya yazdırır, bu da verilerin komut satırı terminaline yazdırılacağı ve tarayıcıya gönderilmeyeceği anlamına gelir; bu durumda verileri bir değişkende yakalamak için ob_start();
ve ob_get_clean();
kullanmamız gerekir, ardından verileri tarayıcıya gönderebiliriz, örneğin:
<?php
namespace app\controller;
use support\Request;
class ImageController
{
public function get(Request $request)
{
// Görüntü oluştur
$im = imagecreatetruecolor(120, 20);
$text_color = imagecolorallocate($im, 233, 14, 91);
imagestring($im, 1, 5, 5, 'Basit Bir Metin Dizisi', $text_color);
// Çıktıyı almaya başla
ob_start();
// Görüntüyü yazdır
imagejpeg($im);
// Görüntü içeriğini al
$image = ob_get_clean();
// Görüntüyü gönder
return response($image)->header('Content-Type', 'image/jpeg');
}
}
Parçalı yanıt
Bazen yanıtları parçalar halinde göndermek isteyebiliriz, aşağıdaki örneğe bakabilirsiniz.
<?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
{
// Bağlantıyı al
$connection = $request->connection;
// HTTP paket gövdesini zamanlayarak gönder
$timer = Timer::add(1, function () use ($connection, &$timer) {
static $i = 0;
if ($i++ < 10) {
// HTTP paket gövdesini gönder
$connection->send(new Chunk($i));
} else {
// Gereksiz zamanlayıcıyı silerek bellek sızıntısını önle
Timer::del($timer);
// İstemciye yanıtın bittiğini bildirmek için boş bir Chunk paketi gönder
$connection->send(new Chunk(''));
}
});
// Transfer-Encoding: chunked olan bir HTTP başlığı gönder, HTTP paket gövdesi asenkron olarak gönderilecek
return response()->withHeaders([
"Transfer-Encoding" => "chunked",
]);
}
}
Eğer büyük model çağrılıyorsa, aşağıdaki örneğe bakabilirsiniz.
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 adresi erişilemezse https://api.openai-proxy.com adresini kullanabilirsiniz
$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) {
// OpenAI arayüzü veri döndüğünde tarayıcıya ilet
$connection->send(new Chunk(json_encode($data, JSON_UNESCAPED_UNICODE) . "\n"));
},
'complete' => function($result, $response) use ($connection) {
// Yanıt bittiğinde hata olup olmadığını kontrol et
if (isset($result['error'])) {
$connection->send(new Chunk(json_encode($result, JSON_UNESCAPED_UNICODE) . "\n"));
}
// Yanıtın bittiğini belirtmek için boş bir chunk gönder
$connection->send(new Chunk(''));
},
]);
// Önce bir HTTP başlığı döndür, daha sonraki veriler asenkron dönecek
return response()->withHeaders([
"Transfer-Encoding" => "chunked",
]);
}
}