Kas.15

AngularJS (1.3 / 1.5) Eğitimi: AngularJS $http Servisi ile Çalışmak

$http servisi; uzak sunuculardan veri okumak için kullanılır. Veriler ya JSON ya da Object türünde gelir. Birkaç uygulama örneği ile $http servisini kullanmayı öğrenelim…

IMDB’de Film Arama ve Detayları Gösterme Uygulaması (GET)

Örneğimizde Bootstrap ile AngularJS’yi bir arada kullanacağız. Basit bir arama çubuğu yapıp, bu arama çubuğu ile IMDB film sitesinden API servisi ile ( omdbapi ) film başlığına göre arama yapıp, film ile ilgili detayları çekip sayfayı yenilemeden AJAX mantığı ile HTML5 sayfamızda göstereceğiz.

<!DOCTYPE html>
<html>
<head>
  <!-- BOOTSTRAP -->
  <link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
  <script src="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
  <!-- ANGULARJS -->
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
  <meta charset="utf-8">
  <title>FİLM ARA</title>
</head>

<body>
  <br>
  <div class="container-fluid" ng-app="imdbUygulamasi" ng-controller="kontrol" >
    <div>
      <div class="input-group search-bar">
        <input type="text" class="form-control" ng-model="arananFilm" ng-change="guncelle()" placeholder="Aramak istediğiniz filmin tam ismini yazınız..." />
        <span class="input-group-addon "><i class="glyphicon glyphicon-search"></i></span>
      </div>
      <hr>
      <div>
        <div ng-if="sonuc.Response=='True'" >
          <p><a href="http://imdb.com/title/{{ sonuc.imdbID }}" target="_blank">
{{ sonuc.Title }}</a></p>
          <strong>IMDB Puanı:</strong>: <span class="label label-info">
{{ sonuc.imdbRating }}</span>
          <p>{{ sonuc.Released }}</p>
          <img class="img-thumbnail" width="150px" ng-src="{{ sonuc.Poster }}" />
          <p>{{ sonuc.Plot }}</p>
          <p class="label label-info">Yönetmen :</p> {{ sonuc.Director }}
          <br>
          <p class="label label-info">Oyuncular :</p> {{ sonuc.Actors }}
          <br>
          <p class="label label-info">Tür :</p> {{ sonuc.Genre }}
        </div>
      </div>
      <div ng-if="ilgiliSonuclar.Response!='False'" >
        <br>
        <p>Arama ile ilgili diğer sonuçlar:</p>
        <ul>
          <li ng-repeat="film in ilgiliSonuclar.Search" >
            <a href="#" id="{{ $index + 1 }}" ng-click="yenile(film)" >
{{ film.Title }}</a> - {{ film.Year }}
          </li>
        </ul>
      </div>
    </div>
  </div>
</body>

<script>
    angular.module('imdbUygulamasi', [])
    .controller('kontrol', function($scope, $http) {

      if ($scope.arananFilm == undefined) {
        $scope.arananFilm = "";
        veriGetir();
      }
  
      $scope.guncelle = function() {
        var aramaIslemi = setTimeout(veriGetir, 100);
      };
  
      function veriGetir() {
        $http.get("http://www.omdbapi.com/?t=" + $scope.arananFilm + "&tomatoes=true&plot=full")
          .success(function(response) {
            $scope.sonuc = response;
          });
  
        $http.get("http://www.omdbapi.com/?s=" + $scope.arananFilm )
          .success(function(response) {
            $scope.ilgiliSonuclar = response;
          });
      }
  
      $scope.yenile = function(film) {
        $scope.arananFilm = film.Title;
        $scope.guncelle();
      }
          
    });
</script>

</body>
</html>

Öncelikle kodumuzun çalışan haline bakalım, sonra da inceleyelim…

Sayfa ilk açıldığında:

Bir arama yapıldığında (Örneğin: pulp fiction):

HTML sayfamızı Bootstrap ile tasarlıyoruz. Tanımladığımız etiketlerdeki AngularJS direktiflerini iyice inceleyin ve hangi direktif ile hangi Module, hangi Controller ve hangi fonksiyonların tetiklendiğine bakın. Farklı olarak yazdığımız kodlara bakalım.

