ile

Hiç Bilmeyenler İçin Nesne Yönelimli Programlamaya Giriş-11 Bileşenler, Composer ve JSON

Bu yazı Hiç Bilmeyenler İçin Nesne Yönelimli Programlamaya Giriş-10 Sayfa Düzeni yazısının devamıdır. Önce onu okumanızı öneririm.

View story at Medium.com

Bileşen

Bir önceki yazıda View yani görünüm sınıfını her türlü şemayı kullanabilecek şekle dönüştürdük ve kullandık. Şimdi teker teker public dizini altında oluşturduğumuz index.html dosyasını parçalayalım ve tema dosyalarına dönüştürelim. Daha önceden oluşturduğumuz Template yani şablon klasöründe tek tek ismini vereceğim dosyaları oluşturun ve kodlarını içine kopyalayın.

  1. layout.php:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>

<?= $title ?>

</title>
<link rel="stylesheet" href="//fonts.googleapis.com/css?family=Roboto:300,300italic,700,700italic">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/5.0.0/normalize.min.css">
<link rel="stylesheet" href="public/css/universal.css">
</head>
<body>

<?= $content ?>

<script src="public/js/main.js"></script>
</body>
</html>

Bu şablon bizim için basit, hiçbirşeyi olmayan bir html sayfasının kodlarını tutuyor. Burada dikkat ettiyseniz, $title ve $content değişkenlerini tanımlamışız. Bu sayede aynı temayı kullanarak istediğimiz sayfa başlığını ve içeriğini tanımlayabiliriz. Diğer dosyalarda da aynı yöntemi kullanacağız.

2. header.php

<header>
<h1>

<?= $title ?>

</h1>
<nav>
<ul class="list horizontal">
<li><a href="#">About</a></li>
<li><a href="#">Terms</a></li>
<li><a href="#">Privacy</a></li>
</ul>
</nav>
</header>

Burada yine aynı $title değişkenini kullandığımıza dikkat edin. <nav> etiketiyle belirlediğimiz link listesi kısmı şimdilik o kadar önemli değil. İstersek o bölümü de değişken bi eleman haline getirebiliriz. Hatta yapalım. aynı klasör içinde nav.php isimli bir dosya oluşturalım. İçeriğini şu şekilde değiştirelim:

<nav>
<ul class="list <?= $direction ?>">

<?php foreach ($links as $link): ?>

<li><a href="<?= $link->href ?>"><?= $link->textContent ?></a></li>

<?php endforeach; ?>

</ul>
</nav>

Elemanımız links diye bir değişkene erişip onun href özelliğine ve textContent yani metin içeriğine erişmeye çalışıyor. Peki henüz böyle bir sınıf var mı? Hayır yok, çünkü daha yazmadım. Daha sonra bunun gibi elemanları da ayrı bir sınıf haline getireceğiz. Şimdilik header.php yazdığımız şekilde kalsın. Daha sonra bunun gibi elemanların sınıflarını yazmaya başladığımızda, varolan şemaları değiştirebiliriz nasılsa.

3. main.php

<main>
<aside>

<?= $aside ?>

</aside>
<section>
<h2>

<?= $title ?>

</h2>

<?= $content ?>

</section>
</main>

Burda yine bileşenin başlık ve içeriğini $title ve $content değişkenleriyle belirledik.

4. footer.php

<footer>
<p>
Dictionary App - Copyright - Midori Kocak - 2017
</p>
</footer>

Şimdilik footer yani alt bilgi kısmının içeriği sabit, daha sonra yine bu eleman için istediğimiz değişkenleri tanımlayabiliriz.

Hazırda aynı dizin içerisinde dictionary.php ve entry.php dosyaları olmalı.

Ana dizindeki app.php dosyamıza geri dönelim. Hala sınıflarımızı çağırmak için iğrenç bir spagetti kodu yazıyoruz, ancak bu sorunu da çözeceğiz.

<?php

require_once 'DictionaryInterface.php'
;
require_once 'Dictionary.php';
require_once 'EntryInterface.php';
require_once 'Entry.php';
require_once 'View.php';


