Kategoriler
Teknik

PHP’de MVC Mimarisi İle Basit Bir Blog Uygulaması

Daha önceden ufak bir yazı dizisiyle Yeni Başlayanlar için PHP’de MVC başlığında ufak örnekler vermiştik. Bu yazdığımız MVC mimarisini birde blog uygulaması yazılmış halde paylaşmak istedim ve bir blog uygulaması yazdım.

Bu blog uygulamasında yönetim paneli ve ziyaretçi arayüzü mevcut. Detaylara Github deposundan bakabilir ve dosyaları indirebilirsiniz.

Kategoriler
Teknik

MacOS Üzerinde Redis Kurulumu ve Ayarlamalar

Kurulum için Homebrew paket yöneticisi gerekiyor.

$ brew install redis

komutuyla Redis kurulumu gerçekleştirelim.

$ brew services start redis

komutuyla Redis’i başlatalım, eğer hata alıyorsanız services yüklü değildir. PostgreSQL kurulumunda services yüklemesinden bahsetmiştim.

Redis sunucusunu test etmek içinse şu komutu yazalım.

$ redis-cli ping
PONG

Redis Sunucusu için diğer ayarlamalar

Her macOS açılışında otomatik başlatma

$ ln -sfv /usr/local/opt/redis/*.plist ~/Library/LaunchAgents

“launchctl” aracılığıyla Redis sunucusunu başlatma

$ launchctl load ~/Library/LaunchAgents/homebrew.mxcl.redis.plist

Konfigürasyon dosyasıyla Redis sunucusunu başlatma

$ redis-server /usr/local/etc/redis.conf

Redis’i otomatik başlatıcıdan kaldırmak

$ launchctl unload ~/Library/LaunchAgents/homebrew.mxcl.redis.plist

Redis sunucusunu kaldırmak

$ brew uninstall redis
$ rm ~/Library/LaunchAgents/homebrew.mxcl.redis.plist

Redis sunucusu hakkında paket bilgisi

$ brew info redis

Kolay gelsin.

Kategoriler
Teknik

İşimizi Kolaylaştıran 10 PHP Kodlama Yöntemi

1. Üçlü (Ternary) Operatör

Üçlü operatör, if/else işlemlerimizi kolaylaştırmamızı sağlayan soru işareti (?) ve iki nokta üst üste (:) işaretiyle oluşturduğumuz bir yöntemdir. Bu yöntem işimizi hem kolaylaştırır hem de hızlı bir hale getirir. Örneğini görelim:

$sayfa = isset($_GET['sayfa']) ? $_GET['sayfa'] : 1;
// veya
echo isset($degisken) ? $degisken : 'Değişken yok!';

2. Hata Yönetimi & İstisna Yakalama

Programlama ile uğraşıyorsak hatalar bu işin olmazsa olmazlarından. Hatasız kul olmadığı gibi, geliştirme sürecinde de uygulama olmuyor. Tüm programlama dillerinde olduğu gibi PHP’de de hata yönetimi oldukça önemli.

try {
  // herhangi bir şey
} catch (Exception $e) {
  echo 'Hata var: ' . $e->getMessage();
}

3. list() Fonksiyonu

Dizi öğelerini değişkenlere atamak için list() fonksiyonu iyi bir araçtır.

$kisi = ['Yılmaz Demir', '[email protected]'];
list($isim, $eposta) = $kisi;

şuna denk düşer:

$isim = $kisi[0];
$eposta = $kisi[1];

4. compact() Fonksiyonu

Ben MVC ile yazdığım uygulamalarımda görünüm dosyasına parametre gönderirken genelde compact() fonksiyonu kullanıyorum. Bu çok daha kolay oluyor ve kod yapısını iyileştiriyor. Örneğin:

$baslik = 'Ana Sayfa';
$gonderiler = $gonderi->hepsi();

$this->render('gonderiler.php', compact('baslik', 'gonderiler'));

compact('baslik', 'gonderiler') şuna denk düşer:

array('baslik' => $baslik, 'gonderiler' => $gonderiler);

5. Tek Satırda if

Metodlarda/fonksiyonlarda eğer olağandan farklı bir durum olursa, süslü parantez kullanmadan if yapısını şu şekilde kullanıyorum:

if (!is_numeric($_GET['id']) return false;

6. Bulunduğunuz Dizini İşaretleyin

Programa herhangi bir dosya dahil ederken (require, include) veya bir dosya çağırırken dosya yoluna bulunulan dizini eklemek oldukça yararlı bir kullanım.

define('CONFIG_DIR', __DIR__.'/config');
// veya
require __DIR__.'/config.php';

7. İsimleri Kısaltarak Anlamsızlaştırmayın

Bizler makine değiliz. Kodlama esnasında ‘zamandan kazanırım’ diyerek değişken, fonksiyon, metod, sınıf vs. isimlerini anlamsızlaştırmak veya kısaltmak hem bize, hem de daha sonra kodu okumak isteyen insanlara epey sıkıntı çıkaracaktır. Örneğin:

$syf = 5; // $sayfa = 5;
$pg = 5; // $page = 5;

8. Çift Tırnak ve Tek Tırnak Farkı

PHP’de çift tırnak ve tek tırnak farklı amaçlar için kullanılır. Bazı programlama dillerinde bu fark gözetildiği gibi PHP’de de gözetilir. Çift tırnak işareti arasında değişkenleri yazdırabiliyorken, tek tırnak işareti arasında yazdıramayız. Aynı zamanda tek tırnak işaretleri arasında ASCII kontrol karakterleri kullanılamıyor. Örneklendirelim:

$isim = 'Yılmaz';
echo "Merhaba $isim"; // doğru

// şu kullanım geçersizdir:
echo 'Merhaba $isimn'; // veya echo 'merhabanisim';

// daha güvenli değişken kullanımı içinse:
echo "Merhaba sevgili {$isim}!";

9. strlen() alternatifi

Birazdan göstereceğim kullanım strlen() fonksiyonu için ufak bir alternatif olabilir. Ama türkçe karakterler için kullandığımız mb_strlen() için bir alternatif olamıyor. Şöyle ki:

$kullaniciAdi = 'demir';
echo isset($kullaniciAdi[15]) ? 'Kullanıcı adı 15 karakterden fazla olamaz' : null;
echo !isset($kullaniciAdi[2]) ? 'Kullanıcı adı 3 karakterden az olamaz' : null;

10. Fonksiyonları Tanımlarken Hatayı Önlemek

Genelde, düzenli kod yazımında ve ortak çalışma yapıldığında bu yöntem çokça kullanılır. Birçok geliştirici bunu alışkanlık haline getirmiştir, size de önerim bu şekilde kullanmanızdır. Fonksiyon tanımlamadan önce, o fonksiyonun tanımlanıp tanımlanmadığını kontrol etmek.

if (!function_exists('permalink')) {
  function permalink($string)
  {
     # kodlar...
  }
}

Umarım hepsi iş görür, iyi kodlamalar.

Kategoriler
Teknik

Model Katmanı ve Veritabanı İşlemlerini Kolaylaştırmak

İlk yazıda bahsettiğimiz gibi, model katmanı veritabanı işlemlerimizi düzene sokmak ve kolaylaştırmak adına ihtiyaç duyduğumuz bir katman. Bu yazıda yapacağımız MVC sisteminin model çekirdeğini kodlayacağız. Haydi başlayalım.

/app/core/model.php:

class model
{
    /**
     * Veritabanını nesnesini tutar
     * @var PDO
     */
    public $db;

    /**
     * Veritabanı nesnesini oluşturur
     */
    public function __construct()
    {
        $this->db = new PDO(DB_DSN, DB_USR, DB_PWD);
    }
}