Arama çubuğundaki metin kutusuna her harf girildiğinde ng-change=”guncelle()” direktifi ile güncelle() fonksiyonunu tetikliyoruz. Bu fonksiyon içinde de aramaIslemi isli ile bir değişken tanımlayıp, bu değişken içinde de setTimeOut() metodu ile bir fonksiyonun çalışma süresini belirliyoruz. Parametre olarak verdiğimiz fonksiyon veriGetir(), süresi de 100 milisaniyedir. Yani metin kutusuna bir harf girildiğinde 0.1 saniye sonra yeni kayıtlar aranıp getirilmesi için veriGetir() fonksiyonu tetiklenecek.

veriGetir() fonksiyonuna bakalım.

$http.get metodu ile veriyi çekeceğimiz adresi tanımlıyoruz. Adresimiz http://www.omdbapi.com adresi. Burada t değeri direktif olarak arama kutusundaki ng-model=”arananFilm” ile alıyoruz.
Örneğimizde “pulp fiction” filmini aramıştık. Bu değer GET metodu ile t parametresine ekleniyor.

http://www.omdbapi.com/?t=pulp%20fiction%22&tomatoes=true&plot=full adresinden bize gelen veri aşağıdaki gibidir. Kalın olarak işaretlenmişler, Object içinden çekilebilmektedir.

{
"Title":"Pulp Fiction","Year":"1994","Rated":"R","Released":"14 Oct 1994","Runtime":"154 min","Genre":"Crime, Drama","Director":"Quentin Tarantino","Writer":"Quentin Tarantino (story), Roger Avary (story), Quentin Tarantino","Actors":"Tim Roth, Laura Lovelace, John Travolta, Samuel L. Jackson","Plot":"The lives of two mob hit men, a boxer, a gangster's wife, and a pair of diner bandits intertwine in four tales of violence and redemption.","Language":"English, Spanish, French","Country":"USA","Awards":"Won 1 Oscar. Another 53 wins & 58 nominations.","Poster":"http://ia.media-imdb.com/images/M/MV5BMTkxMTA5OTAzMl5BMl5BanBnXkFtZTgwNjA5MDc3NjE@._V1_SX300.jpg","Metascore":"94","imdbRating":"8.9","imdbVotes":"1,219,681","imdbID":"tt0110912","Type":"movie","tomatoMeter":"93","tomatoImage":"certified","tomatoRating":"9.1","tomatoReviews":"76","tomatoFresh":"71","tomatoRotten":"5","tomatoConsensus":"One of the most influential films of the 1990s, Pulp Fiction is a delirious post-modern mix of neo-noir thrills, pitch-black humor, and pop-culture touchstones.","tomatoUserMeter":"96","tomatoUserRating":"4.2","tomatoUserReviews":"1119300","DVD":"19 May 1998","BoxOffice":"N/A","Production":"Miramax Films","Website":"N/A","Response":"True"
}

Eğer veri gelirse, .succes metodu ile algılanıyor. Bu metoda da fonksiyon ataması yapılıp parametre değerine response veriliyor. response, gelen veriyi temsil eder. response değeri de doğrudan $scope içindeki sonuc değişkenine aktarılıyor.

Tekrar HTML5 etiketlerimize bakalım… div ng-if=”sonuc.Response==’True'” şeklinde bir kök div var. Bu

içinde ng-if ile karşılaştırma yapılıyor. veriGetir fonksiyonumuz ile aranan değere göre film verileri çekilmiş oluyor ve sonuc. Response değeri True sonucuna kavuşur. Arama yapılmadan önce ve arama sonucu bulunamazsa False değerinde kalır. İlk anda False konumunda olduğu için sayfalar görünmüyor. Eğer ng-if kontrolü olmazsa ilk açıldığında sayfa şu şekilde görünürdü.

Kök div’in görünmesi ile birlikte filme ait sonuçların da geldiği belli olmaktadır. {{ sonuc.parametreIsmi }} şeklinde Object nesnesinden alınan veriler sayfada gösteriliyor. Bazı yerlerde Boostrap ile birlikte, bazı yerlerde düz şekilde gösteriliyor.