try {

// İstediğimiz başlıkla sözlük sınıfından yeni bir nesne oluşturduk
$dictionary = new MidoriKocakDictionary("Nesne Yönelimli Programlama Sözlüğü");

// Kelime sınıfından yeni bir nesne oluşturduk.
$nesne = new MidoriKocakEntry('nesne', 'aklımızın dışındaki herşey');

// kelimeye başka açıklamalar ekledik.
$nesne->addValue('harika bişi');
$nesne->addValue('ingilizce object');

// Kelime sınıfından istediğimiz verilerle başka bir nesne türettik.
$şey = new MidoriKocakEntry('şey', 'ismi olmayan nesne');

// bu iki kelimeyi sözlük nesnesine ekliyoruz.
// Bu sayede sözlük kelime nesnelerine erişebiliyor.
$dictionary->addEntry($nesne);
$dictionary->addEntry($şey);

// View yani görünüm sınıfından yeni bir nesne oluşturduk.
$dictionaryView = new MidoriKocakView();

// Görünüm sınıfı içindeki data dizisine dictionary anahtarıyla sözlük değişkenimizi ekledik.
// Bu sayede, dictionary.php adlı şablon dosyasına, $dictionary yazan yerde, bu nesneye erişim
// sağlanacak. Örneğin $dictionary->getTitle() gibi.
// Aslında şablonların sınıflara bu şekilde erişmesi doğru olmayabilir, ancak şimdilik böyle bırakalım.
$dictionaryView->set('dictionary', $dictionary);

// Görünüm yani view sınıfımıza dictionary.php tema dosyasını kullanarak içeriği vermesini söyledik.
// Bu gelen içeriği dictionaryContent adlı bir değişkene atadık ki daha sonra bu veriyi kullanabilelim.
$dictionaryContent = $dictionaryView->render('dictionary');

// Elemanları oluşturmaya başladık
// Yine görünüm sınıfından yeni bir nesne türettik ve değişkenlerini belirledik.
// Burada header yani üst bilgi kısmını oluşturduk.
$header = new MidoriKocakView();
$header->set('title', 'Sözlük Uygulaması');
$headerContent = $header->render('header');

// Main elemanını oluşturduk ve değişkenlerini belirledik.
$main = new MidoriKocakView();
$main->set('aside', 'aside');
$main->set('title', 'Sözlüklerim');
$main->set('content', $dictionaryContent);
$mainContent = $main->render('main');

// footer elemanını oluşturduk.
$footer = new MidoriKocakView();
$footerContent = $footer->render('footer');

// Son olarak page yani sayfa diye bir değişken oluşturduk.

$page = new MidoriKocakView();

// Önceki elemanlarda olduğu gibi değişkenleri belirledik.
$page->set('title', 'Sözlük Uygulaması');

// Buraya dikkat, burada 3 ayrı hazırlanmış temanın içeriğini birbirine ekledik
// Ve bunu content olarak tanımladık ki, layout.php'deki $content değişkeninin
// bulunduğu yerde bu birbirine eklenmiş 3 içerik görünsün.
$page->set('content', $headerContent . $mainContent . $footerContent);

// layout.php'yi yani sayfa düzeni şablonunu kullanarak çıktı aldık.
echo $page->render('layout');

} catch (Exception | Error $e) {
echo 'Error on line ' . $e->getLine() . ' in ' . $e->getFile()
. ': <b>' . $e->getMessage();
}

Bu kodu web sunucumuzu kullanarak çalıştırdığımızda şöyle bir görüntüyle karşılaşmalıyız.


Aside kısmında sadece aside kelimesini görüntüledik. Bu bir hata değil.

Şimdi kodumuzu satır satır inceleyelim. $dictionaryContent = $dictionaryView->render(‘dictionary’); ifadesine kadar herşey önceki yazıda yaptığımız şeylerle aynı. Önceki yazıda kodlarımızda yorumlar yoktu ancak ben daha kolay anlaşılması için bunları ekledim. Bu kod bloğu içinde daha iyi olabilecek şeyler var. Bunları tek tek anlatacağım. En baştan başlayalım.

