İlk web modeli RoR olan MVC’nin PHP gibi yüksek sayıda takipçisi olan bir web sunucu dili ile gündeme gelmesiyle View’un özellikleri de çeşitlilik gösterdi. Önceleri, sadece template sistemi gibi olan dosyalar varken, View zamanla Layout ve Element özelliklerini de kendine kattı. Konumuz ise Code Igniter (CI)’da olmayan element (aslında gene recursive view) ve daha geniş bir çerçeveden bakan Layout sistemini CI’a kazandırmak. Buarada küçük ve konumuzla alakası olmayan bir bilgi, web’e ilk olarak RoR (Ruby on Rails) ile gelen bu MVC’nin V’sinin helperıymış, layoutuymuş gibi eklektik olayları yüzünden, gerçek MVC pattern‘inin kötü bir uyarlamasını düşünen ve haklı noktalarının olduğunu düşündüğüm argümanlar var, gene cümleyi hem uzattım hem böldüm hem de konu dağıttım bunu ayrı bir yazıda uzun uzun anlatayım iyisi.

Konumuza yavaştan dönersek; daha önce de bahsettiğim gibi, büyük (esnek, modüler, ve bakımı gittikçe zorlaşan) web uygulamalarında tercihim Zend Framework (ZF) iken; özel CMS, küçük/orta ölçekli yönetim paneli, veya benzeri küçük web uygulamalarında tercihim şu anda Code Igniter. Hala konuya gelemedim, ama devam..

Code Igniter’dan frameworklerle ilgili ilk yazımda kısaca bahsetmiştim. Code Igniter’ın benim için en kötü özelliği, herşeyin birbirine bağımlı olması ve pek modüler olmamasıydı. Buna rağmen, kodları PHP’ye başlayalı 3-4 ay olmuş ve OOP ile önceden tanışmış biri için çok kolay modifiye edilebiliyor olması bu dezavantajı ortadan kaldırıp yerini esnekliği getirebiliyor. Yani, özel birşey istediğinizde ya da Code Igniter yapısıyla ilgili bir sorunla karşı karşıya kaldığınızda bunun için düşünülmüş bir yapı yerine, Code Igniter içine özel kod yazmanın kolaylığını bulacaksınız.

Benim en büyük sorunum web uygulamalarında çok büyük rahatlık sağlayan Layout idi. Evet, sanki konuya yaklaşıyoruz gibi bir his var. Buradaki sorunumuz Layout’un View’un üstünde tanımlanması gereken birşey olduğu ama aynı zamanda View’un bir parçası olması gerektiği sorunuyla karşı karşıya kalmamız. Dolayısıyla Code Igniter’a bir yapısal değişiklik getirmek sözkonusu.

Ve Layout’a başladık.

Layout yapısını eklememiz için, CI Core’unun view’unu üstlenen display birimini değiştirmek durumdayız. Böyle büyük değişiklikleri CI’ya Core’unu doğrudan değiştirmeden uygulamamız için hooker sistemi var. Bu sayede CI core’u düzenlemediğimizden, Evillabs’dan gelen CI güncelleştirmelerini huzurla uygulayabiliyoruz.

Hook tanımlamak

Hook’lar CI’in hazır gelen bootsrap’ine dahil olmayabilir, açıkçası hatırlamıyorum :-). Ama yapmak çok basit, öncelikle bootsrap’de hooku açıyoruz.

Aşağıdaki satırı application/config/config.php ‘deki enable_hooksatırını bulup değiştirin veya dosyanın sonuna ekleyin.

$config['enable_hooks'] = TRUE;

Bu durumda Code Igniter artık yaşadıkça öğreneceğiniz meşhur tek singleton class’ı olan CI ‘yı başlamadan application/config/hooks.php dosyasını değerlendirecektir.

Bu dosyada prototipi burada olup, kendim geliştirdiğim Yielder hookunu tanımlayacağız.

hooks.php içeriği

< ?
$hook['display_override'][] = array(
'class' => 'Yielder',
'function' => 'yield',
'filename' => 'Yielder.php',
'filepath' => 'hooks'
);
?>

Bu dosyada tanımlanan Yielder hookunun ismi Yielder.php ve adı Yielder. Şimdi display işini CI ‘dan devralacak Yielder classını yaratalım. Gene CI hazır bootsrap’i sayesinde, yaratılan hookları application/hooks dizininde arayacaktır. Bizde dolayısıyla bu dizinin altında Yielder.php isimli dosyada classımızı oluşturacağız.

Yielder.php içeriği

< ? if (!defined('BASEPATH')) exit('No direct script access allowed');
class Yielder
{
function yield()
{
/*TODO yeni display.. eski benchmark ->; System/Libraries/Output.php _display replace, inherit edilecek. ediliyor. EDİLDİ. */
global $BM;

$CI= &amp; get_instance();
$output = &$CI->output->final_output;

if (!preg_match("/(.+).php$/", $CI->layout)){
$CI->layout .= ".php";
}

if ($CI->layout != -1)
{
$requested = 'application/views/layouts/' . $CI->layout;
$default = 'application/views/layouts/default.php';
if (!file_exists($default)) die("Hook failed: Yealder 404 $default");
if (file_exists($requested))
{
$layout = $CI-&gt;load->file($requested,true);
$view = $layout; //nerdeyse performans farkı yok 0.001-5 ms.
}
else
{
$layout = $CI->load->file($default, true);
$view = $layout;
}
}

else
{
$view = $output;
}
/* direk inherit? */
echo $CI->output->_display($view);
//echo $view;
}
}
?>