Sayfanın en alt kısmında ise, aranan kelime ile ilgili diğer sonuçlar da bir liste haline getiriliyor. İlgili sonuçlar da başka bir adresten çekiliyor.

http://www.omdbapi.com/?s=” + $scope.arananFilm

Bu adresten gelen sonuç da aşağıdaki gibidir. Arama kısmında “pulp” yazdığımızda şu sonuçlar gelir. Unutmayın, yazı yazdıkça sonuçlar güncellenecektir.

{
"Search":[{"Title":"Pulp Fiction","Year":"1994","imdbID":"tt0110912","Type":"movie","Poster":"http://ia.media-imdb.com/images/M/MV5BMTkxMTA5OTAzMl5BMl5BanBnXkFtZTgwNjA5MDc3NjE@._V1_SX300.jpg"},{"Title":"Pulp","Year":"1972","imdbID":"tt0069134","Type":"movie","Poster":"http://ia.media-imdb.com/images/M/MV5BMjAzNjA2MjczMF5BMl5BanBnXkFtZTcwMjIwOTc2NA@@._V1_SX300.jpg"},{"Title":"Pulp: A Film About Life, Death and Supermarkets","Year":"2014","imdbID":"tt3265262","Type":"movie","Poster":"http://ia.media-imdb.com/images/M/MV5BMzgzNTQ0NjQyNV5BMl5BanBnXkFtZTgwMzE5NzczMjE@._V1_SX300.jpg"},{"Title":"Marvel 75 Years: From Pulp to Pop!","Year":"2014","imdbID":"tt4128102","Type":"movie","Poster":"http://ia.media-imdb.com/images/M/MV5BMTQ4MjE1NTk3NF5BMl5BanBnXkFtZTgwMTk4Mjg2NDE@._V1_SX300.jpg"},{"Title":"Pulp Fiction: The Facts","Year":"2002","imdbID":"tt0332732","Type":"movie","Poster":"N/A"},{"Title":"Pulp","Year":"2013","imdbID":"tt1737680","Type":"movie","Poster":"http://ia.media-imdb.com/images/M/MV5BMTUwMTQ3NjIxOV5BMl5BanBnXkFtZTcwODA1NjI4OA@@._V1_SX300.jpg"},{"Title":"'Pulp Fiction' on a Dime: A 10th Anniversary Retrospect","Year":"2004","imdbID":"tt0478720","Type":"movie","Poster":"N/A"},{"Title":"Pulp Sport","Year":"2003–","imdbID":"tt1400965","Type":"series","Poster":"N/A"},{"Title":"Pulp Diction","Year":"2003","imdbID":"tt0382925","Type":"movie","Poster":"N/A"},{"Title":"Pulp Friction","Year":"1994","imdbID":"tt0127181","Type":"movie","Poster":"N/A"}]
}

Buna göre listelenen filmlerin isimleri yukarıda görülmektedir. Bu verilere göre de $scope içindeki ilgiliSonuclar değişkenine response aktarılıyor. Tekrar HTML5 kodlarına baktığımızda şu döngü ile listenin oluşturulduğu görülüyor.

<li ng-repeat="film in ilgiliSonuclar.Search" >
        <a href="#" id="{{ $index + 1 }}" ng-click="yenile(film)" >{{ film.Title }}</a> - {{ film.Year }}
</li>

ng-repeat direktifi ile film in ilgiliSonuclar.Search içinden tek tek {{film.Title}} ve {{film.Year}} direktifleri ile filmin ismi ve yayınlandığı yıl değerleri alınıp liste elemanlarında gösteriliyor. Örneğin “Pulp Fiction – 2000” gibi. Bu liste elemanları da etiketleri ile hazırlanıyor. Böylece link verilebilecek. Link olarak aynı sayfada kalması için href=”#” tanımlaması yapılıyor. id tanımlamasına gerek yok, ama lazım olur diye gösterdik. $index + 1 ile sıralı bir şekilde artan sıralama yaptık. Her bir elemana da ng-click direktifi eklenmiş ve yenile() fonksiyonu film parametresi ile çalıştırılıyor.

