11 Mart 2015 Çarşamba

CodeIgniter - 5 - Sıfırdan Dinamik Site Kodlaması


Not: Bu yazı dizisi ne yazık ki burada bitiyor. Vaktiyle konuyu tamamlamadan bıraktığım bu yazıyı devam ettiremiyorum çünkü çok uzun zamandır CodeIgniter kullanmıyorum. En baştan, bu yazının tamam olmadığını ve tamamlanmayacağını belirtmek isterim. Kolay gelsin...



Eveet, geldik CodeIgniter'ın en önemli mevzuuna: Veritabanı işlemleri...

Bu yayında, örnek bir proje geliştireceğiz. Projemizde şu özellikler olacak:
1- Kullanıcıları karşılayan, içeriğini veritabanından çeken bir AnaSayfa
1.1 - Anasayfamızda bir resim listesi ve resimlerin altında açıklamaları yer alacak
2 - Anasayfayı yönetmek için bir yönetim paneli
2.1 - Yönetim paneli girişi için bir sayfa
2.2 - Resimlerin silinmesi veya yeni resim eklenmesi için bir sayfa

Bu basit projemize sıfırdan başlayalım:

1) Öncelikle projemiz için, localhost'umuzda bir klasör açalım: site.com
> Ben XAMPP kullandığımdan, yolum şu şekilde: C:\xampp\htdocs\site.com\

2) İnternetten edindiğimiz CodeIgniter dosyalarımızı, bu klasör içine atalım.
> application, system klasörleri ve index.php dosyası

3) site.com klasörümüzde .htaccess dosyası oluşturalım ve içine standart kodlarımızı yazalım:

RewriteEngine on
RewriteCond $1 !^(index\\.php|resources|robots\\.txt)
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?/$1 [L,QSA]

5 yayındır .htaccess dosyası oluşturun diyorum ama bunu oluştururken sorun yaşayanlar olabilir diye yazmak istedim: Yeni bir notepad metin belgesi oluşturun. İçine yukarıdaki kodları yazın. Farklı kaydet deyin ve dosyanın adına (çift tırnaklar ve başındaki nokta da dahil) şunu yazıp Kaydet deyin: ".htaccess"

4) PhpMyAdmin ile yeni bir veritabanı oluşturalım. Adına da site_vt diyelim.

5) site_vt adlı veritabanımızda, şu tablolarımız ve sütunlarımız bulunsun:

resimler [4 sütun] > id [int], resim [varchar(20)], tarih [timestamp], sira [varchar(5)]
anasayfa [4 sütun] > id [int], title [text], description [text], keywords [text]
admin [3 sütun] > id [int], user [varchar(50)], pass [varchar[50]

6) application/config/database.php dosyasını açalım ve şu satırları değiştirelim:

$db['default']['hostname'] = 'localhost'; // localhost'ta çalışacağız
$db['default']['username'] = 'root'; // PhpMyAdmin'e girerken kullandığınız kullanıcı adı
$db['default']['password'] = '1234'; // PhpMyAdmin'e girerken kullandığınız şifre
$db['default']['database'] = 'site_vt'; // Malum, veritabanı adımız

7) application/config/config.php dosyasını açalım ve şu satırları değiştirelim:

// Tarayıcımız yolunu kaybetmesin, sitenin ana yolunu bilsin diye:
$config['base_url'] = 'http://localhost/site.com/';

// URL'lerde Türkçe karakter sorunu yaşamamak için:
$config['permitted_uri_chars'] = 'a-üöçşığz A-ÜÖÇŞİĞZ 0-9~%.:_\-';

8) application/config/autoload.php dosyasını açalım ve şu satırları değiştirelim:

$autoload['libraries'] = array('database'); // Her sayfada veritabanı işlemi yapacağız

$autoload['helper'] = array('url'); // URL yapımızla ilgili her sayfada işlem yapacağız

9) application/config/routes.php dosyasını açalım ve şu satırı değiştirelim:

$route['default_controller'] = 'anasayfa'; // Varsayılan giriş sayfası anasayfa olacak.

10) Dilerseniz, site.com dosyanızı bu haliyle başka bir yere de kaydedin. Böylece her yeni siteye başladığınızda bu ayarları tekrar tekrar yapmak zorunda kalmak yerine, sadece yeni projenin gerektirdiği bölümleri değiştirirsiniz.

11) Sitemizi kodlamaya giriş olarak, anasayfa adlı controller'ımızı kodlamaktan başlayalım.
applications/controllers/ klasörü altına anasayfa.php adlı bir controller dosyası oluşturun. (routes.php dosyasında yaptığımız değişiklikle, site açıldığında ilk olarak bu controller'ın çalışmasını istedik) Bu controller'ımızın içinde, şu kodlarımız yer alsın:

<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');

class anasayfa extends CI_Controller
{
    public function __construct() {
        parent::__construct();
    }

    public function index() {
        $this->load->view('anasayfa_view');
    }
}


Sayfa açıldığında ilk olarak elbette kurucu fonksiyon çalışacak. Daha sonra, URL yapısında* herhangi bir parametre bulunmadığı için, varsayılan olarak index() adlı fonksiyon çalışacak. Gördüğünüz gibi, index() fonksiyonunda da şu an için yalnızca, anasayfa_view adlı view dosyasının gösterilmesi komutunu vermişiz. Bu controller'ımızı, daha sonra dönmek üzere bu haliyle kaydedelim ve anasayfa_view adlı view'imizi tasarlayalım. Çünkü artık bir HTML sayfası görmenin vakti geldi...

*URL yapımız, CodeIgniter mantığında şudur:
http://localhost/site.com/[controller adı]/[fonksiyon adı]/[fonksiyona giden parametre]

12) application/views/ klasörü altına, anasayfa_view.php adlı bir dosya oluşturalım ve içine, şu HTML kodlarını yazalım:

<!DOCTYPE HTML>
<html lang='tr-TR'>
<head>
    <meta charset='UTF-8'>
    <title>Başlık</title>
    <meta name='description' content='Açıklama' />
    <meta name='keywords' content='Anahtar Kelimeler' />
    <base href='<?=base_url()?>'>
    <link href='assets/css/style.css' rel='stylesheet' />
</head>
<body>
    <div id='resim-listesi'>
        <div class='resim-kutusu'>
            <div class='resim'><img src='assets/images/1.jpg' /></div>
            <div class='metin'>Örnek resim metni</div>
        </div>
    </div>
</body>
</html>


13) Sayfamızı çalıştırmadan önce, bir CSS dosyası ve bir de resimler için klasör oluşturalım.
Kök klasörümüzün (site.com) içine, assets adlı bir klasör oluşturun. Bu klasörün de içine images ve css adında iki klasör oluşturun. images klasörünün içine 1.jpg adında herhangi bir resim dosyası atın. css klasörünün içine de, style.css adında bir dosya oluşturun ve içine şunları yazın:

* { margin:0; padding:0; box-sizing:border-box; transition:all .3s ease; }
body { font-family:Arial; cursor:default; font-size:14px; letter-spacing:0.5px;  }
#resim-listesi { margin:10px; }
#resim-listesi .resim-kutusu { margin-bottom:10px; }
#resim-listesi .resim-kutusu .resim img { max-width:300px; max-height:200px; }
#resim-listesi .resim-kutusu .metin { background:#ccc; padding:10px; }

14) Şimdi sayfamızı görüntüleyelim. Tarayıcımıza localhost/site.com yazalım. Resmimiz görüntülenmiş olmalı.

15) Şimdi sıra geldi, anasayfa adlı controller'ımızdan bu sayfaya veri göndermeye...
application/controllers/anasayfa.php dosyamızı tekrar açalım ve index() fonksiyonumuzu şu şekilde değiştirelim:

public function index() {
    $data['title'] = 'Site Başlığı';
    $data['description'] = 'Site Açıklaması';
    $data['keywords'] = 'anahtar kelime 1, anahtar kelime 2, ...';
    $this->load->view('anasayfa_view',$data);
}

Şu an için verileri veritabanından çekmek yerine, kendimiz veriyoruz. Şimdi bu verileri view dosyamızda okumak üzere, view dosyamızı açalım.
application/views/anasayfa_view.php dosyamızı tekrar açalım ve head tagı içinde şu değişiklikleri yapalım:

<head>
    <meta charset='UTF-8'>
    <title><?=$title?></title>
    <meta name='description' content='<?=$description?>' />
    <meta name='keywords' content='<?=$keywords?>' />
    <base href='<?=base_url()?>'>
    <link href='assets/css/style.css' rel='stylesheet' />
</head>

Şimdi yeniden deneme zamanı. Tarayıcımıza localhost/site.com yazarak, title, description ve keywords taglarına istediğimiz şekilde değerler yazılmış mı kontrol edelim. (Sayfanın kaynağını görüntüleyerek bu kontrolü sağlayabilirsiniz.) Böylelikle, controller'ımızdan view'ımıza veri göndermiş olduk. Şimdi sıra geldi, controller'ımızın bu verileri veritabanından çekmesine...

16) Nihayet, esas konumuza geldik. Veritabanı işlemlerini nasıl yaparız? Diğer bir deyişle, model katmanından controller katmanına nasıl veri çekeriz?
application/models/ klasörü altına, anasayfa_model.php adlı bir dosya oluşturalım ve içine şunları yazalım:

<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');

class anasayfa_model extends CI_Model
{  
    function __construct() {  }

    public function get_sayfa_verileri()
    {
        $this->db->select('title,description,keywords');
        $this->db->from('anasayfa');
        $sorgu = $this->db->get();
        $satir = $sorgu->row_array();
        return $satir;
    }
 }

Eğer CodeIgniter'ı benim yayınlarımdan öğrenmeye çalışıyorsanız, şu an ilk kez gördüğünüz birçok komutla karşılaştınız demektir. Aslında satırları inceleyecek olursanız, mantığın çok basit olduğunu görebilirsiniz. CodeIgniter sayesinde, SQL komutları yazmıyoruz. Daha şirin görünen komutlarla SQL sorgumuzu oluşturuyoruz. Satırları tek tek açıklamakta fayda görüyorum:

class anasayfa_model extends CI_Model
Bu satırımızda, modelimizin adını belirtiyor ve özelliklerini, CI_Model adlı class'dan miras alıyor.

public function get_sayfa_verileri()
Bu satırımızda, controller'ımızdan çağıracağımız fonksiyonumuzun adını belirtiyoruz. Neden fonksiyon adının başına get_ diye bir bölüm ekledim? Bu benim alışkanlığım. Bir veri çağıracaksam get_ derim, güncelleyeceksem update_ derim, ekleyeceksem set_ derim. Mecbur muyuz? Hayır.

$this->db->select('title,description,keywords');
SQL sorgumuzun SELECT title,desctiption,keywords FROM anasayfa bölümünü temsil ediyor. Alan adlarını tek tek yazmak zorunda mıydım? Hayır. Tüm alanları çekmek isteseydim, şöyle bir komut kullanabilirdim: $this->db->select('*');