Composer aracı, Programımıza yeni bileşenler eklemek, bileşenleri yönetmek ve kolayca kullanmak

app.php dosyasını açtığımızda ilk karşılaştığımız satırlar şu şekilde. Yanlış değil de daha temiz şekilde yapılabilecek şeyler var.

<?php

require_once 'DictionaryInterface.php'
;
require_once 'Dictionary.php';
require_once 'EntryInterface.php';
require_once 'Entry.php';
require_once 'View.php';

Buradaki sorun, ihtiyaç duyduğumuz bütün sınıfları tek tek dosyanın üzerine yazmak zorunda oluşumuz. Biz 5 adet sınıf kullandığımız için bu pek sorun değil. Ancak çok kapsamlı bir yazılımda onlarca kütüphaneye ihtiyaç duyduğumuzu düşünürsek, atıyorum 64 adet dosyayı buraya tek tek yazmamız zor. Ayrıca sınıfları dosya isimleriyle tek tek çağırmak beni mutlu etmiyor. Bir de, çağırdığımız dosyaların yeni mi, eski mi, programda eriştiğimiz şekilde hata oluşturmadan çalışabileceklerinden emin olamıyoruz. Çünkü başka bir programcı girip o dosyayı darmadağın edebilir. Bu meseleyi composer denen vazgeçilmez aracı kullanarak hallediyoruz. Composer programını tıpkı telefondaki uygulamaları yüklediğiniz AppStore, PlayStore gibi programlar gibi düşünebilirsiniz. Composer sayesinde yazılımınızın ihtiyaç duyduğu kütüphane, uygulama ve sınıfları otomatik olarak ihtiyaç duyduğunuz paket isimlerini sürümleriyle beraber programınızın kök dizininde oluşturacağınız composer.json dosyasına yazacaksınız. composer install komutunu çalıştırdığınız anda composer programı, belirlediğimiz paketleri vendor dizinine göre sürüm numaralarını kullanarak indirecek, ve autoloader.php adında bir dosya oluşturacak. Biz yukarıdaki gibi bağımlılıkları tek tek yazmak yerine sadece bu autoloader.php dosyasını programımızda require komutu ile çağıracağız ve ihtiyaç duyduğumuz uygulama, sınıf ve kütüphanelere tek tanımlamayla erişebileceğiz. Ayrıca bileşenleri güncellemek istediğimizde bunları her bileşenin kodunu kaynağından indirip kopyala yapıştır yapmayla uğraşmak yerine otomatik olarak yapabileceğiz.

Composer Kurulumu

Windows ortamında çalışıyorsanız Composer aracını kurmak için en kolay yöntem https://getcomposer.org/Composer-Setup.exe dosyasını indirip çalıştırmak. Linux ve Mac ortamında çalışıyorsanız, https://getcomposer.org/installer dosyasını indirip, terminal üzerinde `php installer`diyerek çalıştırmanız gerekiyor. Program sizin ortamınıza göre gerekli düzenlemeleri yapıp kurulumu otomatik olarak gerçekleştiriyor. Daha çok ayrıntı için https://getcomposer.org/doc/00-intro.md sayfasına bakmanızı öneririm.

PHP için AppStore: Packagist

Composer ile kullanabileceğimiz diğer bir eşsiz araç ise Packagist.org. Packagist.org sitesi sayesinde istediğimiz konuyla ilgili herhangi bir kütüphane veya uygulamaya kolaylıkla erişebiliyoruz.

Packagist.org