film parametresi de ng-repeat ile sırası ile gelen Object elemanıdır. yenile() fonksiyonu incelediğimizde de $scope içinden arananFilm isimli ng-model’e, yani arama kutusundaki metin kutusuna film.Title değeri ile o linkteki filmin adı atanıyor. Ardından da guncelle() fonksiyonu tekrar çalıştırılarak tıklanan filmin içeriği çekiliyor.

AngularJS ile PHP’ye JSON Veri Göndermek (POST) ve PHP’de Parse Etmek ve PHP’de JSON Data Olarak Üretilen Veriyi Tekrar AngularJS’ye Çekmek (GET)

Başlığımız her ne kadar uzun olsa da yapacağımız iş bir form doğrulama olacaktır. Bootstrap ile basit bir üye giriş formu yapacağız ve bu form ile kullanıcı adı ve şifresini alacağız. Eğer kişi bu bilgilerden birini veya ikisini de yazmadan giriş butonuna basarsa, metin kutularının altlarında uyarı yazıları yazdıracağız.

Yapacağımız işlemde ilk olarak formdaki metin kutularının değerlerini boş olsalar dahi alıp JSON formatına çevirerek $http servisinin POST metodunu kullanarak PHP dosyamıza göndereceğiz. PHP’de de gelen bu verileri $_POST ile alıp (ilerleyen konularda PHP ile daha detaylı çalışacağız, isterseniz şimdiden bir göz atabilirsiniz) parse edeceğiz, yani ayrıştıracağız. Gelen veriler, metin kutularının doldurulması gerektiğiyle veya verilerin girildiğini belirten bir mesaj ile ilgili olacaktır. Aslında veriler tam girildiğinde bir mesaj göndermek doğru değil. Bunun yerine MySQLi ile veritabanına bağlanıp üye giriş kontrolü yaparak, “giriş yapıldı” veya “giriş yapılmadı” gibi bir mesaj göndermek veya doğrudan yetkilendirilmiş sayfaya yönlendirme yapmak daha doğru olur. Fakat şu an PHP ve MySQLi konuların işlemediğimiz için doğrudan mesaj alışverişi yapacağız.

İlk olarak VIEW alanı olan HTML5 sayfamızı kodlayalım…

<!DOCTYPE html>
<html>
<head>
  <link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
  <script src="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
  <script src="script.js"></script>
  <meta charset="utf-8">
</head>
<body ng-app="uygulama" ng-controller="kontrol">
<div class="container">
<div class="col-sm-4 col-sm-offset-4">
 <div class="page-header"><h3>Üye Giriş</h3></div>
  <form ng-submit="formGonder()">
   <div class="form-group">
        <label>Kullanıcı Adı</label>
        <input type="text" class="form-control" ng-model="kullanici.kullaniciAdi">
        <span ng-show="hataKullaniciAdi">{{hataKullaniciAdi}}</span>
    </div>
    <div class="form-group">
        <label>Şifre</label>
        <input type="password" class="form-control" ng-model="kullanici.kullaniciSifre" >
        <span ng-show="hataKullaniciSifre">{{hataKullaniciSifre}}</span>
    </div>
    <button type="submit" class="btn btn-primary">Giriş</button>
  </form>
  <div class="pull-right"><h4>{{mesaj}}</h4></div>
</div>
</div>
</body>
</html>

Sayfanın en başında Bootstrap ve AngularJS kütüphaneleri ekleniyor. Sonra da VIEWCONTROL için script.js dosyası ekleniyor. Bu dosyada AngularJS kodlarımız olacak.