$this->db->from('anasayfa');
SQL sorgumuzun SELECT title,description,keywords FROM anasayfa bölümünü temsil ediyor.

$sorgu = $this->db->get();
SQL sorgumuz çalıştırılıyor ve sonuç, $sorgu değişkenine aktarılıyor.

$satir = $sorgu->row_array();
Bu satırda istiyoruz ki, tek satırlık (olduğunu bildiğimiz) sorgu sonucumuz, bir diziye aktarılsın. row_array() dan anlamamız gereken budur. Bu iş neticesinde sütunlarımızı şu şekilde okuyabileceğiz: echo $satır['title'];

return $satir;
Controller ve Model katmanlarında (amacımız test etmek değilse) echo komutu kullanmayız. Bu katmanlar yalnızca veri iletimi yaparlar. Biz de bu satır sayesinde, model katmanımızda elde ettiğimiz $satir adlı diziyi, controller katmanından yakalanması için döndürüyoruz.

Şu an bazı şeyleri anladınız, bazı konularda da kafanızda soru işaretleri oluştu. Mesela tek satır değil de daha çok satır çekseydik, row_array() yerine ne yazmamız gerekirdi? Şu an bilmeniz gerekmeyen bu konuya, kafanızda soru işaretiyle devam etmemeniz için cevap veriyorum: result_array()
Bu komut ile elde ettiğiniz diziyi, foreach döngüsü yardımıyla satır satır okuyabilirsiniz. Sonraki adımlarda bu konunun da örneğini yapacağız...

Diğer bir soru da, peki ya WHERE koşuluyla arama yapmamız gerekseydi ne yapacaktık? Aslında bu konuda fikir yürüterek bir sonuca varmışsınızdır ama emin değilsinizdir. Daha sonra bunun da örneğini yapacağız ama şimdilik buna da cevap vermiş olalım. SQL sorgusunu çalıştırdığımız satırdan ($sorgu = $this->db->get(); satırından) önce şunu yazardık: $this->db->where('id',5);
Peki ya verileri sıralı çekmek isteseydik?
ORDER BY sira ASC için kodumuz: $this->db->order_by('sira');
ORDER BY sira DESC için kodumuz: $this->db->order_by('sira','DESC');

Daha merak ettiğiniz çok şey var biliyorum. Ama acele etmeyelim ve projemize devam edelim. Şu anda model katmanındaki dosyamızı oluşturduk ve ilk fonksiyonumuzu yazdık. Peki controller katmanında bu veriyi nasıl çağıracağız? Cevabı sonraki adımda:

17) application/controllers/anasayfa.php dosyamızı tekrar açalım ve index() fonksiyonumuzda şu değişiklikleri yapalım:

public function index() {

    $this->load->model('anasayfa_model'); // Model dosyamızı çağırıyoruz

    $veriler = $this->anasayfa_model->get_sayfa_verileri(); // Model'deki fonksiyonumuz...

    $data['title'] = $veriler['title'];
    $data['description'] = $veriler['description'];
    $data['keywords'] = $veriler['keywords'];
    $this->load->view('anasayfa_view',$data);
}

İşte bu kadar. Zaten daha önceden, veritabanından verileri çekmeden önce, verilerimizi $data adlı diziyle view'imize göndermiştik. Şimdi bu $data değişkenimizin değerlerini, veritabanından çektiğimiz değerlerle değiştirmiş olduk. Şimdi tarayıcıyı açıp çalıştırsak çalışır mı peki? Çalışmaz. Çünkü, veritabanında sorgu sonucunda hiç değer dönmüyor. Çünkü veritabanına değer girmedik! O halde, PhpMyAdmin üzeinden veritabanımızdaki anasayfa adlı tabloyu açın ve tek satırlık verilerimizi girin. Daha sonra localhost/site.com diyerek, sonucu görebilirsiniz...

18) Şimdi anasayfada resimlerin listelenmesinden önce, yönetim panelini kodlamaya geçelim. Yönetim panelimiz için tek bir controller kullanalım. Yani admin girişini de bu controller halletsin, resim ekleme ve silme işlemini de...
Önceki derslerimizden bildiğiniz gibi, eğer bir sayfa ekleyeceksek bu sayfa için controller oluşturuyor ve bu controller ile bir view çağırıyorduk. Bunu her sayfa için ayrı ayrı yapıyorduk. Ancak yönetim panelimizde, farklı bir yöntem kullanacağız. yonetimpaneli adında tek bir controller'ımız olacak ve bu controller, birçok view sayfasını yönetecek. Uygulamada daha iyi anlayacaksınız.
application/controllers/ klasörü içine yonetimpaneli.php adlı bir sayfa oluşturun ve şu kodları yazın:

<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');

class yonetimpaneli extends CI_Controller
{
    public function __construct() {
        parent::__construct();
    }

    public function index() {
        $this->load->view('yonetimpaneli/giris_view');
    }
}

Gördüğünüz gibi, yonetimpaneli adlı controller'ımızın varsayılan fonksiyonu olan index()'de, yonetimpaneli klasörü altındaki giris_view adlı view'ı çağırıyoruz. Şimdi, admin'in kullanıcı adı ve şifresiyle giriş yapacağı bu view'ımızı oluşturalım.

19) application/views/ klasörü altına, yonetimpaneli adlı bir klasör açın. (Bu klasörün adıyla controller'ımızın adının aynı olması tamamen benim tercihim. Böyle bir zorunluluk yok.) Neden böyle bir klasör açtık diye sorarsanız: Sitenin normal sayfalarıyla, yönetim paneli sayfaları birbirinden ayrı dursun, karışmasın, aradığımız view'ı rahatça bulabilelim diye...
Şimdi bu yonetimpaneli klasörünün içine, giris_view.php adında bir dosya oluşturun ve içine şunları yazın:

<!DOCTYPE HTML>
<html lang='tr-TR'>
<head>
    <meta charset='UTF-8'>
    <title>Yönetim Paneli</title>
    <base href='<?=base_url()?>'>
    <style>#uyari { color:#f22; padding:20px; border:1px solid #f22; margin:20px; }</style>
</head>
<body>
    <?= $uyari ) ? '<div id="uyari">' . $uyari . '</div>' : ' ' ?>
    <form method='post'>
        <input type='text' name='user' placeholder='Kullanıcı Adı' />
        <input type='text' name='pass' placeholder='Şifre' />
        <input type='submit' value='Oturum Aç' />
    </form>
    <div><a href='anasayfa'>Siteye Dön</a></div>
</body>
</html>

Çok basit ve tasarım çalışması yapılması gereken bir form sayfamız oldu. Konumuz tasarım olmadığı için CSS'e fazlaca girmek istemiyorum. Şu an sayfamızda üç tane yan yana dizilmiş input'umuz, henüz görünmese de bir uyarı div'imiz ve bir de bizi anasayfa'ya yönlendiren link'imiz var. Sayfamızı çalıştırmak istediğimizde bir hata alacağız, çünkü $uyari değişkeni oluşturmadık. Bunu controller'ımızdan oluşturacağız ve bu sayfaya göndereceğiz. (uyarı verilen satırdaki yazım şeklini bilmeyenler olabilir diyerek, o satırın ne iş yaptığını anlatmak istiyorum.
Bu satır: <?= $uyari ? '<div id="uyari">' . $uyari . '</div>: ' ' ?> ve
bu satır: <?php if $uyari echo '<div id="uyari">' . $uyari . '</div>'; else echo ' '; ?>
aynı işi yapar.

20) application/controllers/yonetimpaneli.php adlı controller dosyamızı tekrar açalım ve şu değişiklikleri yapalım:

<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');

class yonetimpaneli extends CI_Controller
{
    public function __construct() {
        parent::__construct();
    }

    private function OturumKapaliMi()
    {
        $this->load->library('session');
        if($this->session->userdata('login')==true)
        redirect(base_url().'yonetimpaneli/resimyonetimi');
    }
    private function OturumAcikMi()
    {
        $this->load->library('session');
        if($this->session->userdata('login')==null)
        redirect(base_url().'yonetimpaneli');
    }
    public function oturumkapat()
    {
        $this->load->library('session');
        $this->session->unset_userdata('login');
        redirect(base_url().'yonetimpaneli');
    }

    public function index() {
        $this->OturumKapaliMi();

        $data['uyari'] = '';

        if( $this->input->post() ) { // Sayfaya veri post edilmişse...
            $user = $this->input->post('user'); // kullanıcı adını $user değişkenine at
            $pass = $this->input->post('pass'); // şifreyi $pass değişkenine at

            $this->load->model('yonetimpaneli_model');
            $admin = $this->yonetimpaneli_model->get_admin();

            if( $user == $admin['user'] && $pass == $admin['pass'] ) {
                $this->load->library('session');
                $this->session->set_userdata('login',true);
                redirect(base_url()."yonetimpaneli/resimyonetimi");
            }
            else $data['uyari'] = 'Kullanıcı adı ve şifre kombinasyonu hatalı...';
        }
     

        $this->load->view('yonetimpaneli/giris_view', $data);
    }
}

Böylelikle, bir sürü yeni komut görmüş oldunuz. Şimdi teeek tek bu komutların ne anlama geldiğini ele alalım bakalım...

İki adet private fonksiyonumuz olan OturumKapaliMi() ve OturumAcikMi() ne iş yaparlar? Bunları yazmamızdaki amaç şudur: Oturumun açık olup olmadığını kontrol etmek... index() fonksiyonumuzun ilk satırında, $this->OturumKapaliMi(); adlı fonksiyonu çağırdığımıza dikkat edin. Orada, şunu kontrol ediyoruz: Bu sayfayı görüntüleyen adamın oturumunun kapalı olması gerekir (ki oturum açmak için bir form görüntülüyor) de, bu adamın oturumu şu an kapalı mı ki? Fonksiyon, eğer oturum açmış biri bu sayfayı görüntülemeye çalışırsa, onu direkt yönetim panelinin iç sayfalarına (resimyonetimi sayfasına - evet, henüz böyle bir sayfamız yok) yönlendiriyor. Facebook gibi düşünün. Eğer oturumunuz açıksa, Facebook'a girdiğinizde oturum açmanız için hazırlanmış giriş sayfasını görmezsiniz. Direkt ana sayfaya yönlendirilirsiniz. Bizdeki de o hesap... OturumAcikMi() fonksiyonunu henüz kullanmadık. O fonksiyonu, sadece oturumu açık kişilerin görebileceği sayfaların başında kullanacağız ki, oturum açmamış biri o sayfalara bir şekilde (mesela URL'ye yazarak) erişmeye kalkarsa, sayfayı göremeden, oturum açması için index() fonksiyonunun sayfasına (giris_view) yönlendirilsin.