Packagist.org sitesini, Android telefonlardaki Google Play Store veya Apple telefonlardaki AppStore uygulamalarına benzetebiliriz. Kayıtlı tüm php kütüphane, sınıf veya uygulamalarının güncel ve geçmiş sürümlerine buradan ulaşabilir, kelime bazlı arama yapabiliriz. Composer ile bir bileşeni kendi uygulamamızda kullanmak istediğimizde, composer aracı, girdiğimiz uygulamanın isminin packagist.org üzerinde kayıtlı olup olmadığına bakar, ve kayıtlı ise programımızın kök dizininde vendor adlı bir dizin oluşturur. Packagist üzerinde kayıtlı olan eklemek istediğimiz bileşeni, çoğunlukla github üzerinden indirir ve vendor dizinine kaydeder. Ayrıca vendor dizini altında autoload.php adlı bir dosya oluşturur. Biz de kendi uygulamamızı kullanırken tek tek bütün dış veya kendi yazdığımız bileşenleri require ile yukarıda yaptığımız gibi çağırmak yerine, autoload.php require komutu ile çağırarak tek bir seferde erişebiliriz.

Composer kullanımı

Şimdi composer’i nasıl kullanacağımıza bir göz atalım. Windows üzerinde CMD ile, Mac veya Linux ortamında komut satırı ile composer’i composer komutunu kullanarak çağırabildiğimizi farzediyorum.

Şu ana kadar yazdığımız sözlük programının dizini şu şekilde görünüyor olmalı:


Eğer programı şu ana kadar web sunucusunu kullanarak çalıştırabildiyseniz, bir iki dosya farklılığı olması o kadar önemli değil. Yazdığımız sözlük programının dosyalarının olduğu dizine gidelim ve o dizinde şu komutu çalıştıralım:

$> composer require phpunit/phpunit

Burada require ifadesiyle programımızın phpunit adlı bileşene ihtiyaç duyduğunu belirtiyoruz. phpunit nedir diyorsanız, programımızı test etmemize yarayan vazgeçilmez bir test aracı. Ona da bir sonraki bölümde detaylıca değineceğim. Composer vendor adlı bir dizin oluşturacak ve tek tek gerekli bileşenleri o dizine indirecek. İndirmesi, internet bağlantınızın hızına göre uzun sürebilir, telaşa kapılmayın. İşlem bittikten sonra ekrana şöyle bir görüntü gelmesi gerek. Eğer hata aldıysanız, dosya dizin izinlerinizi kontrol etmenizi öneririm. Ayrıca composer kurulumunuzda da sorun olabilir.

Görüntü bu şekildeyse sorun yok.

Şimdi sözlük programımızın olduğu dizine tekrar bakalım.

Composer’den sonra

1 adet yeni dizin ve 2 yeni dosya oluştuğunu görüyoruz. Bunları tek tek anlatayım:

Vendor dizini

Vendor dizini programımızın ihtiyaç duyduğu ve composer tarafından indirilen bileşenlerin tutulduğu dizindir. Ayrıca indirdiğimiz bileşenlerin getirdiği ek araçlar varsa onlar da bu dizinde tutulur. Ayrıca herşey indirilip bittikten sonra, autoload.php adlı, bizim tüm bileşenleri kullanıcı programımıza eklememizi sağlayan dosyayı da oluşturur composer. Şimdi vendor dizinine bir göz atalım:

Vendor dizini içeriği

Burada bin, komut satırı, terminal ya da cmd’den çağırabileceğimiz araçları içeren dizindir. Örneğin, phpunit aracı buraya yüklenmiş durumda. İhtiyaç duyduğumuzda buradan çağırabiliriz.

Composer dizininde composer’in kendi ihtiyaç duyduğu dosyalar bulunuyor. Bu dosyalar autoload.php tarafından erişiliyor. Bence fazla kurcalamaya gerek yok. Üzümünü ye bağını sorma demişler yani information hiding. Ancak composer’in nasıl çalıştığını merak ediyorsanız dosyaların içini açıp bakabilirsiniz. Açık kaynağın güzelliği de burada.

Diğer tüm dizinler, phpunit aracının ihtiyaç duyduğu ek kütüphaneler ve uygulamaları içeriyor.

Burada composer.json dosyasını inceleyeceğiz ancak json formatından bahsetmemiz gerekiyor. Eğer json formatını biliyorsanız JSON bölümünü atlayabilirsiniz.