En basit haliyle bu şekilde olan bir model katmanı bizim birçok ihtiyacımızı karşılayacaktır. Sınıf içerisinde $db değişkeni ekleyip, buna PDO nesnesi ile veritabanı bağlantığımızı bağladık. Görece bu yeterlidir, fakat ben işimizi daha da kolaylaştırmak istiyorum. Şimdi iki tane daha metod yazacağız. Bu metodlardan birisi fetch() ve fetchAll() metodları olacak. Bilindiği üzere bu metodlar PDO ile veri alışverişi yaptığımızda veri döndüren metodlardı. Haydi işimize koyulalım.

fetch() metodu

/**
 * Tek satırlık veri döndüren sorgu çalıştırır
 * @param string $query SQL sorgusu
 * @param array $params varsa parametreler
 * @return array
 */
public function fetch($query, array $params = [])
{
    $sth = $this->db->prepare($query);
    $sth->execute($params);
    return $sth->fetch();
}

Ne işimizi görecek bu metod? Bununla daha hızlı sorgular oluşturup, parametre ile beraber veriyi alabileceğiz. PDO’da fetch() metodu tekil veri döndürür. Bu metodun örnek kullanımı şu şekilde olabilir:

$post = $model->fetch('SELECT * FROM post WHERE id=:id', [':id' => 5]);

Bu satır, 5 numaralı ID’ye sahip olan veriyi döndürecektir. Aynı metodun bir de fetchAll() ile query() olanını ekleyelim:

/**
 * Birden fazla satır döndüren sorgu çalıştırır
 * @param string $query SQL sorgusu
 * @param array $params varsa parametreler
 * @return array
 */