$this->load->library('session');
CodeIgniter'da nasıl ki view'leri, model'leri controller'ımıza çağırmak için bu load zımbırtısını (controller'ımıza extends ettiğimiz CI_Controller sınıfıyla gelen load sınıfını) kullanıyorsak, oturum işlemleri yapmak için de CodeIgniter'ın library'sinden (applications/library klasörü) session class'ını çağırmamız gerekiyordu ve bu komutla çağırmış oluyoruz... Böylelikle, CodeIgniter'ın $_SESSION yönetimi yapan komutlarını kullanabiliyoruz.

if($this->session->userdata('login')==true) { ... }
Standart PHP'deki karşılığı şudur: if ( $_SESSION['login'] == true ) { ... }

redirect(base_url().'yonetimpaneli/resimyonetimi');
yonetimpaneli adlı controller'ın resimyonetimi() fonksiyonunu çalıştır. (Evet, henüz resimyonetimi() fonksiyonunu yazmadık.) Diğer bir deyişle, şu URL'ye yönlendir:
http://localhost/site.com/yonetimpaneli/resimyonetimi

redirect(base_url().'yonetimpaneli');
yonetimpaneli adlı controller'a yönlendir. Diğer bir deyişle, şu URL'ye yönlendir:
http://localhost/site.com/yonetimpaneli
Diğer bir deyişle, yonetimpaneli controller'ının index() fonksiyonunu çalıştır.

public function oturumkapat() { ... }
Bu fonksiyonumuzun amacı, adı üzerinde, oturum kapatmak. Eğer biz oturum açmış kullanıcımıza şu yönlendirmeyi yaparsak, bu fonksiyon çalışacaktır:
http://localhost/site.com/yonetimpaneli/oturumkapat

$this->session->unset_userdata('login');
login adlı SESSION'ı yok et... Biz bu projemizde sadece login adlı SESSION ile oturum kontrolü yapıyoruz. Siz elbette $_SESSION dizisi üzerinden başka veriler de oluşturabilirsiniz. Biz şu an bu projemizde güvenlik önlemi almıyoruz. Güvenlik, başka bir yayınımın konusu olacak.

$user = $this->input->post('user');
Standart PHP'deki karşılığı: $user = $_POST['user']; (Evet, hiç güvenli değil biliyorum.) CodeIgniter'da mecbur muyuz post edilen veriyi input class'ı yardımıyla çekmeye? Hayır. Standart PHP'deki gibi kullansanız da olur. Ama elinizden geldiğince CodeIgniter'daki şekliyle kullanın ki, öğrenin. Çünkü CodeIgniter, buna ek olarak birçok özellik sunmaktadır. Mesela kodumuz şöyle olsaydı: $user = $this->input->post('user',true); post edilen veri, zararlı kodlardan arındırılmış olurdu... CodeIgniter komutlarına alışın ki, onların özelliklerinden faydalanın. (input class'ı, başka bir yayınımın konusu olacak. Şimdilik konudan sapmayalım...)

$this->load->model('yonetimpaneli_model');
$admin = $this->yonetimpaneli_model->get_admin();
Bu iki satırın ne yaptığını merak ediyor musunuz? 17.adımda anlattığım örneği inceleyin. Bu satırların işlevini burada açıklamamamın nedeni sizi sinir etmek değil elbet. Bu şekilde, daha iyi öğrenirsiniz diye düşünüyorum.

$this->session->set_userdata('login',true);
login adlı SESSION'ımızı burada oluşturuyor ve true değeri atıyoruz.

Umarım açıklayıcı olabilmişimdir. Bu 20.adımda size çok yüklendim, ilk kez gördüğünüz (tabi CodeIgniter'ı bu blog'dan takip ederek öğreniyorsanız) bir sürü komutu önünüze yığdım. Neyse ki bu canlı bir ders değil de, geriye dönüp tekrar tekrar okuma ve rahatça not alma şansınız var.

Şimdi iki görevimiz var:
Birincisi, PhpMyAdmin'e girip, veritabanımızdaki admin adlı tablomuza veri girmek. user sütununa admin, pass sütununa 123 yazın. Bu, kolay görevdi.
İkincisi, controller'ımızda çağırdığımız yonetimpaneli_model adlı model dosyamızı oluşturmak ve get_admin() adlı fonksiyonumuzla, admin tablosundaki verileri çekip return etmek... Bu arada, aklınıza takılmış olabilir. view dosyalarına _view diye yazıyorduk ve bu tamamen bizim keyfimize kalmış bir durumdu. (anasayfa_view.php, giris_view.php gibi) Daha önceki yayınlarımda yazdım mı bilmiyorum ama yazdıysam da yine yazayım. Model dosyalarında _model ekini koymamız mecburi bir durum. (anasayfa_model.php, yonetimpaneli_model.php gibi) Bunu da söyledikten sonra, ikinci görevimizi 21.adımda gerçekleştirelim...

21) application/models/ klasörü altına yonetimpaneli_model.php dosyası oluşturun ve şunları yazın:

<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');

class yonetimpaneli_model extends CI_Model
{
    function __construct() {  }

    public function get_admin()
    {
        $this->db->select('user,pass');
        $this->db->from('admin');
        $sorgu = $this->db->get();
        $satir = $sorgu->row_array();
        return $satir;
    }
}

Böylelikle, admin girişi yapan sayfamız da hazır... Gördüğünüz gibi sitemiz bir üyelik sistemi barındırmıyor. Yalnızca yönetim paneli için, yalnızca tek bir admin için giriş yaptıryoruz. Ancak mantığı kavradığınızda, üyelik sistemi de kodlayabilirsiniz.

Şu anda neler oldu? Adminimiz yönetim panelinin giriş sayfasına giriyor. Kullanıcı adını ve şifresini yazıp oturum açıyor ve yonetimpaneli controller'ımızın resimyonetimi fonksiyonuna yönlendiriliyor. Burada resim ekleme, güncelleme ve silme işlemlerini yapacağız ve yönetim panelimizi tamamlamış olacağız. Daha sonra bu yönetim panelimizi kullanarak images klasörümüze ve veritabanımıza resimler ekleyeceğiz. Sonra da, 18.adımda yarım bıraktığımız anasayfa'da resimlerin listelenmesi olayını gerçekleştirerek, yayınımızı tamamlayacağız.

22) application/controllers/yonetimpaneli controller'ımızı açalım ve index() fonksiyonumuzun altına şu eklemeleri yapalım:

<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');

class yonetimpaneli extends CI_Controller
{
    public function __construct() {
        parent::__construct();
    }

    private function OturumKapaliMi() { ... }
    private function OturumAcikMi() { ... }
    public function oturumkapat() { ... }
 
    public function index() { ... }

    public function resimyonetimi($islem='',$silinecek_id='')
    {
        // Oturum açık mı? Çünkü oturum açık değilse, bu fonksiyon çalışmamalı...
        $this->OturumAcikMi();

        $data['uyari'] = '';

        if( $islem == 'ekle' ) 
        { 
             // yonetimpaneli/resimyonetimi/ekle URL'si gelirse yapılacak işlemler

             $data['uyari'] = 'Resim eklendi';
        }        
        elseif( $islem == 'guncelle' )
        {
             // yonetimpaneli/resimyonetimi/guncelle URL'si gelirse yapılacak işlemler

            $data['uyari'] = 'Resim güncellendi';
        }
        elseif( $islem == 'sil' )
        {
             // yonetimpaneli/resimyonetimi/sil/1 şeklinde bir URL gelmiş olmalı...
             // Silme işlemi için URL'de sil parametresinden sonra gelen parametremiz
             // id parametremiz olacak. Bu parametrenin, integer bir sayı olması gerekiyor.
             $id = (int)$silinecek_id+0;

            // Böylece $id değişkenimizde bir adet tam sayımız var. Eğer bu parametre
            // boş gönderilmişse ( URL: yonetimpaneli/resimyonetimi/sil )
            // veya id parametresi olarak sayı gelmemişse ( yonetimpaneli/resimyonetimi/şaka )
            // id değerimiz 0 olacak. Yani bir sorun var demektir... Kontrol edelim var mı:             
             if( $silinecek_id <= 0 )
             {
                  $data['uyari'] = 'Silinecek resim bilgisini veren parametrede sorun var.';
             }
             else
             {
                   // yonetimpaneli/resimyonetimi/sil/1 şeklinde bir URL gelirse yapılacak işlemler

                   $data['uyari'] = $id.' ID\'li resim silindi'; // 1 ID'li resim silindi
              }
        }

        $this->load->view('yonetimpaneli/resimyonetimi_view', $data);

    }
}

Bu yapıyı açıklamak gerekirse, URL'den resimyonetimi adlı fonksiyona parametreler gönderiliyor. URL içinde bu parametrelere göre farklı if kontrolleri çalışıyor. Buradaki amacım, yapılacak her işlem için (Güncelle, Ekle, Sil) yeni bir fonksiyon oluşturmamak... Böyle bir kullanım, bir fonksiyon içinde çok fazla komut birikmesine ve hata ararken yorulmamıza neden olur. (Ama ben genelde bu yapıyı kullanıyorum.)

Öncelikle, bu sayfanın HTML halini (view dosyasını) görmek için, resimyonetimi_view dosyamızı oluşturalım ve genel yapımızı görelim. Buna göre, controller'ın hangi verilere ihtiyacı olacağını daha iyi görebiliriz.

23) application/views/yonetimpaneli klasörü altına resimyonetimi_views.php adlı dosyamızı oluşturalım ve şunları yazalım:

--- YAYIN BURADA BİTİYOR. ---

<<< Umarım buraya kadar olan kısım faydalı olmuştur.  >>>

10 Mart 2015 Salı

PDO ile MySQL Veritabanı İşlemleri Yapan Class


Bugün, PHP'de PDO ile MySQL veritabanı işlemleri yapmamıza olanak sağlayan bir class'ımı tanıtmak ve kullanımınıza sunmak istiyorum.

Amacımız kodlama yaparken hız kazanmak mı? O halde kendi hazır fonksiyonlarımız, class'larımız olmalı. Şimdi bu bağlamda, PHP'de PDO kullanarak MySQL bağlantısı sağlayan ve temel veritabanı işlemleri olan SELECT, INSERT, UPDATE ve DELETE işlemlerini yapabilen bir class yapısını sizlerle paylaşacağım.

class ebykdrms_Veritabani {
 
    private $db;
    private $dsn;
    private $user;
    private $password;

    function __construct() {      
        $this->dsn = 'mysql:host=localhost;dbname=veritabaniadi;charset=utf8';
        $this->user = 'root';
        $this->password = '1234';
    }

    private function baglantiAc() {
        try { $this->db = new PDO($this->dsn, $this->user, $this->password); }
        catch (PDOException $e) { echo 'Veritabanı bağlantısı başarısız oldu: ' . $e->getMessage(); }
    }

    private function baglantiKapat() {
        $this->db = null;
    }

