Phalcon Framework Dersleri – 5 / Controller ile Detaylı Çalışma
Controller Nedir?
Controller, MVC (Model-View-Controller) deseninde projenin iç süreçlerini kontrol eden, gelen istekleri işleyen bölümdür. Bu bölümde View ile Model arasındaki bağlantı kurulur. Kullanıcılardan gelen istekler (request) Controller’da değerlendirilir, isteğin detayına göre hangi işlemlerin yapılacağı ve kullanıcıya hangi View’ın döneceği (response) belirtilir. Default olarak tüm controller metodları ulaşılabilir bir haldedir. Action’lar ise isteği yorumlama ve yanıtı oluşturmak için sorumludur ve sonucu gösterme işlemi ile yükümlüdür.
Controller Nasıl Çalışır ?
Örnek verecek olursak; http://localhost/blog/posts/show/2014/phalcon-dersleri-5-controller-ile-detayli-calisma adresine erişmek istediğimizde Phalcon default olarak her parçayı şu şekilde ayrıştıracaktır :
Kısaca MVC Tasarım Deseni (Design Pattern);
– Kullanıcı sayfa üzerinden bir istek gönderir. (İstek: Request)
– İstek, ilgili Controller’da değerlendirilir ve hangi model ile ilgiliyse o modelde (ve veritabanında) işlemler yapılır. Controller ile Model arasında çift yönlü ok olmasının sebebi, isteğin çalıştırılma sürecinde Controller üzerinden farklı modellerin çağırılabillmesidir.
– Controller üzerinde Model işlemleri tamamlandıktan sonra bilgiler View üzerine yerleştirilir.
– View’a yerleştirilen bilgi kullanıcıya yanıt olarak gönderilir (Yanıt: Response). Böylelikle kullanıcının yaptığı bir istek MVC ile geliştirilmiş olan uygulamamız içerisinde başarıyla işlenip sonucu kullanıcıya sunulur.
– Controller, gelen isteğe göre Model’e uğramadan gerekli verileri hazırlayıp direk View’a bu bilgileri yerleştirip kullanıcıya yanıtı dönebilir.
Phalcon Klasörü | blog |
Controller | posts |
Action | show |
Parameter | 2014 |
Parameter | mustafa-toker |
Bu durumda, PostsController bu isteği karşılayıp, showAction‘a iletecektir. Oluşturacağınız Controller dosyaları mutlaka Controller son eki ile bitmelidir aynı şekilde Action’larda Action son eki ile bitmelidir.
<?php class PostsController extends \Phalcon\Mvc\Controller { public function indexAction() { } public function showAction($year, $postTitle) { } }
Yukarı da ki kodta da gördüğünüz üzere Değişkenleri URL’den alıp Action’a basit bir şekilde ilettik. Dilerseniz default değerde atayabilirsiniz :
<?php class PostsController extends \Phalcon\Mvc\Controller { public function indexAction() { } public function showAction($year=2014, $postTitle='some default title') { } }
Parametreleri metoda tanımlayabildiğiniz gibi, dispatcher servisine bağlı getParam metoduyla da alabilirsiniz (Sıralamaya dikkat edin):
<?php class PostsController extends \Phalcon\Mvc\Controller { public function indexAction() { } public function showAction() { $year = $this->dispatcher->getParam('year'); $postTitle = $this->dispatcher->getParam('postTitle'); } }
Dispatch Döngüsü (Dispatch Loop)
Dispatch döngüsü, Dispatcher servisi ile, çalıştırılacak bir method olmadığı durumlarda çalışır. Örneğin bir sayfamız var ve yetki kontrolü yaptık kullanıcının buraya girmesi yasak. O halde kullanıcıyı başka bir action’a gönderiyoruz.
<?php class PostsController extends \Phalcon\Mvc\Controller { public function indexAction() { } public function showAction($year, $postTitle) { $this->flash->error("You don't have permission to access this area"); // Forward flow to another action $this->dispatcher->forward(array( "controller" => "users", "action" => "signin" )); } }
Eğer kullanıcıların PostController’in showAction’una erişebilme yetkisi yoksa UsersController’in signinAction’una göndererek giriş yapmasını sağlıyoruz.
<?php class UsersController extends \Phalcon\Mvc\Controller { public function indexAction() { } public function signinAction() { } }
Controller Initialize
Not : Terimleri varolan şekliyle bilmeniz sizin için yapacağınız araştırmalarda kolaylık sağlayacaktır.
Phalcon\Mvc\Controller bize controller üzerinde ilk çalıştırılacak olan bir initialize methodu sağlar.
__construct methodu phalcon! tarafından tavsiye edilmez
<?php settings = array( "mySetting" => "value" ); } public function saveAction() { if ($this->settings["mySetting"] == "value") { //... } } }
Unutmayın ! initialize methodu sadece “geçerli action” controller üzerinde varsa ve yetkilendirme vs gibi işlemler için yönlendirme yapılmazsa çağrılır. Bu program mantığını korur.
Eğer siz her durumda çalışmasını istiyorsanız , onConstruct methodunu kullanabilirsiniz.
Unutmayın! onConstruct action olsun olmasın , yetki olsun olmasın her durumda çalışır , Controller’a istek gelmesi yeter.
DI Servisleri
Eğer Controller’ınız da Phalcon\Mvc\Controller’ı extend etti iseniz Bootstrap’de (index.php) tanımladığımız $di servislerine kolay bir şekilde erişebilirsiniz:
Bootstrap’de (public/index.php) şu şekilde tanımlayalım ;
<?php $di = new Phalcon\DI(); $di->set('storage', function() { return new Storage('/some/directory'); }, true);
Daha sonra Controller’ımız da şu şekilde erişebiliyoruz ;
<?php class FilesController extends \Phalcon\Mvc\Controller { public function saveAction() { // Injecting service ile bağlanıyoruz $this->storage->save('/some/file'); // DI ile bağlanıyoruz $this->di->get('storage')->save('/some/file'); // magic getter kullanarak bağlantı $this->di->getStorage()->save('/some/file'); // magic getter kullanarak farklı bir bağlantı $this->getDi()->getStorage()->save('/some/file'); // array ile bağlantı $this->di['storage']->save('/some/file'); } }
Request ve Response
Request ve Responce Phalcon\Mvc\Controller üzerinde sağlanan iki farklı servistir. Bu servisler bağlamında bir çok farklı method içerir. Request almak , talep etmek , Response basmak , yollamak anlamında kullanabilirsiniz. Bu anlamlarda mesela saveAction’a yollanan postu almak için request’i kullanırız.
<?php class PostsController extends Phalcon\Mvc\Controller { public function indexAction() { } public function saveAction() { // Check if request has made with POST if ($this->request->isPost() == true) { // Access POST data $customerName = $this->request->getPost("name"); $customerBorn = $this->request->getPost("born"); } } }
Bilgileri aldık ve işledik , ama mesela bir şey oldu mesela bir yazıya geldi adam 404 action’a yönlendirdik. 404 action’da status kodu ayarlamak için response kullanıyoruz
<?php class PostsController extends Phalcon\Mvc\Controller { public function indexAction() { } public function notFoundAction() { // Send a HTTP 404 response header $this->response->setStatusCode(404, "Not Found"); } }
Session Data
Persistant’lar bize istekler arasında veri saklama imkanı sağlar. Phalcon\Session\Bag servisine herhangi bir controller ‘dan ulaşabilirsiniz.
<?php class UserController extends Phalcon\Mvc\Controller { public function indexAction() { $this->persistent->name = "Michael"; } public function welcomeAction() { echo "Welcome, ", $this->persistent->name; } }
Servisleri Controller olarak kullanmak
Bir kontrolleri servis olarak kaydedebilirsininiz. Bu bir gizleme işlemi olarak adlandırılabilir. Yani IndexController çağrıldığında bir servis çalışabilir.
<?php //Register a controller as a service $di->set('IndexController', function() { $component = new Component(); return $component; }); //Register a namespaced controller as a service $di->set('Backend\Controllers\IndexController', function() { $component = new Component(); return $component; });
Temel Controller Oluşturmak (ControllerBase)
Base controller oluşturmak her zaman size kolaylık sağlayacaktır . ControllerBase phalcon\mvc\controller’dan extend olurken , diğer tüm controller’larınız bu ControllerBaseextend olur. Bu sayede mesela tüm controller’larda geçerli bir servis var, mesela çoklu dil, ve ya cache bu durumlarda , her controllerda karışıklık yapmak yerine ControllerBase üzerinden ayarlıyoruz.
<?php class ControllerBase extends \Phalcon\Mvc\Controller { /** * This action is available for multiple controllers */ public function someAction() { } }
Şu şekilde extend edip erişebiliyoruz;
<?php class UsersController extends ControllerBase { }
Controller’da olay tabanlı işlemler
Controller’lar dispatcher’de bir olay olduğunda otomatik dinleyici olarak hareket eder. Uygulamalarınıza önce/sonra eylemlerini şu şekilde implemente edebilirsiniz :
<?php class PostsController extends \Phalcon\Mvc\Controller { public function beforeExecuteRoute($dispatcher) { // Her bulundu eyleminin öncesinde çalışır. Örneğin http://localhost/posts/save/ şeklinde istek geldiğinde Action'ın ismi save ise kullanıcının bu sayfayı görüntüleme izini olmadığını ve dispatcher ile anasayfa'ya yönlendirebilirsiniz. if ($dispatcher->getActionName() == 'save') { $this->flash->error("You don't have permission to save posts"); $this->dispatcher->forward(array( 'controller' => 'home', 'action' => 'index' )); return false; } } public function afterExecuteRoute($dispatcher) { // Her bulundu eyleminin sonrasında çalışır. } }
Not : Genellikle Resmi dökümandan çeviri yaptığım için ekip arkadaşım Muhammed’in yazmış olduğu makaleden yararlandım bir kaç konuda ise yazdıklarını direkt aldım.