public function fetchAll($query, array $params = [])
{
    $sth = $this->db->prepare($query);
    $sth->execute($params);
    return $sth->fetchAll();
}

/**
 * Sorgu çalıştırır
 * @param string $query SQL sorgusu
 * @param array $params varsa parametreler
 * @return array
 */
public function query($query, array $params = [])
{
    $sth = $this->db->prepare($query);
    return $sth->execute($params);
}

Bunu ise şu şekilde kullanabileceğiz:

$posts = $model->fetchAll('SELECT * FROM post WHERE draft=:draft', [':draft' => 'taslak_olmayan_gonderi']);

Bu kadar kolay. Şimdi, sınıfımızın son haline bakalım:

class model
{
    /**
     * Veritabanını nesnesini tutar
     * @var void
     */
    public $db;

    /**
     * Veritabanı nesnesini oluşturur
     */
    public function __construct()
    {
        $this->db = new PDO(DB_DSN, DB_USR, DB_PWD);
    }

    /**
     * Tek satırlık veri döndüren sorgu çalıştırır
     * @param string $query SQL sorgusu
     * @param array $params varsa parametreler
     * @return array
     */
    public function fetch($query, array $params = [])
    {
        $sth = $this->db->prepare($query);
        $sth->execute($params);
        return $sth->fetch();
    }

    /**
     * Birden fazla satır döndüren sorgu çalıştırır
     * @param string $query SQL sorgusu
     * @param array $params varsa parametreler
     * @return array
     */
    public function fetchAll($query, array $params = [])
    {
        $sth = $this->db->prepare($query);
        $sth->execute($params);
        return $sth->fetchAll();
    }

    /**
     * Sorgu çalıştırır
     * @param string $query SQL sorgusu
     * @param array $params varsa parametreler
     * @return array
     */
    public function query($query, array $params = [])
    {
        $sth = $this->db->prepare($query);
        return $sth->execute($params);
    }
}

Bu yazdığımız çekirdek sınıfı, yarattığımız bir model dosyasında veya bir controller metodunda şu şekilde kullanabileceğiz:

Model dosyasında:

class post extends model
{
    public function getAll()
    {
        return $this->fetchAll('SELECT * FROM post ORDER BY created DESC');
    }
}

Controller dosyasında:

class postController extends controller
{
    public function getAction($id)
    {
        $model = $this->model('post');
        $post = $model->fetch('SELECT * FROM post WHERE id=?', [$id]);
        var_dump($post);
    }
}

Artık, MVC sistemimiz hazır.


Adım adım:

  1. Yeni Başlayanlar İçin PHP’de MVC
  2. MVC Uygulaması İçin İlk Adımlar: App Sınıfı
  3. MVC’de Giriş Sayfası, Ayarlamalar ve İlk Controller
  4. Controller ve View Çekirdek Sınıflarını Oluşturmak
  5. Model Katmanı ve Veritabanı İşlemlerini Kolaylaştırmak (Şu an buradasınız)
  6. Proje/Uygulamanın Deposu
  7. Uygulamanın bitmiş halini indirin
Kategoriler
Teknik

Controller ve View Çekirdek Sınıflarını Oluşturmak

View Katmanının Çekirdek Sınıfı

/app/core/view.php:

class view
{
  /**
   * Görünüm dosyasını yorumlayan metod
   * @param string $view görünüm dosyası
   * @param array $params parametreler
   */
  public static function render($view, array $params = [])
  {
    /**
     * Eğer dosya varsa
     */
    if (file_exists($file = VDIR."/{$view}.php")) {
      /**
       * $params dizesindeki verileri extract fonksiyonu
       * ile değişken haline döndürüyoruz
       */
      extract($params);

      /**
       * Çıktı tamponlamasını başlatıyoruz
       */
      ob_start();

      /**
       * View dosyası içeriğini çağırıyoruz
       */
      require $file;

      /**
       * Çıktı tamponun içeriğini döndürüp siliyoruz
       */
      echo ob_get_clean();
    /**
     * Dosya yoksa programı sonlandır
     */
    } else {
      exit("Görünüm dosyası bulunamadı: $view");
    }
  }
}

Burada view sınıfı içerisine, statik bir render sınıfı oluşturuyoruz. Statik sınıflar, normal fonksiyonlar gibi ulaşılabilen sınıflardır. Burada bunu kullanmamızın özel bir sebebi yok.