    function ekle($tablo, $veriler) {
        $sonuc = 0;
        $alan1 = "";
        $alan2 = "";
        foreach ($veriler as $anahtar => $deger) {
            $alan1 .= $anahtar . ",";
            $alan2 .= ":".$anahtar.",";
        }
        $alan1 = substr($alan1,0,strlen($alan1)-1);
        $alan2 = substr($alan2,0,strlen($alan2)-1);
        $this->baglantiAc();
        $query = $this->db->prepare("INSERT INTO ".$tablo." (".$alan1.") VALUES (".$alan2.")");
        $query->execute($veriler);
        if ( $query ) $sonuc = $this->db->lastInsertId(); else $sonuc = 0;
        $this->baglantiKapat();
        return $sonuc;
    }

    function guncelle($tablo, $veriler, $where="") {
        $sonuc = "";
        $alan = "";
        foreach ($veriler as $anahtar => $deger) $alan .= $anahtar . "= :".$anahtar.",";
        $alan = substr($alan,0,strlen($alan)-1);
        if($where!="") $where = " WHERE ".$where;
        $this->baglantiAc();
        $query = $this->db->prepare("UPDATE ".$tablo." SET ".$alan.$where);
        $update = $query->execute($veriler);
        if ( $update ) $sonuc = $query->rowCount(); else $sonuc = 0;
        $this->baglantiKapat();
        return $sonuc;
    }

    function idGuncelle($tablo, $veriler, $id) {
        $sonuc = 0;
        $alan = "";
        foreach ($veriler as $anahtar => $deger) $alan .= $anahtar . "= :".$anahtar.",";
        $alan = substr($alan,0,strlen($alan)-1);
        $veriler['id'] = (int)$id;
        $this->baglantiAc();
        $query = $this->db->prepare("UPDATE ".$tablo." SET ".$alan." WHERE id=:id");
        $update = $query->execute($veriler);
        if ( $update ) $sonuc = 1; else $sonuc = 0;
        $this->baglantiKapat();
        return $sonuc;
    }

    function sil($tablo,$where) {
    $this->baglantiAc();      
        $delete = $this->db->exec("DELETE FROM ".$tablo." WHERE ".$where);
        $this->baglantiKapat();
        return $delete;
    }

    function idSil($tablo,$id) {
        $sonuc = 0;
    $this->baglantiAc();
        $query = $this->db->prepare("DELETE FROM ".$tablo." WHERE id = :id");
        $delete = $query->execute(array('id' => (int)$id));
        if ( $delete ) $sonuc = 1; else $sonuc = 0;
        $this->baglantiKapat();
        return $sonuc;
    }

    function select($tablo,$diger="") {
        $sonuc = null;
        $this->baglantiAc();
        $query = $this->db->query("SELECT * FROM ".$tablo." ".$diger, PDO::FETCH_ASSOC);
        if ( $query ) $sonuc = $query; else $sonuc = null;
        $this->baglantiKapat();
        return $sonuc;
    }
}

Şimdi sırasıyla, class'ımız içindeki fonksiyonların ne iş yaptığına bakalım.

1) Kurucu fonksiyon:
function __construct() {      
    $this->dsn = 'mysql:host=localhost;dbname=veritabaniadi;charset=utf8';
    $this->user = 'root';
    $this->password = '1234';
}
Bu fonksiyon ile, veritabanına bağlanmak için gerekli verileri tanımlıyoruz. Örnek olarak bizim host'umuz localhost, veritabanımızın adı veritabaniadi, kullanıcı adımız root, şifremiz 1234'tür.

2) Bağlantı açıp kapatan fonksiyonlar:
private function baglantiAc() {
    try { $this->db = new PDO($this->dsn, $this->user, $this->password); }
    catch (PDOException $e) {echo 'Veritabanı bağlantısı başarısız oldu: '. $e->getMessage();}
}
private function baglantiKapat() {
    $this->db = null;
}
Bu iki fonksiyonu private olarak tanımladım çünkü dışarıdan veritabanına bağlantı işlerine karışılmasın istedim. Siz isterseniz private kısmını silebilirsiniz (veya public olarak değiştirebilirsiniz).

3) Veri ekleyen fonksiyonumuz:
function ekle($tablo, $veriler) {
    $sonuc = 0;
    $alan1 = "";
    $alan2 = "";
    foreach ($veriler as $anahtar => $deger) {
        $alan1 .= $anahtar . ",";
        $alan2 .= ":".$anahtar.",";
    }
    $alan1 = substr($alan1,0,strlen($alan1)-1);
    $alan2 = substr($alan2,0,strlen($alan2)-1);
    $this->baglantiAc();
    $query = $this->db->prepare("INSERT INTO ".$tablo." (".$alan1.") VALUES (".$alan2.")");
    $query->execute($veriler);
    if ( $query ) $sonuc = $this->db->lastInsertId(); else $sonuc = 0;
    $this->baglantiKapat();
    return $sonuc;
}
Bu fonksiyon, kendisine gönderilen diziyi parçalayıp SQL sorgusuna benzeterek veritabanına işletmektedir. (SQL Injection güvenlik açığından bizi PDO korumaktadır)
Fonksiyon verileri ekledikten sonra, son eklediği satırın ID'sini döndürmektedir. Fonksiyonun nasıl kullanılacağının örneğini aşağıda örnekler kısmında bulabilirsiniz.

4) Veri güncelleyen fonksiyonumuz:
function guncelle($tablo, $veriler, $where="") {
    $sonuc = "";
    $alan = "";
    foreach ($veriler as $anahtar => $deger) $alan .= $anahtar . "= :".$anahtar.",";
    $alan = substr($alan,0,strlen($alan)-1);
    if($where!="") $where = " WHERE ".$where;
    $this->baglantiAc();
    $query = $this->db->prepare("UPDATE ".$tablo." SET ".$alan.$where);
    $update = $query->execute($veriler);
    if ( $update ) $sonuc = $query->rowCount(); else $sonuc = 0;
    $this->baglantiKapat();
    return $sonuc;
}
Fonksiyonumuz, kendisine gönderilen diziyi ve WHERE koşullarını alarak SQL sorgusuna çeviriyor ve bunu veritabanına işletiyor. Sonuç olarak da bu işlemden kaç adet satırın etkilendiğini döndürüyor.

5) ID değerine göre verileri güncelleyen fonksiyonumuz:
function idGuncelle($tablo, $veriler, $id) {
    $sonuc = 0;
    $alan = "";
    foreach ($veriler as $anahtar => $deger) $alan .= $anahtar . "= :".$anahtar.",";
    $alan = substr($alan,0,strlen($alan)-1);
    $veriler['id'] = (int)$id;
    $this->baglantiAc();
    $query = $this->db->prepare("UPDATE ".$tablo." SET ".$alan." WHERE id=:id");
    $update = $query->execute($veriler);
    if ( $update ) $sonuc = 1; else $sonuc = 0;
    $this->baglantiKapat();
    return $sonuc;
}
Bazen (aslında çoğu zaman) ID değerine göre güncelleme yaparız. Bu durumda yeniden WHERE koşulu yazmamıza gerek kalmasın diye böyle bir fonksiyon oluşturdum. Fonksiyonumuz kendisine gönderilen dizideki verilere göre, gönderilen id'ye sahip satırda güncelleme yapıyor. Burada dikkat edilecek husus, fonksiyonun çalışması için ID sütununun adı "id" olmalıdır. Eğer siz bu sütunu "id" olarak değil de mesela "ID" veya "Id" olarak kullanıyorsanız, yukarıdaki fonksiyonda yalnızca WHERE id= kısmını kendinize göre değiştirmeniz gerekiyor. Fonksiyonumuz güncelleme işlemi tamamsa 1 (true), olmadıysa da 0 (false) döndürüyor.

6) Silen fonksiyon:
function sil($tablo,$where) {
    $this->baglantiAc();      
    $delete = $this->db->exec("DELETE FROM ".$tablo." WHERE ".$where);
    $this->baglantiKapat();
    return $delete;
}
Bu fonksiyonumuz da kendisine gönderilen where koşuluna göre silme işlemi yapar. Sonuç olarak da kaç satırın silindiğini döndürür.

7) ID değerine göre silen fonksiyon:
function idSil($tablo,$id) {
    $sonuc = 0;
    $this->baglantiAc();
    $query = $this->db->prepare("DELETE FROM ".$tablo." WHERE id = :id");
    $delete = $query->execute(array('id' => (int)$id));
    if ( $delete ) $sonuc = 1; else $sonuc = 0;
    $this->baglantiKapat();
    return $sonuc;
}
Fonksiyonumuz kendisine gönderilen ID'ye sahip satırı siliyor.

8) Nihayet, SELECT fonksiyonumuz:
function select($tablo,$diger="") {
    $sonuc = null;
    $this->baglantiAc();
    $query = $this->db->query("SELECT * FROM ".$tablo." ".$diger, PDO::FETCH_ASSOC);
    if ( $query ) $sonuc = $query; else $sonuc = null;
    $this->baglantiKapat();
    return $sonuc;
}
Bu fonksiyonumuz SELECT sorgusu işletir. Sonuçta eğer sorgudan dönen bir sonuç yoksa null döndürür. Varsa, foreach kullanarak satır satır verileri okuyabiliriz.

Şimdi gelelim örneklere:

1) Class'ımızı nasıl çağıracağız?
- Bu class'ı bir php dosyası olarak kaydedin. (veri.php gibi)
- Kurucu fonksiyondaki ayarları kendi veritabanı bağlantınıza göre değiştirin.
  (Kendi host'unuzun IP'si, hendi veritabanı adınız, kendi veritabanı kullanıcı adı ve şifreniz)
- Class'ı kullanacağınız sayfalara php dosyasını çağırın. ( include_once("veri.php"); )
Şimdi de çağırdığımız bu dosyadaki class'dan bir nesne oluşturalım.
$vt = new ebykdrms_Veritabani();
Bu komut ile, class'ımızdan $vt adında bir nesne oluşturmuş olduk. Dilediğimizce kullanabiliriz.

2) Nasıl veri ekleyeceğiz?
$sonuc = $vt->ekle("tablo1",array("isim"=>"Emre","yas"=>27);
Bu kadar. Bu satır $sonuc değişkenimize, veritabanına yeni eklenen son satırın ID değerini atayacaktır. (Mesela echo $sonuc; diyerek bu değeri okuyabilirsiniz.)

3) Nasıl güncelleyeceğiz?
$sonuc = $vt->guncelle("tablo1",array("isim"=>"Emreeee"),"yas"=27);
Bu kadar. Bu komut ile tablo1 adlı tablomuzda yas sütununda değeri 27 olan tüm satırların isim sütunu değerleri Emreeee olarak değişecektir. Bu satır $sonuc değişkenine, kaç adet satırın bu işlemden etkilendiğini atayacaktır. ( echo $sonuc." adet satırda güncelleme yapıldı"; )