JSON

JSON kısaltması “JavaScript Object Notation” yani Javascript Nesne Gösterimi anlamına geliyor. Javascript’te nesneleri nasıl tanımlıyorsak, json dosyalarını o şekilde biçimlendiriyoruz. Son zamanlarda JSON biçimi, internet üzerinden veri gönderip almada standart hale geldi diyebiliriz. Çünkü daha önce kullanılan xml formatı aynı veriyi tanımlamak için daha uzun dosyalara ihtiyaç duyuyor. Örnek vereceğim ama önce json’u tanımaya devam edelim.

JSON dosyaları Nesne veya Dizi şeklinde şeklinde olabilirler. Biz nesne tanımlama ile başlayalım. Buradaki JSON örneklerini data.json diye kaydedip istediğimiz json dosyasında hata almadan kullanabiliriz.

{

}

Burada boş bir JSON nesnesi oluşturduk. Eğer https://jsonformatter.curiousconcept.com/ adresine gidip bu kodu yazarsak, kodun valid json olduğunu göreceğiz. Siz de json örnekleri oluşturmak istediğinizde, kodunuzu kontrol etmek için bu aracı kullanabilirsiniz.

Json kodunu test etmek

Json nesneleri verileri “anahtar”:değer şeklinde tutarlar.

{
"name": "Deniz",
"lastname": "Mahir",
"age": 30,
"immortality": true
}

Örneğin bir burada çift tırnak kullanarak tanımladığımız kelimeler, anahtar isimlerini belirtirler ve benzersiz olmak durumundadırlar. Yani aynı kişinin birden fazla soyadı alanı olamaz. JSON aslında PHP’de Dizi/Array veri yapısına benziyor bir bakıma.

Değer kısmında kullanabileceğimiz veri tipleri ise kısıtlı. Bir JSON değeri, bir metin, bir sayı, bir nesne, bir dizi, doğru/yanlış şeklinde boolean değer ve null tipinde olabilir. Json formatında değerler javascript nesnelerinde olduğu gibi fonksiyon, tarih ve undefined yani tanımsız tipinde olamazlar. Olurlarsa, JSON okuyan program hata verir. Kodumuz patlar ağlarız. Kaynak: https://www.w3schools.com/js/js_json_syntax.asp

JSON ayrıca veriyi dizi yani array olarak kaydetmemize de imkan veriyor.

[
"Ethem",
"Abdullah",
"Ali İsmail",
"Ahmet",
"Medeni",
"Mehmet",
"Hasan",
"Berkin"
]

Burada metin tipindeki verileri dizi olarak json dosyasına kaydettik. Dikkat. Tek bir json dosyasında, tek bir nesne ya da tek bir dizi olmalı. Eğer birden fazla nesneyi tek dosyada tutmamız gerekseydi nesneleri dizinin içinde tutacaktık.

[
{
"name": "Ethem",
"age": 27
},
{
"name": "Abdullah",
"age": 22
},
{
"name": "Ali İsmail",
"age": 19
},
{
"name": "Ahmet",
"age": 22
},
{
"name": "Medeni",
"age": 18
},
{
"name": "Mehmet",
"age": 19
},
{
"name": "Hasan Ferit",
"age": 21
},
{
"name": "Berkin",
"age": 15
}
]

Ayrıca bir nesne içinde bir değeri dizi olarak da tanımlayabiliriz. Kaynak

{
"name":"John",
"age":30,
"cars":[ "Ford", "BMW", "Fiat" ]
}

