Bu bölümde, HTTP temel kavramlarını bir bir el alarak bu kavramların Symfony için nasıl uygulandığını ele alacağız.
HTTP (Hypertext Transfer Protocol), iki makinenin birbirleriyle iletişim kurmasını sağlayan bir metin dilidir. Bilgisayarınızdaki bir web tarayıcı ile bir siteye erişmek istediğinizde, aşağıdaki işlemler gerçekleşir:
Kullanılan gerçek dil oldukça basittir. HTTP, bu basit metin tabanlı dili tanımlamak için kullanılan terimdir. Sunucunuzun amacı her zaman metin isteklerini anlamak ve metin yanıtlarını iade etmektir. Symfony, tabandan yukarıya doğru bu gerçek esasına göre oluşturulmuştur.
Web üzerindeki her iletişim bir istekle (Request) başlar. İstek, HTTP olarak bilinen özel bir formatta bir istemci (ör. web tarayıcısı, akıllı telefon uygulaması vb.) tarafından oluşturulan bir metin mesajıdır. İstemci bu isteği bir sunucuya gönderir ve yanıt (Response) bekler.
Bir tarayıcı ile web sunucusu arasındaki etkileşimin (Request) ilk kısmına (istek) bir göz atalım:
HTTP dilinde, bu HTTP isteği aslında şu şekildedir:
GET / HTTP/1.1 Host: www.bilgigunlugum.net Accept: text/html User-Agent: Mozilla/5.0 (Windows)
Bu basit mesaj, istemcinin tam olarak hangi kaynağı talep ettiği hakkındaki gerekli her türlü bilgiyi iletir. HTTP isteğinin ilk satırı en önemlisidir, çünkü iki önemli şey içerir: HTTP metodu (GET) ve URI (/).
URI (ör. /, /contact, vb.), istemcinin talep ettiği kaynağı tanımlayan benzersiz adres veya konumdur. HTTP metodları (ör. GET), müşterinin kaynakla ne yapmak istediğini tanımlar. HTTP metodları (ayrıca fiiller olarak da bilinir), istemcinin kaynak üzerinde işlem yapabileceği birkaç yaygın yolu tanımlar. En yaygın HTTP yöntemleri şunlardır:
GET: Sunucudan kaynağı alır (ör. bir sayfayı ziyaret ederken)
POST: Sunucuda bir kaynak oluşturur (ör. bir form gönderirken)
PUT/PATCH: Sunucudaki kaynağı günceller (API'ler tarafından kullanılır)
DELETE: Sunucudaki kaynağı siler (API'ler tarafından kullanılır)
Bu düşünceyle, belirli bir blog girişini silmek için HTTP isteğinin nasıl göründüğünü hayal edebilirsiniz, örneğin:
DELETE /blog/15 HTTP/1.1
Aslında, HTTP tarafından tanımlanan dokuz HTTP yöntemi olmasına rağmen, bunların çoğu yaygın olarak kullanılmamaktadır. Gerçekte, birçok modern tarayıcı yalnızca POST ve GET'i HTML formlarında desteklemektedir. Bununla birlikte, diğerleri sadece XMLHttpRequest işlemlerinde desteklenmektedir.
İlk satıra ek olarak, bir HTTP isteği daima, istek başlıkları olarak adlandırılan diğer bilgi satırlarını içerir. Başlıklar, istek yapılan kaynağın sunucusu (Host), istemcinin kabul ettiği yanıt biçimlerini (Accept) ve istemcinin isteği yapmak için kullandığı (User-Agent) uygulama gibi bilgileri içeren geniş bir bilgi yelpazesi sağlayabilir.
Bir sunucu isteği aldığında, istemcinin hangi kaynağa (URI ile) ihtiyaç duyduğu ve istemcinin bu kaynakla (metod ile) ne yapmak istediğini bilir. Örneğin, GET isteğinde sunucu kaynağı hazırlar ve bir HTTP yanıtında döndürür.
HTTP'ye çevrildiğinde, tarayıcıya geri gönderilen yanıt şöyle görünecektir:
HTTP/1.1 200 OK Date: Mon, 24 Apr 2017 10:47:13 GMT Server: Apache Content-Type: text/html <html> <!-- ... HTML for the bilgigunlugum.net --> <html>
HTTP yanıtı, yanıtla ilgili diğer bilgilerin yanı sıra istenen kaynağa (bu durumda HTML içeriği) ait bilgileri de içerir. İlk satır özellikle önemlidir ve HTTP yanıt durumu kodunu içerir (bu durumda 200).
Durum kodu, isteğin genel sonucunu istemciye geri bildirir. Bu kod, isteğin başarılı veya hatalı sonuçlarına bağlı olarak farklı bilgiler içerebilir.
İstek gibi, bir HTTP yanıtı HTTP başlıkları olarak bilinen ek bilgi parçaları içerir. Aynı kaynağın içeriği, HTML, XML veya JSON gibi birden çok farklı formatta döndürülebilir ve Content-Type başlığı, istemciye hangi formatta geri döndürüldüğünü bildirmek için text / html gibi İnternet Medya Türleri kullanır.
Bu istek-yanıt döngüsü, web üzerindeki tüm iletişimi sağlayan temel işlemdir. Bu süreç önemli ve güçlü olduğu kadar aynı zamanda basittir.
Temel çalışma prensibi: Kullandığınız dilden bağımsız olarak, oluşturduğunuz uygulamanın türü (web, mobil, JSON API) veya takip ettiğiniz geliştirme felsefesi, bir uygulamanın nihai amacı daima her isteği anlamak ve uygun yanıtı oluşturmak ve istemciye döndürmektir.
PHP ile çalışırken, bir isteğe işlem yaparken ve yanıt oluştururken, PHP sizi tüm süreçten biraz soyutlar:
$uri = $_SERVER['REQUEST_URI'];
$foo = $_GET['foo'];
header('Content-Type: text/html');
echo 'The URI requested is: '.$uri;
echo 'The value of the "foo" parameter is: '.$foo;
Biraz garip gelsede, bu küçük uygulama aslında bilgiyi HTTP isteğinden alır ve bir HTTP yanıtı oluşturmak için kullanır. PHP, ham HTTP istek mesajını ayrıştırmak yerine, isteğin tüm bilgilerini içeren süper global değişkenleri ($_SERVER ve $_GET gibi) hazırlar. Benzer şekilde, HTTP ile biçimlendirilmiş metin yanıtını döndürmek yerine, yanıt başlıkları oluşturmak ve yanıt mesajının içerik kısmını oluşturacak olan gerçek içeriği basmak için PHP başlık bilgisi fonksiyonunu kullanabilirsiniz. PHP gerçek bir HTTP yanıtı yaratacak ve istemciye geri döndürecektir:
HTTP/1.1 200 OK Date: Mon, 24 Apr 2017 10:53:13 GMT Server: Apache/2.2.17 (Unix) Content-Type: text/html The URI requested is: /testing?foo=symfony The value of the "foo" parameter is: symfony
Symfony, HTTP istek ve yanıtına daha kolay işlem yapmanıza olanak sağlayan iki sınıf ile PHP yöntemine bir alternatif sağlar.
İstek sınıfı, HTTP istek mesajının nesneye dayalı bir temsilidir. Bu sınıfla birlikte, tüm istek bilgilerinizi elinizin altında bulundurabilirsiniz:
use Symfony\Component\HttpFoundation\Request;
$request = Request::createFromGlobals();
// istek yapılan URI (örneğin, /about) parametresiz olarak
$request->getPathInfo();
// $_GET ve $_POST değişken değerlerini alma
$request->query->get('id');
$request->request->get('category', 'default category');
// $_SERVER değişken değerlerini alma
$request->server->get('HTTP_HOST');
// "attachment" olarak tanımlanmış yüklenen dosyanın bir kopyasını alma
$request->files->get('attachment');
// Bir $_COOKIE değeri alma
$request->cookies->get('PHPSESSID');
// Bir HTTP request başlığı alma, normal, küçük karakterlerle
$request->headers->get('host');
$request->headers->get('content_type');
$request->getMethod(); // ör. GET, POST, PUT, DELETE veya HEAD
$request->getLanguages(); // İstemcinin kabul edeceği dilleri içeren dizi
İlave bir avantaj olarak, istek sınıfı, arka planda sizin düşünmenizi gerektirmeyen çok iş yapar.
Symfony ayrıca Response sınıfı ile HTTP yanıt mesajının basit bir PHP gösterimini sağlar. Bu, uygulamanızın istemciye geri gönderilmesi gereken yanıtı oluşturmak için nesneye dayalı bir arabirim kullanmasını sağlar:
use Symfony\Component\HttpFoundation\Request;
$request = Request::createFromGlobals();
// istek yapılan URI (örneğin, /about) parametresiz olarak
$request->getPathInfo();
// $_GET ve $_POST değişken değerlerini alma
$request->query->get('id');
$request->request->get('category', 'default category');
// $_SERVER değişken değerlerini alma
$request->server->get('HTTP_HOST');
// "attachment" olarak tanımlanmış yüklenen dosyanın bir kopyasını alma
$request->files->get('attachment');
// Bir $_COOKIE değeri alma
$request->cookies->get('PHPSESSID');
// Bir HTTP request başlığı alma, normal, küçük karakterlerle
$request->headers->get('host');
$request->headers->get('content_type');
$request->getMethod(); // ör. GET, POST, PUT, DELETE veya HEAD
$request->getLanguages(); // İstemcinin kabul edeceği dilleri içeren dizi
JSON geri gönderilmesi, yönlendirme, akış dosyası indirme işlemlerine ve daha fazlasına yardımcı olacak birkaç yanıt alt sınıfı da vardır.
Request(İstek) ve Response(Yanıt) sınıfları, herhangi bir PHP projesinde kullanabileceğiniz, symfony/http-foundation adı verilen bağımsız bir bileşenin parçasıdır. Bu aynı zamanda oturumları yönetme, dosya yüklemeleri ve daha fazlası için sınıflar içerir.
Symfony başka bir şey önermezse, istek bilgisine kolayca erişmek için bir araç seti ve yanıt oluşturmak için nesne yönelimli bir arabirim olmalıdır. Symfony'deki pek çok güçlü özelliği öğrenirken bile, uygulamanızın amacının daima bir isteği yorumlamak ve uygulama mantığınıza dayalı uygun yanıtı yaratmak olduğunu unutmayın.
HTTP'de olduğu gibi, İstek ve Yanıt nesnelerini kullanmak oldukça basittir. Bir uygulama oluşturmanın zor kısmı arasında olanı yazmaktır. Başka bir deyişle, gerçek çalışma, istek bilgilerini yorumlayan ve cevabı oluşturan kodu yazmayı içerir.
Uygulamanız büyük olasılıkla e-posta gönderme, form gönderilerini işleme, işleri bir veritabanına kaydetme, HTML sayfaları oluşturma ve içerik güvenliğini koruma gibi birçok işlemi yapar. Bütün bunları nasıl idare edersiniz ve hala kodunuzu organize ve bakımlı tutabilir misiniz? Symfony bu sorunlarda size yardımcı olmak için oluşturulmuştur.
Geleneksel olarak, uygulamalar, bir sitenin her "sayfası" sı için kendi fiziksel dosyası (ör. index.php, contact.php vb.) olacak şekilde oluşturulmuştur.
Bu yaklaşımda URL'lerin esnekliği de dahil olmak üzere çeşitli sorunlar bulunmaktadır (blog.php dosyasını news.php dosyasına tüm linklerinizi kırmadan değiştirmek isterseniz) ve güvenlik, veritabanı bağlantıları ve sitenin görünümünün tutarlı kalmasını sağlayan her dosyanın bazı temel dosyalar kümesini manuel olarak içermesi gerektiğidir.
Daha iyi bir çözüm ise, uygulamanıza gelen her isteği işleyen tek bir PHP dosyasından oluşan bir ön denetleyiciyi kullanmaktır. Örneğin aşağıdaki her bir istek index.php dosyasını çalıştırır:
/index.php index.php'yi çalıştırır. /index.php/contact index.php'yi çalıştırır. /index.php/blog index.php'yi çalıştırır.
Web sunucusu yapılandırmanızdaki yeniden yazma kurallarını kullanarak, index.php ifadesini kullanmadan temiz URL'ler oluşturabilirsiniz.
Artık her istek aynı şekilde işlem görmektedir. Farklı PHP dosyalarını çalıştıran farklı URL değerleri yerine, her zaman ön denetleyici çalıştırılır ve farklı URL'lerin uygulamanızın farklı bölümlerine yönlendirilmesi dahili olarak yapılır.
Çok basit bir ön denetleyici şu şekildedir:
// index.php
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
$request = Request::createFromGlobals();
$path = $request->getPathInfo(); // istek yapılan URI yolu
if (in_array($path, array('', '/'))) {
$response = new Response('Welcome to the homepage.');
} elseif ('/contact' === $path) {
$response = new Response('Contact us');
} else {
$response = new Response('Page not found.', Response::HTTP_NOT_FOUND);
}
$response->send();
Buradaki ön denetleyici iyi bir durumda olmasına rağmen, hala tekrar edilen bir çok işlem vardır. Symfony bu noktada devreye girer.
Bir Symfony uygulaması da bir ön denetleyici dosyası kullanır. Ancak, gelen her isteği ele almak ve ne yapılacağını belirlemekten Symfony sorumludur:
Gelen talepler Routing bileşeni tarafından yorumlanır ve Yanıt nesnelerini döndüren PHP fonksiyonlarına aktarılır.