4) Direkt ID'ye göre güncelleme yapmak istersek?
$sonuc = $vt->guncelle("tablo1",array("isim"=>"Emreeee"),"id"=1);
Bu şekilde bu işi yapmak mümkün. Ama ID'ye göre güncelleme yapmak sık yapılan bir işlemdir. Bu yüzden class'ımızda bunun için daha pratik bir metot bulunuyor:
$sonuc = $vt->idGuncelle("tablo1",array("isim"=>"Emreeee"),1);
Bu satır, $sonuc değişkeninin değerine eğer güncelleme yapılmışsa 1 (true), aksi halde (mesela böyle bir ID değeri yoksa) 0 (false) atar.
( echo ($sonuc) ? "Güncelleme yapıldı" : "Güncelleme yapılmadı"; )

5) Nasıl sileceğiz?
$sonuc = sil("tablo1","id=1");
$sonuc = idSil("tablo1",1);
Bu iki satır da aynı işi yapmaktadır. İlk satırda WHERE koşullarını (id=1 dediğimiz parametreyi) daha detaylı verebiliriz.
$sonuc değişkenine, bu işlemden etkilenen satır sayısı atanacaktır.
echo "Veritabanından $sonuc adet satır silindi"; )

6) Nasıl veri çekeceğiz?
$sorgu = $vt->select("tablo1","WHERE isim= 'Emre' ORDER BY yas DESC");
Bu şekilde sorgu sonucunu $sorgu değişkenine almış olduk. Peki satırlara nasıl erişeceğiz?
if($sorgu != null) foreach( $sorgu as $satir ) { echo $satir["yas"]."<br />"; }
Sonuç olarak isim değeri Emre olanları yaslarına göre büyükten küçüğe sıralayan bir sorguyla gelen satırların yas sütunu değerlerini alt alta yazdırmış olduk.


Başka bir yazıda görüşmek üzere...





8 Mart 2015 Pazar

CodeIgniter - 4 - Upload - Resim Havuzu Örneği


Yeni yayınımdan merhabalar... Bu sefer, geçen yayınımda anlattığım CodeIgniter'da Upload meselesini biraz daha genişletmek istiyorum. Bugünkü uygulamamız şöyle olacak:

Bir resim havuzumuz olacak. Buraya resim upload edebileceğiz. Buradaki resimleri görebileceğiz ve silebileceğiz. Veritabanı işlemi yapmayacağız. Bu yayını anlayabilmeniz için, CodeIgniter'ın kurulumunu ve temel mantığını biliyor olmalısınız. Bu konuda sorun yaşıyorsanız, önceki yayınlarımı okuyabilirsiniz:

1- Merhaba Dünya
2- Template Sistemi
3- Resim Upload Etmek

Yine, kolay takip edebilmeniz için, adım adım anlatacağım. Ancak, Template Sistemi başlıklı yayınımdaki kurulumu yaptığınızı varsayıyorum. Buyrun:

1) Kök klasörümüze (site.com) assets adlı bir klasör açacağız. assets'in içine images adlı bir klasör açacağız. images'in içine de resimhavuzu adlı bir klasör açacağız. Upload edeceğimiz resimleri bu klasöre kaydedeceğiz: http://localhost/site.com/assets/images/resimhavuzu/

2) Öncelikle, application/controllers/ klasörü altına resimhavuzu.php adında bir dosya açalım ve bu controller'ımızın kodlarını yazalım:

<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');

class resimhavuzu extends CI_Controller
{
    public function __construct() { parent::__construct(); }
 
    public function index()
    {      
        $data['bilgi'] = '';
        $data['uyari'] = '';

        $this->load->helper('directory');

        $map = directory_map('./public/assets/images/resimhavuzu/');

        $data['dosyalar'] = $map;

        $this->load->view('resimhavuzu_view',$data);
    }
}

Burada, resimhavuzu_view.php adlı view'a gönderilen $bilgi ve $uyari adlı değişkenler dikkatinizi çekmiştir. Eğer resim yükleme sırasında bir sorun oluşursa uyarımızı $uyari değişkenine, eğer işlem başarılı olursa da $bilgi değişkenine bilgi yükleyeceğiz. Ancak sayfa ilk yüklendiğinde (yani index() fonksiyonunda) bilgi veya uyarı görüntülenmeyecek. O yüzden, bu değişkenlere şimdilik boş bir string atadık. Şuanlık controller'ımız hazır. Buraya daha sonra tekrar döneceğiz. Ama öncelikle sayfamızı görmek için, view dosyamızı da oluşturalım...

3) application/views/ klasörü altına, resimhavuzu_view.php adında bir dosya oluşturalım ve içine şu basit formu yerleştirelim:

<!doctype html>
<html lang="tr-TR">
<head>
    <meta charset="UTF-8">
    <title>Resim Havuzu</title>
    <base href="<?=base_url()?>">
</head>
<body>
    <?=$bilgi?>
    <?=$uyari?>
    <hr />
    <form method='post' action='resimhavuzu/yukle' enctype='multipart/form-data'>
        <input type='file' name='resim' />
        <input type='submit' value='Resmi Yükle' />
    </form>
    <hr />
    <?php foreach($dosyalar as $dosya) { ?>
        <div><img src='assets/images/resimhavuzu/<?=$dosya?>' /></div>
        <div><a href='resimhavuzu/sil/<?=$dosya?>'><?=$dosya?> adlı resmi sil</a>
        <hr />
    <?php }?>
</body>
</html>

Burada, tasarımı güzelleştirecek hiçbir kod yazmadım. Siz CSS'le daha düzgün bir yapı oluşturabilirsiniz. Konumuz bu değil. Bu sayfayı oluşturduğunuzda,
http://localhost/site.com/resimhavuzu
linki ile sayfaya erişebilirsiniz. "Resmi Yükle" butonuna tıkladığınızda, url'miz şu şekle girecek:
http://localhost/site.com/resimhavuzu/yukle
Bunun anlamı: "resimhavuzu adlı controller'ın yukle() adlı fonksiyonunu çalıştır"
Ancak henüz böyle bir fonksiyon oluşturmadık. Sıra bunu oluşturmaya geldi.

4) Şimdi yeniden application/controllers/resimhavuzu.php yolundaki controller'ımızı açalım ve index() fonksiyonundan sonra, class'ımızın içinde kalacak şekilde, şu fonksiyonu da ekleyelim:

public function yukle()
{
    $data['bilgi'] = '';
    $data['uyari'] = '';

    if( !$this->input->post() ) $data['uyari'] = 'Bu sayfaya direkt erişmemelisiniz';
    else
    {
        $config['upload_path'] = 'assets/images/resimhavuzu/';
        $config['allowed_types'] = 'gif|jpg|jpeg|png';
        $config['file_name'] = 'ResimHavuzu';

        $this->load->library('upload', $config);
        $sonuc = $this->upload->do_upload('resim');

        if( !$sonuc ) $data['uyari'] = '<strong>Hata:</strong> '.$this->upload->display_errors();
        else
        {
            $yuklenen_ad = $this->upload->data()['raw_name'].$this->upload->data()['file_ext'];
            $data['bilgi'] = 'Resim, "'.$yuklenen_ad.'" adıyla, başarıyla yüklendi.';
        }

        $this->load->helper('directory');

        $data['dosyalar'] = directory_map('./public/assets/images/resimhavuzu/');

        $this->load->view('resimhavuzu_view',$data);
    }
}

Merak edenler için: Dosyaları bir dizi halinde bize sunan, CodeIgniter'ın directory_map() fonksiyonunu kullanabilmek için, directory adlı helper'ı yüklememiz gerekiyordu.

yukle() fonksiyonumuzu da yazmamızla birlikte, şuan resim upload edebiliyoruz. Şimdi de sıra, son işlemimiz olan silme işleminde... resimhavuzu_view.php dosyamızda bir link koymuştuk: Her resmin altında, resimhavuzu/sil/dosyaadı şeklinde href parametresi barındıran bir <a> tagı. Şimdi, bu linke tıklandığında olacakları işleyelim.

5) Yüklediğimiz resimlerin altındaki linklere tıkladığımızda, şöyle bir url yapımız oluyor:
http://localhost/site.com/resimhavuzu/sil/ResimHavuzu3.jpg
Anlamı: resimhavuzu controller'ındaki sil() fonksiyonuna ResimHavuzu3.jpg parametresini göndererek çalıştır.

O halde, application/controllers/resimhavuzu.php yolundaki controller'ımızı açalım ve bir parametre alan sil() fonksiyonumuzu oluşturalım. yukle() fonksiyonundan sonra, şu fonksiyonu ekleyin:

public function sil($dosya='')
{
    if( $dosya == '' ) redirect(base_url().'resimhavuzu');

    unlink('public/assets/images/resimhavuzu/'.$dosya);
    $data[bilgi'] = $dosya.' adlı resim, resim havuzundan kaldırıldı.';

    $this->load->helper('directory');
    $data['dosyalar'] = directory_map('./public/assets/images/resimhavuzu/');
    $this->load->view('resimhavuzu_view',$data);
}

İşte bu kadar. Artık resimhavuzu adlı klasörümüze resim ekleyebiliyoruz. Resimleri listeleyebiliyoruz ve silebiliyoruz. Temel haliyle bu bilgileri anlatmaya çalıştım. Bunun üzerine kendinize göre sayfayı tasarlayabilirsiniz.

Mesela resmi silmek için ilgili linke tıklandığında, pat diye silmesin de önce bir sorsun mu istiyorsunuz? O halde linkleri şu şekilde düzenleyin:

<a
    href='assets/images/resimhavuzu/<?=$dosya?>'
    onclick='return confirm('<?=$dosya?> adlı resim silinecek!');'
>
    <?=$dosya?> adlı resmi sil
</a>

Veya eğer hiç resim yoksa, resimlerin listelendiği bölüme "Hiç resim yok" yazmasını isteyebilirsiniz. Bunun için de, resimleri listeleyen foreach döngüsünü kapsayan bir if yapısı kullanabilirsiniz:

<?php if( count($dosyalar) > 0 ) { ?>
    <?php foreach($dosyalar as $dosya) { ?>
        ...
    <?php } ?>
<?php } else echo 'Hiç resim yok'; ?>

Bu gibi geliştirmeler size kalmış. Başka bir yayında görüşmek üzere. :)

5 Mart 2015 Perşembe

CodeIgniter - 3 - Resim Upload Etmek


Upload Meselesi


Buraya kadar olan yayınlarımı okuduysanız, codeigniter kurulumu hakkında bilgi sahibisiniz demektir.

Eğer okumadıysanız, şu linklerden ulaşabilirsiniz:
Yayın 1 - Merhaba Dünya
Yayın 2 - Template Sistemi

CodeIgniter'a yeni başlayanların merak ettikleri, çözüm bulmakta zorlandıkları bir konu hakkında bilgi vermek istiyorum. Nasıl resim upload ederiz? Bu iş çok basit. Ben de mümkün olduğunca, işinize yaramayacak kodları kullanmadan anlatıyorum:

