Kontrolcü

Yeni bir kontrolcü dosyası app/controller/FooController.php oluşturun.

<?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');
    }
}

http://127.0.0.1:8787/foo adresine erişildiğinde, sayfa hello index döner.

http://127.0.0.1:8787/foo/hello adresine erişildiğinde, sayfa hello webman döner.

Tabii ki, yönlendirme yapılandırması ile yol kurallarını değiştirebilirsiniz, yönlendirme bölümüne bakınız.

İpucu
404 hatası alıyorsanız, lütfen config/app.php dosyasını açın, controller_suffix değerini Controller olarak ayarlayın ve yeniden başlatın.

Kontrolcü Sonuçları

Webman 1.3 sürümünden itibaren, config/app.php dosyasında kontrolcü son eklerini ayarlamayı destekler. Eğer config/app.php dosyasında controller_suffix boş '' olarak ayarlanmışsa, kontrolcü şöyle olacaktır:

app\controller\Foo.php şeklindedir.

<?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');
    }
}

Kontrolcü son ekinin Controller olarak ayarlanması şiddetle önerilir, bu, kontrolcüler ile model sınıf adları arasında çakışma olasılığını azaltır ve güvenliği artırır.

Açıklama

  • Çerçeve otomatik olarak kontrolcülere support\Request nesnesi geçer; bu nesne ile kullanıcı tarafından gönderilen verileri (get, post, header, cookie vb.) alabilirsiniz. Daha fazla bilgi için istek bölümüne bakın.
  • Kontrolcü içinde sayılar, dizeler veya support\Response nesneleri dönebilir, ancak başka türde veri dönemez.
  • support\Response nesnesi, response(), json(), xml(), jsonp(), redirect() gibi yardımcı fonksiyonlar aracılığıyla oluşturulabilir.

Kontrolcü Parametre Bağlama

Örnek

Webman, kontrolcü metod parametrelerini otomatik olarak istek parametrelerine bağlamayı destekler. Örneğin:

<?php
namespace app\controller;
use support\Response;

class UserController
{
    public function create(string $name, int $age): Response
    {
        return json(['name' => $name, 'age' => $age]);
    }
}

name ve age değerlerini GET veya POST yöntemiyle iletebilir veya yönlendirme parametreleri ile de geçirebilirsiniz. Örneğin:

Route::any('/user/{name}/{age}', [app\controller\UserController::class, 'create']);

Öncelik sırası: yönlendirme parametreleri > GET > POST parametreleri

Varsayılan Değerler

Eğer /user/create?name=tom adresine erişirsek, aşağıdaki hatayı alacağız:

Missing input parameter age

Sebep, age parametresini iletmemiş olmamızdır; bu durumu çözmek için parametreye varsayılan bir değer verebiliriz. Örneğin:

<?php
namespace app\controller;
use support\Response;

class UserController
{
    public function create(string $name, int $age = 18): Response
    {
        return json(['name' => $name, 'age' => $age]);
    }
}

Parametre Türleri

Eğer /user/create?name=tom&age=not_int adresine erişirsek, aşağıdaki hatayı alacağız:

İpucu
Burada testi kolaylaştırmak için, parametreleri doğrudan tarayıcı adres çubuğuna yazdık, gerçek geliştirme sürecinde parametreleri POST yöntemiyle iletmek gereklidir.

Input age must be of type int, string given

Bu hatanın sebebi, alınan verinin türüne göre dönüştürme yapılmasıdır. Eğer dönüştürme yapılamazsa, support\exception\InputTypeException istisnası fırlatılır. Geçilen age parametresi int türüne dönüştürülemediği için yukarıdaki hata ile karşılaşırız.

Özelleştirilmiş Hatalar

Missing input parameter age ve Input age must be of type int, string given gibi hataları çok dilli destek ile özelleştirebiliriz. Aşağıdaki komutlar ile bunu gerçekleştirebilirsiniz:

composer require symfony/translation
mkdir resource/translations/zh_CN/ -p
echo "<?php
return [
    'Input :parameter must be of type :exceptType, :actualType given' => 'Girdi parametresi :parameter :exceptType türünde olmalıdır, verilen tür :actualType',
    'Missing input parameter :parameter' => ':parameter girdi parametresi eksik',
];" > resource/translations/zh_CN/messages.php
php start.php restart

Diğer Türler

Webman'da desteklenen parametre türleri int, float, string, bool, array, object, sınıf örnekleri gibi türlerdir. Örneğin:

<?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,
        ]);
    }
}