Şimdi JSON’un nasıl tanımlandığını ve söz dizimi yapısını kısaca anladığımıza göre PHP’de nasıl kullanıyoruz ona bakalım. PHP’de json için kullandığımız iki fonksiyon mevcut. Bunlar json_encode() ve json_decode() yöntemleri. json_encode, bir diziyi geçerli bir JSON metnine dönüştürür. json_decode fonksiyonu ise geçerli bir json metnini, dizi ya da nesneye dönüştürür. Örneğin, $array = json_decode($jsonString, true) dediğimizde json verilerine birebir sahip olan bir php dizisi elde ederiz. Eğer true kullanmadan doğrudan $object = json_decode($jsonString) deseydik, elemanlarına $object->name gibi ifadeler kullanarak erişebileceğimiz nur topu gibi bir nesneye sahip olacaktık. Nesnelerin saklanması, metine çevirilmesi, ekrana basılması, klonlanması ve uyandırılması (metinden tekrar nesne üretilmesi) gibi konulara daha sonra detaylıca değineceğim.

Daha sonra programlar ya da sınıflar arası ya da internet üzerinde veri alışverişi yaparken JSON verisini PHP ile bol bol kullanacağız. (Anahtar kelimeler: AJAX, curl, stream, request, response, JS:promise)

JSON kısmını anladığmıza göre composer.json dosyasına geri dönelim.

composer.json

Composer.json adlı dosya, ithiyaç duyduğumuz bileşenlerin çetelesini tuttuğumuz liste aslında. Açıp bakalım.

{
"require": {
"phpunit/phpunit": "^6.0"
}
}

Burada require olarak tanımlanan değer programımızın ihtiyaç duyduğu bileşenleri listelememize yarıyor. phpunit adlı github kullanıcısının yine phpunit adlı kütüphanesine erişmek istediğimizi belirtmişiz. Değer olarak belirlediğimiz ifade ise ihtiyaç duyduğumuz paketin versiyonu. “^6.0” ifadesiyle 6 ve 7 sürümleri arasındaki herhangi bir sürüm işimizi görür demişiz. Geçmiş bir sürüme ihtiyaç duysaydık, onu da burada ifade edecektik.

Örneğin programımızı birine göndermek isteseydik, vendor klasörünü doğrudan silip sadece kendi yazdığımız kaynak dosyalarını ve composer.json dosyasını daha kısa sürede gönderebilirdik. Bu sayede gönderdiğimiz kişi composer install komutunu kullanarak bileşenleri ayrıca yükleyebilir.

composer.lock

Bu dosya composer aracı tarafından otomatik olarak oluşturulan bir dosya. Vendor dizini içine kaydedilmiş bütün bileşenlerin sürüm numaralarının kaydedildiği bir dosya. Bununla ilgili Davey Shafik şu adreste konuyu şöyle açıklamış:

composer install çalıştığında:

  • composer.lock dosyası ver mı yok mu bakılır.
  • Yoksa composer update çalıştırılır ve bir adet yaratılır.
  • composer.lock dosyası mevcutsa, lock dosyasında belirtilen sürümler yüklenir.

composer update yani güncelleme komutu çalıştığında:

  • composer.json var mı yok mu bakılır.
  • Belirlediğimiz versiyona göre bağımlı olunan bileşenlerin en son sürümleri belirlenir.
  • En son sürümler yüklenir, yani güncelleme yapılır.
  • Son olarak composer.lock en son sürümü yüklenmiş bileşenleri göstermesi için yeni sürüm numaralarıyla güncellenir.

Kaynak: https://blog.engineyard.com/2014/composer-its-all-about-the-lock-file

Bu iki dosya ve dizini de anladığımıza göre composer’in nasıl yüklendiğini ve composer ile nasıl bileşenlerin programımıza indirildiğini anlamışız demektir. Bir sonraki yazıda, app.php kodumuzu satır satır incelemeye devam edeceğiz ve işleri nasıl daha iyi yapabileceğimize bakacağız.

Bir sonraki yazı şurda:

View story at Medium.com


Projelerle PHP 7

Ben Mutlu Koçak, Bilgisayar Mühendisiyim, ZCPE Sertifikasına sahibim ve “Hiç Bilmeyenler İçin İnternet Programlamaya Giriş — PHP 7” adlı kitabın yazarıyım. Kitabım: https://www.seckin.com.tr/kitap/911934237
Özgeçmişim:
http://represent.io/mtkocak.pdf 
Websitem:
http://mynameismidori.com

Yorumla

Yorum