Öncelikle bir view dosyası oluşturalım. application/views/ altına resimyukle_view.php adında bir dosya açalım. Burada, resim upload edeceğimiz bir formumuz olacak. Resmi POST ettiğimizde de yine aynı sayfa görüntülenecek ve "Resim başarıyla yüklendi!" mesajı verecek.

<html>
    <head>
        <title>Upload</title>
        <base href="http://localhost/site.com/" />
    </head>
    <body>
        <div><?=$bilgi?></div>
        <form action="resimyukle/yukle" method="post" enctype="multipart/form-data" >
            <div><strong>Resim Seçin:</strong> <input type="file" name="resim" /></div>
            <div><input type="submit" value="Yükle" /></div>
        </form>
    </body>
</html>

Böylelikle bir formumuz oldu. Bu view sayfası, resimyukle adlı controller'a bağlı. Bu controller'ımızı da oluşturalım. application/controllers/ klasörü içine resimyukle.php adlı bir dosya oluşturun ve şunları yazın:

<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');

class resimyukle extends CI_Controller
{
        public function __construct() { parent::__construct(); }

        public function index()
        {
            $data['bilgi'] = '';
            $this->load->view('resimyukle_view', $data);
        }

        public function yukle()
        {          
            $config['upload_path'] = 'assets/images/'; // dosyayı upload edeceğimiz klasör
            $config['allowed_types'] = 'gif|jpg|jpeg|png';                // izin verilen dosya uzantıları
            $config['file_name'] = 'Resim';                                      // dosya hangi adla kaydedilsin?

            $this->load->library('upload', $config);               // CodeIgniter'ın upload sınıfını yükledik
            $sonuc = $this->upload->do_upload('resim');     // Dosyamızı upload ediyoruz.
         
            if($sonuc) $data['bilgi'] = 'Resim başarıyla yüklendi!';
            else $data['bilgi'] = 'Resim yüklenemedi. Hata Mesajı: '.$this->upload->display_errors();

            $this->load->view('resimyukle_view', $data);
        }
}

İşe bu kadar. Ama kafanıza takılan sorular var... Yüklediğimiz resim, "Resim" adıyla kaydoluyor. Peki ya yine resim yüklemek istersek, o da mı "Resim" adıyla kaydedilecek (yani üzerine mi yazılacak)? Hayır. Eğer yeni bir resim upload edilirse, klasörde "Resim" adlı başka bir resim dosyası olduğundan, Resim1 olarak kaydedecektir. (dosya uzantısını kendisi ekliyor) Ama eğer istersek bir ayar yapıp, aynı adlı dosyanın üzerine yazılmasını da sağlayabiliriz.

Şimdi biraz detaylandıralım.

1) $config adlı bir dizi kullandık ve upload kütüphanemizi yüklerken, bu diziyi de parametre olarak belirttik. Bu dizinin ne işe yaradığını anlamışsınızdır zaten. Upload işleminin ayarlarını belirtiyoruz. Peki bu ayarlara başka nasıl parametreler verebilirdik? Buyrun, ellislab.com sitesinden aldığım tabloyu kendimce Türkçe'ye çevirdim:

ÖzellikVarsayılan DeğerTürAçıklama
upload_pathNone(string)Resmi hangi klasöre kaydedeceğiz?
Tam yol vermemiz gerekiyor.
allowed_typesNone(string)Hangi dosya uzantılarına izin vereceğiz?
Örnek: 'gif|jpg|jpeg|png'
file_nameNone(string)Eğer bu parametreye (üstteki örnekte 'Resim'  dediğimiz gibi) bir değer verirsek, dosyayı bu isimle kaydeder.
Eğer parametre vermezsek, dosyayı orijinal adıyla kaydeder.
(Uyarı: Türkçe karakterlerde sorun yaşarsınız)
overwriteFALSETRUE/FALSE
(boolean)
Adı üzerinde. Kaydedilen dosyayla aynı dosya adına sahip başka dosya varsa, üzerine yazılsın mı?
max_size0(int)KB cinsinden, izin verilen maksimum dosya boyutu.
0 verilirse, limitsiz kabul edilir.
(PHP'nin verdiği limit başka bir mevzu tabii ki...)
max_width0(int)Piksel cinsinden, izin verilen maksimum genişlik değeri.
0 verilirse, limitsiz kabul edilir.
max_height0(int)Piksel cinsinden, izin verilen maksimum yükseklik değeri.
0 verilirse, limitsiz kabul edilir.
max_filename0(int)Dosya adının uzunluğu en fazla kaç karakter olsun?
0 verilirse, limitsiz kabul edilir.
encrypt_nameFALSETRUE/FALSE
(boolean)
Hiç kullanmadım ama sanırım true yapılırsa, dosya adını rastgele şifreli bir adla değiştiriyor.
remove_spacesTRUETRUE/FALSE
(boolean)
Dosya adındaki boşluklar silinsin mi?

2) Yükleme işlemi başarılı olduğunda, yüklenen dosyayla ilgili hangi verilere ulaşabiliriz? Öyle ya, dosyamız yüklendikten sonra bu dosyayı veritabanına da yazmak isteyebiliriz. O halde, kaydedilen resim adını bir değişkene atabilmek isteriz.

$this->upload->do_upload(); fonksiyonumuzdan true dönmüşse, yani resim başarıyla kaydedilmişse, $this->upload->data() komutuyla bize sunulan dizi ile, şu bilgilere ulaşabiliriz:

$bilgiler = $this->upload->data();

$resmin_orijinal_adi = $bilgiler['orig_name'];

$yuklenen_resmin_adi = $bilgiler['raw_name'].$bilgiler['file_ext'];

$yuklenen_klasor_yolu = $bilgiler['file_path'];  //  assets/images/

$yuklenen_dosya_yolu = $bilgiler['full_path'];  //   assets/images/Resim.jpg

$resim_uzantisi = $bilgiler['file_ext'];  //   .jpg

$resim_mi = $bilgiler['is_image'];  //   1

$resim_width = $bilgiler['image_width'];  //   800

$resim_height = $bilgiler['image_height'];  //   600

$img_icin_genislik = $bilgiler['image_size_str'];  // width='800' height='200'
//Bunu da bir img tagına kolayca yazabilelim diye yapmışlar herhalde.

Umarım bir yardımım dokunmuştur. Yorumlarınızı beklerim.
 Başka yayınlarda görüşmek üzere...

4 Mart 2015 Çarşamba

CodeIgniter - 2 - Template Sistemi



CodeIgniter Framework'une giriş yaptığım ilk yayını okuduysanız, CodeIgniter'da "Merhaba Dünya" yapmışsınızdır. Şimdi, çok hızlı bir şekilde yeni bir siteye giriş yapalım. Baştan başlıyoruz...

1) CodeIgniter Framework'unu indirelim. Link: CodeIgniter.com

2) Masaüstünde yeni bir klasör açalım. Adına "site.com" diyelim. İndirdiğimiz CodeIgniter klasöründeki şu dosyaları ve klasörleri, site.com adlı klasörümüze kopyalayalım:
applicationsystemindex.php

Neden diğer klasörleri almadık? Çünkü onlar site yapmak için şuan bize lazım değiller ve ders niteliğindeler.
Klasörün adına site.com dememin nedeni tamamen keyif... Siteye ulaşmak için "localhost/site.com" yazmak istediğimden... Yani "CodeIgniter'da kök klasörlerin sonuna .com gibi bir uzantı koymamız gerekiyor" diye düşünmeyin.

3) Şimdi site.com klasörümüzü, PHP kodlarımızın çalıştığı klasörümüze taşıyalım. Sitemizi localhost üzerinde kodlayacağız.

Ben XAMPP kullandığım için, bu klasör bende C:/xampp/htdocs/site.com

4) PhpMyAdmin'i kullanarak, bir MySQL veritabanı oluşturalım. Adına da sitevt diyelim.

Tarayıcınızdaki adres çubuğuna "localhost/phpmyadmin" yazarak giriyorsunuz dememe gerek yok sanıyorum. Çünkü CodeIgniter kullanıyorsanız, bu temel mevzuları biliyorsunuz demektir.

5) CodeIgniter'da veritabanı bağlantısının kurulabilmesi için, ilgili dosyada düzenleme yapmamız gerekiyor.
application/config/database.php dosyasını açın ve şu satırları düzenleyin:

$db['default']['hostname'] = 'localhost';
$db['default']['username'] = 'root'; // MySQL kullanıcı adınız
$db['default']['password'] = '1234'; // MySQL şifreniz
$db['default']['database'] = 'sitevt'; // Veritabanı adımız

6) Sitemizin kök klasörünü de CodeIgniter'ımıza göstermemiz gerekiyor.
application/config/routes.php dosyasını açın ve şu satırı düzenleyin:

$route['default_controller'] = 'anasayfa';

Bunu yaptık, çünkü siteye girildiğinde varsayılan olarak açılacak sayfamızın anasayfa adındaki sayfamız olmasını istiyoruz.

Şimdi de kök klasörümüzü CodeIgniter'a göstermek için şu dosyayı açın:
application/config/config.php ve şu satırı düzenleyin:

$config['base_url'] = 'http://localhost/site.com/';

7) Böylelikle, 6 adımda kurulumumuzu tamamladık. CodeIgniter'ı indirip, dosyalarını kök klasörümüze taşıdık. database.phproutes.php ve config.php dosyalarında düzenleme yaptık. Bir de sitevt adında veritabanı oluşturduk. Kurulumun son adımı olarak, site.com klasörümüzün içine bir .htaccess dosyası oluşturalım ve o arama motorlarının sevdiği link yapısını kullanmamıza olanak sağlayacak şu kodları yazalım:

RewriteEngine on
RewriteCond $1 !^(index\\.php|resources|robots\\.txt)
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?/$1 [L,QSA]

Artık sayfalarımızı oluşturmaya başlayabiliriz:

application/controllers/ klasörüne anasayfa.php adlı dosyamızı oluşturuyoruz ve içine şunları yazıyoruz:

<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');

class anasayfa extends CI_Controller
{
    public function __construct() { parent::__construct(); }

    public function index()
    {    
        $this->load->view('anasayfa_view');
    }
}

Bunlar nedir?
İlk satırda bir if koşulu görüyoruz. Bu, sayfaya direkt erişimi engelleyen bir kod.

class anasayfa dediğimizde, anasayfa adında bir class oluşturmuş oluyoruz.

extends CI_Controller dediğimizde, "bu clasım, CI_Controller adlı class'ın özelliklerini de taşısın" demiş oluyoruz. Sonra { ... } arasında, class'ımızın elemanlarını yazıyoruz.

public function __construct() { ... } dediğimizde, anasayfa'ya girildiğinde ilk çalışacak kodları belirliyoruz.
Bunun nesne tabanlı programlamada farklı bir açıklaması var elbet. Ama ben CodeIgniter'ın düşünme mantığında daha temel bilgi vermeye çalışıyorum.