/user/create?name=tom&age=18&balance=100.5&vip=true&extension[foo]=bar adresine eriştiğimizde, aşağıdaki sonucu alırız:

{
  "name": "tom",
  "age": 18,
  "balance": 100.5,
  "vip": true,
  "extension": {
    "foo": "bar"
  }
}

Sınıf Örnekleri

Webman, parametre türü belirtimi ile sınıf örneklerini geçirmeyi destekler. Örneğin:

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());
    }
}

/blog/create?blog[title]=hello&blog[content]=world adresine eriştiğimizde, aşağıdaki sonucu alırız:

{
  "title": "hello",
  "content": "world"
}

Model Örnekleri

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;
    // Burada doldurulabilir alanları eklemek, güvenli olmayan alanların önüne geçmek için gereklidir.
    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;
    }
}

/user/create?user[name]=tom&user[age]=18 adresine eriştiğimizde, aşağıdaki gibi bir sonuç alırız:

1

Kontrolcü Yaşam Döngüsü

config/app.php dosyasındaki controller_reuse değeri false olduğunda, her istekte karşılık gelen kontrolcü örneği yeniden başlatılır ve istek sona erdiğinde kontrolcü örneği yok edilir. Bu, geleneksel çerçeve çalışma mekanizmasına benzerdir.

config/app.php dosyasındaki controller_reuse değeri true olduğunda, tüm istekler kontrolcü örneklerini yeniden kullanır; yani bir kontrolcü örneği oluşturulduktan sonra bellek üzerinde kalır ve tüm istekler bu örneği yeniden kullanır.

Dikkat
Kontrolcü yeniden kullanımı etkinleştirildiğinde, isteklerin kontrolcünün herhangi bir özelliğini değiştirmemesi gerektiği unutulmamalıdır; çünkü bu değişiklikler sonraki istekleri etkileyecektir. Örneğin:

<?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)
    {
        // Bu yöntem, ilk istek update?id=1 gerçekleştikten sonra modeli saklayacak.
        // Eğer delete?id=2 isteği yapılırsa, 1'in verileri silinir.
        if (!$this->model) {
            $this->model = Model::find($id);
        }
        return $this->model;
    }
}

İpucu
Kontrolcünün __construct() yapıcı fonksiyonunda döndürülen verinin bir etkisi olmayacaktır; örneğin:

<?php
namespace app\controller;

use support\Request;

class FooController
{
    public function __construct()
    {
        // Yapıcı fonksiyonda döndürülen verinin hiç bir etkisi yoktur; tarayıcı bu tepkiyi almayacaktır.
        return response('hello'); 
    }
}

Kontrolcü Yeniden Kullanımının Farkları

Farklar aşağıdaki gibidir:

Kontrolcü Yeniden Kullanılmaması

Her istek yeni bir kontrolcü örneği oluşturur, istek sona erdikten sonra bu örnek serbest bırakılır ve bellek geri alınır. Kontrolcülerin yeniden kullanılmaması, geleneksel çerçevelerin çalışma şekline benzer ve çoğu geliştiricinin alışkanlıklarına uygundur. Kontrolcülerin tekrar tekrar oluşturulması ve yok edilmesi nedeniyle performansı, kontrolcülerin yeniden kullanılması ile biraz daha düşük olma eğilimindedir (hello world performans testi yaklaşık %10 daha kötü, iş mantığı durumlarında bu fark göz ardı edilebilir).

Kontrolcü Yeniden Kullanılması

Yeniden kullanma durumunda bir işlemde sadece bir kez kontrolcü oluşturulur; istek sona erdikten sonra bu kontrolcü örneği serbest bırakılmaz ve mevcut işlemin sonraki istekleri bu örneği yeniden kullanır. Kontrolcü yeniden kullanımı performansı artırır, fakat çoğu geliştiricinin alışkanlıklarına aykırıdır.

Aşağıdaki Durumlarda Kontrolcü Yeniden Kullanılamaz

Eğer istekler kontrolcünün özelliklerini değiştirecekse, kontrolcü yeniden kullanımı etkinleştirilemez; çünkü bu özelliklerdeki değişiklikler sonraki istekleri etkileyebilir.

Bazı geliştiriciler kontrolcünün __construct() yapıcı fonksiyonunda her istek için bazı başlangıç ayarları yapmayı tercih eder; bu durumda kontrolcü yeniden kullanılamaz çünkü mevcut işlemde yapıcı fonksiyon yalnızca bir kez çağrılır ve her istek için tekrar çağrılmaz.