HTML5 sayfamızda basit bir formumuz var. Formdan ng-control ile input değerleri alınıyor. Bu metin kutularının altında da etiketleri içinde PHP’den gelecek olan değerlere göre ng-show kontrolü yapılıyor. Aslında PHP, input içindeki veriyi alp geri gönderiyor. Eğer ng-show için bir String değeri varsa, bu True olarak yorumlanır. Ancak bir veri geri dönmemişse, yani metin kutusu boşsa bu sefer veri gelmeyeceği için False olarak yorumlanır. {{}} direktiflerinin verileri de PHP tarafından verilecek. Buralarda “Kullanıcı adını girin”, “Şifreyi girin” gibi mesajlar yazdıracağız. Giriş yapıldığında da (aslında PHP’de şu an giriş kontrolü yaptırmayacağız. Eğer iki veri de gelmişse direkt giriş yaptırmış olacağız) “Giriş yapıldı” şeklinde uyarı yazdıracağız.

Burada şuna dikkat edin. form etiketinde ng-submit=”formGonder()” şeklinde bir direktif tanımlı. Aslında formun altında bir button etiketimiz var ve Giriş butonu olarak gösterilecek. Normalde bu butona tıkladığımızda işlemler başlayacak. Düz mantıkla bakarsak normalde bu butona direktifi vermemiz gerekirdi. Fakat

etiketleri içinde type attribute değeri submit olan button nesneler, formdaki verileri POST etmek için kullanılır. Şu an POST metodu yok form tanımlamasında, ama form yine de çalıştırılacak ve aynı button nesnesi tıklanmış gibi Controller’ı tetikleyecek. Bu özel durum sadece

’larda vardır.

VIEWCONTROL için yazdığımız script.js dosyasına bakalım…

script.js

var uygulama = angular.module('uygulama', []);
uygulama.controller('kontrol', function($scope, $http) {
        $scope.kullanici = {};
        $scope.hataKullaniciAdi = '';
        $scope.hataKullaniciSifre = '';
        $scope.mesaj = '';
        $scope.formGonder = function() {
        $http({
          method  : 'POST',
          url : 'uye-giris-form-dogrulama.php',
          data : $scope.kullanici,
          headers : {'Content-Type': 'application/x-www-form-urlencoded'} 
        })
        .success(function(data) {
              $scope.hataKullaniciAdi = data.kullaniciAdi;
              $scope.hataKullaniciSifre = data.kullaniciSifre;
              $scope.mesaj = data.mesaj;
        });
    };
});

Bütün değişkenlerimizi $scope erişimi ile tanımlıyoruz, buna dikkat edin!

İlk olarak kullanici adında bir nesne tanımlıyoruz. Bu nesne bir Object gibi davranacak. Daha sonra hataKullaniciAdi, hataKullaniciSifre, mesaj isimleri ile değişkenler de tanımlayıp değerlerini ‘ ‘ ile boş yapıyoruz. Bu değişkenlere PHP’den gelen JSON verilerindeki değerler aktarılacak.

$http servisimizi tanımlıyoruz. method olarak POST veriyoruz. Böylece sayfanın URL adresi değişmeden arkaplanda input içindeki verileri göndereceğiz (Detaylı bilgi için kitapta PHP’ye POST ile Veri Gönderme veya Formlarla Çalışma konularını inceleyin). Gönderme işlemini yaparken de kullanici adlı Object nesnemizi data metodunda belirtiyoruz. Böylece diğer alt değişkenler bu Object içinde topluca paket halinde gidecek. url metodunda da hangi sayfaya veri gönderilecekse o dosyanın adresini yazıyoruz. header metoduna da atadığımız değer ile JSON dosyası gönderdiğimizi belirtmiş oluyoruz. Bu aşamada formdaki veriler Giriş butonun tıklanması ile göndermiş oluyor.

.success ile de PHP’den gelen veriler okunuyor. Bir fonksiyon tanımlanıyor ve PHP’den gelecek olan JSON dosyasındaki Object nesnesinin adı parametre olarak veriliyor. Fonksiyon içinde de data.degiskenIsmi şeklinde tek tek veriler alınıp, direktiflere gönderiliyor.

Şimdi de servis işlemi yapacak olan PHP dosyamıza bakalım…

uye-giris-form-dogrulama.php

<?php

$data = array();

$_POST = json_decode(file_get_contents('php://input'), true);