parent::__construct(); dediğimizde, miras alınan class'ın (CI_Controller) kurucu metodunun (function __construct() {...}) içindeki kodların çalıştırılmasını istiyoruz. (Bu işlemi şuan yapmamız gerekmiyordu aslında ama, biz bunu bir alışkanlık olarak yapalım...)

public function index() {...} dediğimizde, anasayfa'ya ulaştığımızda ve herhangi bir parametre göndermediğimizde çalışacak kodları yazıyoruz. Yani "localhost/site.com/anasayfa" ile anasayfa'mız çağırılırsa, bu fonksiyon işletilecektir. Ama örneğin "localhost/site.com/anasayfa/islem" dediğimizde, anasayfa class'ımızdaki islem() adlı fonksiyon çalışacaktır. (Evet, böyle bir fonksiyon oluşturmadık.)

$this->load->view('anasayfa_view'); dediğimizde, anasayfa'ya girildiği zaman görüntülecek view sayfasınının yüklenmesini istiyoruz.

View dosyası nedir? Bizim şuan üzerinde çalıştığımız anasayfa adlı class'ımızı controllers adlı klasöre atmıştık. Controller, siteyle ilgili programatik işlerin yapıldığı kısımdır. Buraya (mecbur kalmadıkça) HTML kodu yazmayız. View ise, HTML kodlarının bulunduğu, mümkün olduğunca az PHP kodu barındıran sayfadır. Bir controller olan anasayfa sayfası ile, bir view olan anasayfa_view sayfasının birbiriyle ilişkisi budur. Burada amaç, HTML kodlamayla PHP kodlamayı ayırmaktır. Böylece site üzerindeki kontrolümüz artar. Ekip çalışmasına daha uygun bir yapımız olur. Bu yapıya MVC mimarisi denir. (Model View Controller) "Model nedir?" diye merak ederseniz, orası da veritabanı işlemlerinin yapıldığı kısımdır diyebilirim. Onu da oluşturacağız ve adına anasayfa_model diyeceğiz. Böylece asıl işi yapan kodlarımızla veritabanı kodlarımız da birbirinden ayrılmış olacak.

Tüm bu sistemin merkezinde, bu ilk oluşturduğumuz anasayfa adlı controller vardır. Tarayıcıya "localhost/site.com/anasayfa" dediğimizde, CodeIgniter bizim için bu anasayfa adını alır. İlk iş olarak böyle bir controller var mı diye bakar. (Eğer anasayfa.php adındaki bir dosyada anasayfa adlı bir class bulamazsa, bir hata sayfasına yönlenir.) Bu controller, model'deki dosyadan veritabanı sorgularından dönen sonuçları çeker. Bunlar üzerinde kodladığımız işlemleri yapar ve görüntülemesi için view'daki dosyaya gönderir. Neyse, artık kodlarımıza dönelim...

8) anasayfa adlı controller'ımız, anasayfa_view adlı bir view dosyası çağırıyordu. Şimdi bunu oluşturalım. application/views/ klasörü altına anasayfa_view.php adlı bir dosya oluşturalım ve burada istediğimiz gibi bir HTML sayfa kodlayalım. Şimdilik sayfanıza resim koymayın ve css'inizi sayfa içinde, <style></style> tagları arasında yazın. Dosya yolu belirtmekle ilgili durumu daha sonra anlatacağım.

"Bu dosya adına _view diye yazmak mecburi mi?" diye sorabilirsiniz. View dosyaları için böyle bir mecburiyet yok. Ama daha anlaşılır olması açısından, böyle bir alışkanlık kazanmakta fayda var. (Model dosyalarında anasayfa_model.php şeklinde yapmak mecburi bir durum bu arada... Ön bilgi olsun.) Diğer bir önemli durum da, daha önce yaşadığım bir sorunla ilgili: Dosya adları küçük harfle başlamak zorunda mı? Hayır. Ama bazı durumlarda sorun oluşabiliyor. Bazen localhost'ta düzgün çalışmasına rağmen, sunucuya attığımızda çalışmayan sayfalarımız olabiliyor bu yüzden. Haliyle benim önerim, dosya adlarınızın (özellikle de varsayılan açılış sayfası olan dosyanın controller dosyasının ve class adının) küçük harfle başlamasını öneriyorum.

Şimdi anasayfa_view.php dosyamızda HTML bir sayfa tasarladığımıza göre, ilk sayfamızı tasarladık demektir. Ana Sayfa'mıza ulaşmak için tarayıcımızı açıp "localhost/site.com" yazalım ve varsayılan sayfa olarak anasayfa_view.php dosyamızın görüntülendiğini görelim. Bu sayfaya ayrıca "localhost/site.com/anasayfa" yazarak da ulaşabiliyoruz. Link yapısı, gördüğünüz gibi, .php gibi bir uzantı barındırmıyor. Bunu bize .htaccess dosyamız sağladı.

9) Şimdi bir template sistemine geçelim. Amacımız, tasarladığımız sayfadaki üst ve alt alanları (her sayfada aynı olacak alanları) başka dosyalara kaydetmek... Diyelim ki anasayfa_view.php dosyamızda şöyle bir HTML tasarım yaptınız:

<!DOCTYPE HTML>
<html lang="tr-TR">
<head>
    <meta charset="UTF-8">
    <title>Başlık</title>
    <meta name="description" content="Açıklama" />
    <meta name="keywords" content="anahtar kelimeler" >
    <meta name="reply-to" content="emrebuyukdurmus@gmail.com" />
    <meta name="designer" content="Emre BÜYÜKDURMUŞ" />
</head>
<body>

<header>    
    <nav>
        <a href="anasayfa">AnaSayfa</a>
        <a href="hakkimda">Hakkımda</a>
        <a href="referanslarim">Referanslarım</a>
        <a href="iletisim">İletişim</a>
    </nav>
</header>

<section id="content">
    Ana Sayfa'ya Merhaba
</section>

<footer>
    CodeIgniter Dersi
</footer>

AnaSayfa için yaptığınız bu tasarımda, aslında AnaSayfa'ya özel olan kısım sadece "Ana Sayfa'ya Merhaba" yazılı kısım. Gerisi, her sayfada aynı olacak kodlamalar. Peki bunu CodeIgniter'da nasıl yaparız?

application/views/ klasörü altına template adında bir klasör açın ve onun da içine header.php ve footer.php adında iki dosya oluşturun. anasayfa_view.php dosyanızdaki "Ana Sayfa'ya Merhaba" yazılı kısmın üstündeki her şeyi kesin ve header.php dosyasına yapıştırın. Altındaki kısımları da kesin ve onları da footer.php dosyasına yapıştırın. Böylece anasayfa_view.php dosyanızda yalnızca "Ana Sayfa'ya Merhaba" yazısı kalacak.

Şimdi bu header ve footer kısımlarını sayfaya çağırması için, controller'ımıza başvuruyoruz. application/controllers/anasayfa.php dosyasını tekrar açın ve index() fonksiyonunun içini şu şekilde düzenleyin:

<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');

class anasayfa extends CI_Controller
{
    public function __construct() { parent::__construct(); }

    public function index()
    {
        $this->load->view('template/header');  
        $this->load->view('anasayfa_view');
        $this->load->view('template/footer');
    }
}

Şimdi yeniden tarayıcınızı açın ve yine "localhost/site.com"a girin. Hiçbir şey değişmediyse, başardık demektir. Şimdi kafanızda bazı sorular vardır: "Ben başka dosyaları sayfama çağırmak için nasıl yol belirteceğim?", "Ben başka bir sayfayı oluşturup, ona ne yazarak link vereceğim?", "Ben controller'da yaptığım kodlamalarla oluşturduğum verileri view dosyasına nasıl iletebileceğim?"... Bunlara sırasıyla cevap verelim...

10) Başka sayfalara link vermekle ilgili (başlangıçta) bir sorun yaşayacağınızı zannetmiyorum. Ama şuanki url yapımızda şöyle bir sistem işliyor:

site.com/controller-class-adi/fonksiyon-adi/parametre

Yani url'de, site.com/anasayfa/liste/1 dediğimizde, anasayfa controller'ındaki liste fonksiyonuna parametre olarak 1 değerini göndermiş oluyoruz.

Yani url'de site.com/anasayfa/liste dediğimizde, anasayfa controller'ındaki liste adlı parametre almayan fonksiyonu çalıştırmış oluyoruz.

Ancak tarayıcımız bu / kullanımını ek iyi anlayamıyor. Yani anasayfa klasörü altındaki liste klasörü altında zannedebiliyor kendini. Haliyle o sayfada bir linke tıklamaya kalktığınızda, linki anasayfa klasörünün altında arıyor ve saçmalıyor. Bu durumun önüne geçmek için, her link'in yolunu tam olarak vermek gerekiyor. Yani mesela hakkimda sayfasına erişmek istiyorsak linkimiz şöyle olmalı:

<a href="http://localhost/site.com/hakkimda">Hakkımda</a>

Ama bu işkence! Hele ki eğer siteyi sunucuya taşırsak, bütün linkleri de buna göre değiştirmemiz gerekecek! Neyse ki biz kurulum sırasında (6.adımda) sitenin kök klasörünü CodeIgniter'a belirtmiştik. Yani yukarıdaki linki şu şekilde de yazabiliyoruz:

<a href="<?=base_url()?>hakkimda">Hakkımda</a>

base_url(), codeigniter'ın bize kök klasörün yolunu string olarak döndüren bir fonksiyonudur. Ama şunu söyleyebilirsiniz: "Ama ben her link verişimde bunu mu yazacağım? Kodlamam karmaşıklaşmaz mı?"

HTML'in bu konuda bize sunduğu diğer bir çözümü de kullanabilirsiniz. Biz de tam olarak o çözümü kullanacağız. application/view/template/header.php sayfasını açalım ve <head></head> tagları arasında bir yere şu satırı ekleyelim:

<base href="<?=base_url()?>" />

Böylelikle HTML kodlarımız tarayıcıya diyor ki, gördüğün her yolun başına base_url()'i yaz. (Bunun CodeIgniter'la ilgisi yok tabii ki. <base /> tagı bir HTML kodudur.)

Şimdi linklerimizi şu şekilde kullanmamızda hiçbir sakınca yok:
<a href="anasayfa">AnaSayfa</a>
<a href="hakkimda">Hakkımda</a>

11) Resimlerimizi, CSS dosyalarımızı, JS dosyalarımızı vs. nerede tutacağız ve nasıl yol göstereceğiz?
MVC mimarisinde genellikle şöyle bir yöntem vardır. Kök klasörde bir index.php dosyası olur. Model, View ve Controller altındaki dosyalar, url yapısına bakılarak bu index.php dosyasına include edilir. Böylelikle her şey aslında kök klasörde çalışıyormuş gibidir. Haliyle yollar da buraya göre verilmelidir. CodeIgniter da MVC mimarisini kullandığına göre, benzer bir sistemle çalışıyor. Ama biz 10.adımda yaptığımız işlem sayesinde, bunları umursamak zorunda değiliz. Herhangi bir yol belirtirken dikkat etmemiz gereken tek şey, kendimizi hep kök klasörde varsaymamızdır.