Metod parametrelerinden aldığımız verilerle işlemlerimize devam edelim. View dosyasının varlığını kontrol ediyoruz ve varsa işlemlerimizi yapıyoruz. extract() fonksiyonu bir dizedeki değerleri alıp, değişkene çevirmemize yarıyor. Detaylarını, PHP’nin dökümantasyonunda bulabilirsiniz. ob_start() fonksiyonu ile çıktı tamponlamasını başlatıyoruz yani çıktıyı tampon belleğe alıyoruz. Akabinde view dosyamızı dahil edip ob_get_clean() fonksiyonu ile tamponladığımız çıktıyı temizleyerek yazdırıyoruz. Hepsi bu.

View katmanıyla olan işimiz yalnızca bu kadar. Şimdi gelelim Controller katmanının sınıfına. Bu katman, yaratacağımız bir Controller’a yardımcı olmak için işimize yarayacak. Yaratacağımız Controller’ı -sayfasını diyelim- genişleterek işlemlerimizi kolaylaştıracak. Haydi girişelim.

İlkin, render metodu ile view dosyası yorumlayacağız.

/app/core/controller.php:

class controller
{
  /**
   * View dosyası çağırmamıza yarayan metod
   * @param string $file dosyasını adını alır
   * @param array $params parametreleri alır
   * @return void view sınıfından render metodu döner
   */
  public function render($file, array $params = [])
  {
    return view::render($file, $params);
  }
}

Yaptığımız şey çok basit, render metodu ile, view sınıfındaki render metodunu döndürdük. Yani kısacası view yorumlamak, view sınıfının işidir dedik. Şimdi, model işlemlerine bir göz atalım.

/app/core/controller.php (devamı):

class controller
{
  /**
   * View dosyası çağırmamıza yarayan metod
   * @param string $file dosyasını adını alır
   * @param array $params parametreleri alır
   * @return void view sınıfından render metodu döner
   */
  public function render($file, array $params = [])
  {
    return view::render($file, $params);
  }

  /**
   * Model dizininden model dosyası çağırır
   * @param string $model model dosyası adı
   * @return void model sınıfı
   */
  public function model($model)
  {
    // Eğer model dosyası varsa çağırıp döndürelim
    if (file_exists($file = MDIR."/{$model}.php")) {
      require_once $file;
      // Eğer model sınıfı tanımlıysa model sınıfını döndür
      if (class_exists($model)) {
        return new $model;
      // Model sınıfı tanımlı değilse programı durdur
      } else {
        exit("Model dosyasında sınıf tanımlı değil: $model");
      }
    // Eğer sınıf yoksa, hata döndürelim
    } else {
      exit("Model dosyası bulunamadı: {$model}.php");
    }
  }

  /**
   * Yönlendirme yapar
   * @param string $path yol
   */
  public function redirect($path)
  {
    header("Location: {$path}");
  }

  /**
   * URL oluşturur
   * Bu sınıfı görünüm dosyası içinde rahat kullanmak için statik yaptık
   * @return string URL
   */
  public static function url()
  {
    return URL.'/?url='.implode('/', func_get_args());
  }
}

Sınıfa üç tane yeni metod ekledik. Bunlardan ilki olan model metoduna göz atalım. Bu metod, model dosyası çağırmak için işimize yarayacak olan metodumuz olacak. Böylelikle Controller ile model ilişkisini tamamlamış olacağız.

Evvela file_exists() fonksiyonu ile dosya varlığı kontrolü yapıyoruz ve varsa require_once() ile sayfaya dahil ediyoruz. require_once() kullanmamın sebebi, olası durumlarda sayfaya iki kere dahil edilmesini engellemek. Sonrasında sınıfın varlığını kontrol ediyoruz ve model metodunu bu sınıf olarak döndürüyoruz (new $model).

Gelelim redirect() metoduna, bu metod ihtiyaç halinde yönlendirmemizi yapıyor. URL’ye göre header’ı ayarlayıp, yönlendirmeye yardımcı oluyor. url() methodu ise URL dizgesi üretmemize yardımcı oluyor.

Olanlar bunlar. Dilersek eklemeleri kendi isteğimize göre yapabiliriz. Artık bir controller oluştururken, bu sınıfı genişleteceğiz (extend). Yani şöyle:

class blogController extends controller
{
  public function indexAction()
  {
    $blog_model = $this->model('blog'); // app/models/blog.php çağırır
    $this->render('blog/post.php'); // app/views/blog/post.php çağırır
    }
}

Kolay gelsin.


Adım adım:

  1. Yeni Başlayanlar İçin PHP’de MVC
  2. MVC Uygulaması İçin İlk Adımlar: App Sınıfı
  3. MVC’de Giriş Sayfası, Ayarlamalar ve İlk Controller
  4. Controller ve View Çekirdek Sınıflarını Oluşturmak (Şu an buradasınız)
  5. Model Katmanı ve Veritabanı İşlemlerini Kolaylaştırmak
  6. Proje/Uygulamanın Deposu
  7. Uygulamanın bitmiş halini indirin