// Boş olan veriler kontrol ediliyor.
if (empty($_POST['kullaniciAdi'])){
  $data['kullaniciAdi'] = 'Kullanıcı adı gerekli';
}
if (empty($_POST['kullaniciSifre'])){
  $data['kullaniciSifre'] = 'Şifre gerekli';
}

// Eğer $data değişkeni boşsa... 
// Yani yukarıdaki iki if döngüsü de çalışmadıysa,
// Yani kullanıcı adı ve şifre girilmişse.
if (!empty($data)) {
  $data['mesaj'] = '';
// Eğer herhangi bir hata yoksa...
} else {
  $data['mesaj'] = 'Giriş yapıldı...';
  $data['kullaniciAdi'] = '';
  $data['kullaniciSifre'] = '';
}
// JSON olarak veri $data değişkeni ile geri gönderiliyor.
echo json_encode($data);

?>

Şu an PHP’yi fazla bilmediğiniz için tek tek satırları açıklayalım. İlk olarak kodlar arasında yer alan // ile başlayan açıklama satırlarını inceleyin…

$data adında bir Array, ani dizi tanımlıyoruz. Aynı Object gibi davranış gösterecek. Bu $data değişkeni, .success içinde kullanılıyordu, hatırlayın. PHP’den gelecek olan değerler bu nesne içinde topluca gelecek.
İkinci satırda POST ile gelen değerler okunuyor ve decode ediliyor.

İlk döngüde PHP’nin empty() fonksiyonu ile değerin boş olup olmadığı kontrol ediliyor. Parametre değerini de $_POST[‘deger’] şeklinde alıyor. Eğer bir değer varsa True, yoksa False verir ve if döngüsü kontrol edilir. Bunun anlamı da input’lara kullanıcı adı veya kullanıcı şifre girilmiş mi diye bakılıyor. İlkinde kullanıcı adı kontrol ediliyor. Eğer gelen veri boşsa, kişinin kullanıcı adını girmesini söyleyecek olan hata mesajını döngü içindeki değişkende tanımlıyoruz. Aynı şekilde kullanıcı şifresi için de başka bir if döngüsü kullanıyoruz.

Üçüncü if döngümüzde ters kontrol yapıyoruz. Yani !empty() şeklinde. Başında ! işaretinin olması, sonucun tersi durumunu alır. Yani sonuç False ise if döngüsü içine girilir. Burada da koşul olarak ilk iki if döngüsünde $data değişkeninde bir alt değer açıp veri atanıp atanmadığına bakılıyor. Eğer atama yapılmamışsa boş demektir. Biz doluluk oranına baktığımız için başına ! koyduk. Kullanıcı adı ve şifre girilmediği için uyarı mesajını boş gönderiyoruz.

else bloğunda da tam tersi duruma bakıyoruz. Yani kullanıcı adı ve şifre girilmişse, bunlarla ilgili uyarı kutularını ‘ ‘ ile sıfırlayıp, giriş yapıldığını belirten değişkene de “Giriş yapıldı…” değerini atıyoruz.

Elde edilen tüm sonuçları da echo ile bastırıyoruz. Yani sayfada çıktı olarak veriyoruz. Ancak yazdırma işlemini düz metin olarak değil de JSON formatına PHP’nin json_encode(); fonksiyonunu kullanarak yapıyoruz. Böylece Array değişkeni JSON’a dönüştürülüyor.

PHP dosyamız, eğer bir veri gönderilmezse aşağıdaki gibi JSON verisini üretir.

JSON formatı:

{
"kullaniciAdi":"Kullanıcı adı gerekli",
"kullaniciSifre":"
Şifre gerekli",
"mesaj":""
}

Bu formatta etiketlerinden hangisi girilirse, ona ait olan parametreler çıkarılır. Eğer ikisi de girilmiş olursa şu şekilde gelir.

JSON formatı:

{
"mesaj":"Giriş yapıldı…"
}

Formu test edelim…

Şifre girilmediğinde:

Kullanıcı adı ve şifre girilmediğinde:

Her ikisi de girildiğinde:

İçeriği paylaş:
  • facebook
  • twitter

Leave a comment

Yorum