Şimdi kök klasörümüzün (site.com klasörünün) içine, assets adlı bir klasör açalım. (assets dememizin bir anlamı yok. "varlıklar" anlamına geliyor. Siz bu klasöre istediğiniz bir ad verebilirsiniz.)

Bu klasörün içine şu klasörleri oluşturalım: imagescssjs

images klasörü altına resimlerimizi, css klasörü altına stil dosyalarımızı... Sistemi anladınız. Örnek verelim. anasayfa_view.php dosyamızda bir resim yolu belirtmek istiyoruz:

<img src="assets/images/1.jpg" />

header.php dosyamızda, bir CSS dosyasını sayfamıza çağırmak istiyoruz:

<link href="assets/css/style.css" rel="stylesheet" />

footer.php dosyamızda, JS dosyalarını çağırmak istiyoruz:

<script src="assets/js/jquery-1.10.4.min.js"></script>

12) Peki controller'daki bir değişkeni view'a nasıl iletiriz? Mesela model dosyamız yardımıyla veritabanından veri çektik. Bu veri de sayfanın title, description ve keywords verilerini içeriyor. Bunları view dosyasına iletmemiz gerekir. Biz şimdi model dosyası kullanımına girmediğimiz için, sanki model'den verileri çekmişiz gibi yapıp, değişkenlere değerler vereceğiz ve bunları view dosyamızda kullanacağız. anasayfa adlı controller'ımızın dosyasını (anasayfa.php) açın ve şu değişiklikleri yapın:

<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');

class anasayfa extends CI_Controller
{
    public function __construct() { parent::__construct(); }

    public function index()
    {
        $data['title'] = 'Site Başlığı';
        $data['description'] = 'Açıklama kısmı';
        $data['keywords'] = 'anahtar kelimeler 1, anahtar kelimeler2, ...';

        $this->load->view('template/header', $data);  
        $this->load->view('anasayfa_view');
        $this->load->view('template/footer');
    }
}

$data adlı bir dizimiz var. (değişken adına data demek zorunda değiliz) Bu diziyi, göndermek istediğimiz view dosyasının olduğu fonksiyona ikinci parametre olarak ekledik. Artık header.php dosyamızda, $data dizisindeki değerleri kullanabiliriz. Hem de nasıl...

header.php'yi açın ve şu şekilde değiştirin:

<!DOCTYPE HTML>
<html lang="tr-TR">
<head>
    <meta charset="UTF-8">
    <title><?=$title?></title>
    <meta name="description" content="<?=$description?>" />
    <meta name="keywords" content="<?=$keywords?>" >
    <meta name="reply-to" content="emrebuyukdurmus@gmail.com" />
    <meta name="designer" content="Emre BÜYÜKDURMUŞ" />
</head>
<body>

<header>    
    <nav>
        <a href="anasayfa">AnaSayfa</a>
        <a href="hakkimda">Hakkımda</a>
        <a href="referanslarim">Referanslarım</a>
        <a href="iletisim">İletişim</a>
    </nav>
</header>

<section id="content">

Gördüğünüz gibi, dizilere indis olarak verdiğimiz değerler değişkene dönüştüler ve bu değişkenleri view dosyamızda dilediğimizce kullanabiliyoruz.
Bu arada yazmama gerek var mı bilmiyorum ama bilmeyen varsa katkı olur:
<?=$title?> demekle, <?php echo $title; ?> demek aynı şeydir.

13) Geldik, en merak ettiğiniz konuya. Aslında artık kafanızda bi'şeyler şekillenmiştir ama yine de bir örnek yapmakta fayda var: Varsayılan sayfadan başka bir sayfa oluşturmak!

Hemen başlayalım. Ana Sayfa için yaptığımız işlerin aynılarını şimdi Hakkımda sayfası için yapacağız.

controllers klasörüne gidin ve hakkimda.php dosyası oluşturun. Sayfaya şunları yazın:

<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');

class hakkimda extends CI_Controller
{
    public function __construct() { parent::__construct(); }

    public function index()
    {
        $data['title'] = 'Hakkımda';
        $data['description'] = 'Hakkımda açıklaması kısmı';
        $data['keywords'] = 'anahtar kelimeler 1, anahtar kelimeler2, ...';

        $this->load->view('template/header'$data);  
        $this->load->view('hakkimda_view');
        $this->load->view('template/footer');
    }
}

Şimdi de views klasörüne gidin ve hakkimda_view.php dosyası oluşturun. Sayfaya şunu yazın:

<h1>Burası Hakkımda Sayfası!</h1>

Bitti. (: Bu dersimizde CodeIgniter'a hızlıa giriş yaptık ve bir template sistemi oluşturduk. Şuan istediğiniz kadar sayfa oluşturabilirsiniz. Şimdi merak ettiğiniz iki konu vardır muhtemelen:
"Ben veritabanından nasıl veri çekebilirim ve veri ekleyebilirim?"
"Ben sayfama nasıl parametre gönderebilir ve bu parametreyi işleyebilirim?"

Veritabanı konusunda şuanlık veritabanı oluşturmak ve config/database.php dosyasını düzenlemekten başka bir şey yapmadık. Bu konuya büyük ihtimalle sıradaki yazımda değineceğim.

Diğer mevzudaysa, teorik olarak bir açıklama yapayım. Siz deneyerek öğrenin.
hakkimda.php dosyasındaki controller class'ımız içinde, index() fonksiyonundan sonra, deneme() fonksiyonu oluşturun ve bu fonksiyon, isteğe bağlı parametre alabilen bir fonksiyon olsun:
public funcion deneme($parametre = 0) { ... }

Bu fonksiyonun içine, index() fonksiyonundaki kodları aynen yazın. Yalnızca title'ın değerini, değişikliği görebilmek için değiştirin:
$data['title'] = "Sayfa ".$parametre;

Şimdi tarayıcınıza "localhost/hakkimda/deneme" yazarsanız, sayfanızın başlığının "Sayfa 0" olarak değiştiğini görürsünüz. "localhost/hakkimda/deneme/55" yazarsanız, sayfanızın başlığının "Sayfa 55" olarak değiştiğini görürsünüz...



ÖZET


Anlatım buraya kadar. Çok uzundu ve gözünüzü korkuttu mu? O halde, bu adımları teorik anlatımları çıkararak özetleyelim:

1) CodeIgniter Framework'unu indirelim. Link: CodeIgniter.com

2) Masaüstünde yeni bir klasör açalım. Adına "site.com" diyelim. İndirdiğimiz CodeIgniter klasöründeki şu dosyaları ve klasörleri, site.com adlı klasörümüze kopyalayalım:
applicationpublicsystemindex.php

3) Şimdi site.com klasörümüzü, PHP kodlarımızın çalıştığı klasörümüze taşıyalım.
Ben XAMPP kullandığım için, bu klasör bende C:/xampp/htdocs/site.com

4) PhpMyAdmin'i kullanarak, bir MySQL veritabanı oluşturalım. Adına da sitevt diyelim.

5) application/config/database.php dosyasını açın ve şu satırları düzenleyin:

$db['default']['hostname'] = 'localhost';
$db['default']['username'] = 'root'; // MySQL kullanıcı adınız
$db['default']['password'] = '1234'; // MySQL şifreniz
$db['default']['database'] = 'sitevt'; // Veritabanı adımız

6) application/config/routes.php dosyasını açın ve şu satırı düzenleyin:

$route['default_controller'] = 'anasayfa';

7) application/config/config.php dsoyasını açın ve şu satırı düzenleyin:

$config['base_url'] = 'http://localhost/site.com/';

8) site.com klasörümüzün içine bir .htaccess dosyası oluşturalım ve şu kodları yazalım:

RewriteEngine on
RewriteCond $1 !^(index\\.php|resources|robots\\.txt)
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?/$1 [L,QSA]

9) Kök klasöre (site.com) assets adlı bir klasör oluşturalım. İçine de imagescssjs adlı klasörler oluşturalım. Kullanmak istersek bulunsunlar...

9) Artık sayfalarımızı oluşturmaya başlayabiliriz: application/controllers/ klasörüne anasayfa.php adlı dosyamızı oluşturuyoruz ve içine şunları yazıyoruz:

<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');

class anasayfa extends CI_Controller
{
    public function __construct() { parent::__construct(); }

    public function index()
    {
        $data['title'] = 'AnaSayfa Başlığı';
        $data['description'] = 'Açıklama kısmı';
        $data['keywords'] = 'anahtar kelimeler 1, anahtar kelimeler2, ...';

        $this->load->view('template/header', $data);
        $this->load->view('anasayfa_view');
        $this->load->view('template/footer');
    }
}

10) application/views/ klasörüne template klasörü ekleyin. İçine de header.php dosyası oluşturup şunları yazın:

<!DOCTYPE HTML>
<html lang="tr-TR">
<head>
    <meta charset="UTF-8">
    <title><?=$title?></title>
    <meta name="description" content="<?=$description?>" />
    <meta name="keywords" content="<?=$keywords?>" >
    <meta name="reply-to" content="emrebuyukdurmus@gmail.com" />
    <meta name="designer" content="Emre BÜYÜKDURMUŞ" />
    <link href="assets/css/style.css" rel="stylesheet" />
</head>
<body>

<header>    
    <nav>
        <a href="anasayfa">AnaSayfa</a>
        <a href="hakkimda">Hakkımda</a>
        <a href="referanslarim">Referanslarım</a>
        <a href="iletisim">İletişim</a>
    </nav>
</header>

<section id="content">

11) application/views/template klasörü içine de footer.php dosyası oluşturup şşunları yazın:

</section>
<footer>Burası footer alanı</footer>
<script src="assets/js/kodumunscripti.js"></script>
</body>
</html>

12) application/views klasörüne anasayfa_view.php adlı bir dosya oluşturun ve içine şunu yazın:

<h1>Ben AnaSayfa'yım!</h1>

13) application/controllers/ içinde anasayfa.php dosyasını kopyalayıp yapıştırın ve adını da hakkimda.php yapın. Sonra bu dosyayı açıp, anasayfa yazan her yeri hakkimda olarak değiştirin.

14) application/views/ klasörü altındaki anasayfa_view.php dosyasını da kopyalayıp yapıştırın ve adını da hakkimda_view.php olarak değiştirin. İçeriğini de şu şekilde yazın:

<h1>Ben Hakkımda Sayfasıyım</h1>

Yeni yayınlarımda görüşmek üzere... Yorumlarınızı, isteklerinizi ve fark ettiğiniz hatalarla ilgili bilgilendirmelerinizi bekleriz. :) İyi günler.

Site Haritası

CodeIgniter Yayınları 1. Merhaba Dünya : CodeIgniter'da Merhaba Dünya yazısını görün... 2. Template Sistemi : CodeIgniter ile sta...