Artık Controllerımızda View çağrıldığında, doğrudan kendisi gelmeden önce hangi layout’un içine geleceğini bildiriyoruz. Bunun için koddan da anlaşılacağı gibi, henüz varolmayan application/views/layouts/ klasörünü ve onun altında default layout dosyasını (default.php) oluşturuyoruz.

default.php

<?php
/**
* GY_Lisans::callback("korktularmiAcaba");
* Bu basit layout dosya örneği, tamamen kendisinin de RoR 'dan arakladığı
* cakePHP'den araklanmıştır. Bankalarda hesaptan hesaba yapılan para transferleriyle
* aklanan insanların "Arakın arakının arakı, benimdir" pskolojisiyle,
* alnın akıyla tüm hakları Gökçe YALÇIN'ındır. Aşağıdaki lisansı, Gökçe YALÇIN dahi iplemez,
* ne de olsa Gökçe YALÇIN'ın da kimliğinde T.C uyruklu yazmaktadır.
* Bırakın biti, bir digit bile değişiklik yapılırsa itfaiye çağırırız,
* BSA'ya haber verir, prestijinizi ilgili reklamlarda gösterilen işadamlarından beter ederiz;
* cabası Micro$oft'un avukatlarıyla kokoreç yemeye zorlanırsınız.  İyi günner.
* GY_Lisans::dispatch();
*
* @author             Gokce YALCIN <breathalyse@gmail.com>
* @license            http://www.opensource.org/licenses/mit-license.php The MIT License
*/

?>
<html>
<head>
<?php
@include("head.php"); //burda da yaparız yani!
?>
</head>
<body>
<div id="container">
<div id="header">
<h1>Bu layout'a tabi statik bilgi</h1>
</div>
<div id="content">
<?php
echo $this->output->get_output();
?>
</div>

< ?@include_once("footer.php");?>

</div>
</body>
</html>

Peki, çeşit çeşit layout’lar kullanmak için ne yapacaksınız? Aşağıda bir controller örneği var.

<?php
class Main extends Controller {
    function Main()
    {
        parent::Controller();
        $this->layout = 'main'; //controllerin varsayilan layoutunu degistirmek, yani default.php yerine main.php layout u kullanilacak.
    }
    function index() {
        $this->load->view("index.php");
    }
    function bununLayoutuYok() { URI: /main/bununLayoutuYok
        $this->layout = -1;
                $this->load->view("bunun.php");
    }
    function bununBisiyiYok() {
                $this->layout = -1;
        }
}
?>

Buarada terimleri niye ingilizce kullandığıma dair bir eleştiri aldım. Aslında haklı bir eleştiri, fakat araçtırmacı insanlar genelde sırtını en bol kaynağı içerdiğinden ötürü ingilizce kaynaklara yöneliyor, dolayısıyla bunu yaparken de terimlerin ingilizce orjinlerine göre hareket ediyor. MVC’yi “Kalıp Görünüm Yönetici” diye çevirsem, kimse Googling ile birşey bulamazdı. Hiçbirşeyin doğrusu yanlışı yok, sadece ben pis bir pragmatistim ve microsoft çevirileri gibi benim hakkımda da ‘acaba bunun ingilizcesi ne olabilir, ne iğrenç çeviri’ diye konuşmalarını istemedim. Neyse layout konusuna gelince tekrar, yapılacak birşey kalmadı. Hepsi bu kadar.

Son söz

Kimileri “MVC’de hani outputun gösterilmesiyle ilgili herşeyin üstünde View olmalıydı? Burada resmen Layout View’u inherit ediyor, hatta içiçe” diyebilir. Bence haklılar ve bunun üzerine düşerken ZF’de Zend_Layout ve Zend_View ayrılmış olarak doğru kullanmanın iç rahatlığını yaşarken , Agavi’de bence MVC’yi en iyi uygulayan yapıyı görebilirler. Fakat Agavi’yi projenin dokümantasyon görevini üstlenecek yeterince geliştiricisi olmadığından, eşeleye eşeleye öğrenmek durumundayız. Bu da ayrı yazının konusu ve kokusu.

Bir diğer haber de Code Igniter ile ilgili yazım, “RoR’daki ve cakePHP’deki View’un renderElement özelliğini de eklemek” olacak. Aslında bence gereksiz, zaten view’un recursive kullanımı. Ama cakePHP’nin View’una alışmış ama sihirbazlığından usanmış insanlar için gene de yapalım.

Eğer beğendiysen, belki GWG'nin RSS beslemesine kayıt olmak istersin. Ziyaretin için teşekkürler!