17 Şubat 2022

WordPress’te JSON kaynağından içerik oluşturmak

ile hasan

Başlık düzgün oldu mu bilemiyorum ama demek istediğim şey şu: Mesela WordPress ile oluşturduğunuz web sitenizde döviz kuru, nöbetçi eczane, ya da önemli haber başlıkları içeren bir JSON kaynağından veri almak istiyorsunuz. Bunun çok basit bir eklenti ile gayet kolay bir yöntemle yapmak mümkün. Eklenti kısmı yazının sonunda yer alacak. Aşağıda uzun uzadıya anlattığım mevzu ise bir siteden nasıl JSON veri elde edebileceğimiz üzerine bir örnek. Dolayısı ile eğer zaten elinizin altında JSON kaynağı varsa doğrudan son kısma atlayabilirsiniz.

Dün aklıma esti, yaşadığımız mevkiin haberlerini paylaşabileceğimiz WP tabanlı basit bir yerel haber sitesi oluşturdum. Siteyi sizle de paylaşırdım da, domaini .com.tr uzantısı ile “belgesiz” ön siparişle aldım. Ön siparişle alınan domainler hizmete açılmıyormuş meğer. Biliyorsunuzdur, normalde .com.tr gibi uzantısı .tr ile biten domainler .com domainler gibi her isteyene satılmıyor. Ya elinizde bir marka belgesi, ya da şirketinizin isminin almak istediğiniz domainle aynı olduğunu gösterir bir belge ibraz etmeniz gerekiyor. Gerekiyordu daha doğrusu. Artık bu sistem kalktı. İlk başvuran belge vs sunmadan .tr uzantılı domain alabilecek ancak henüz sadece ön sipariş kısmı devrede. TRABİS denen bir kurumun oluşumu tamamlanınca bu aldığımız domainleri kullanabileceğiz. O yüzden dün 4-5 saatlik bir macera ile haber sitesini sorunsuz oluşturdum ama şuan sadece kendi bilgisayarımda çalıştığı için adresini paylaşamıyorum. Görüntüsü yaklaşık şöyle:

Bu siteyi yapınca hem daha dolu görünsün hem de gerçekten bölgede yaşayanların bir ihtiyaç anında işini görsün diye siteye günlük nöbetçi eczaneleri koymak istedim. Bunun için JSON çıktı veren ücretsiz düzgün bir kaynak bulamadım. Günlük eczane bilgisi veren farklı siteler var ama doğru bilgiyi mi veriyorlar bundan emin olamadığım için -belediye sitesinde de bulamayınca- İstanbul Eczacı Odası‘nın sayfasından bu bilgiyi almaya karar verdim. İnşallah doğru kaynaktır 🙂 Şu araba mevzusundan sonra artık sitelere güvenim kalmadı. Keşke Twitter’da mavi tikli hesaplarda olduğu gibi sitelerde de mavi tık olsa.

İstanbul Eczacı Odası sitesinde mesela şu sayfada Avcılar Belediyesi sınırlarındaki nöbetçi eczaneler yanda yer alıyor. İlçeyi değiştirdikçe sağ tarafın ve haritanın sayfanın tamamından bağımsız olarak güncellenmesi bana burda bir servis olabileceği intibaını verdi. Network tabından bakınca tahmin ettiğim gibi verilerin JSON olarak geldiğini gördüm.

Aslında görülen sayfanın tamamı da, bu JSON çıktılar da hep index.php’den geliyor. İstenen parametrelere göre index.php HTML ya da JSON dönüyor.

Yani bu örneğimizde index.php’ye POST isteğinde bulunup form-data verisi olarak bu yukarıdaki görselde yer alan parametreleri girdiğinizde size güzel bir şekilde nöbetçi eczaneleri isim, telefon, adres, tarif ve hatta lokasyon (lat, long) bilgisine kadar dönüyor. Şükela!

Fakat bir iki deneme sonrasında anlıyorum ki yine görseldeki h değeri aslında bir jeton (token) gibi çalışıyor. O değer bir süre sonra eskiyor (expire oluyor) ve bu kez sayfayı yenilemek lazım olduğuna dair hata döndürüyor.

Bu işimi biraz zorlaştıracaktı ama yine de en azından JSON kaynağı orada hazır vardı. Almak için bir parametreyi elde etmek, bütün sayfayı parse etmekten daha kolay bir işti.

Bu h değerinin AJAX requestine nerden geldiğine bakmak için sayfanın source’ına bakınca (view source) <input type=”hidden” name=”a” value=”blablabla” /> şeklinde bir gizli form öğesi olduğunu gördüm. Maksat işte burdaki veriyi almaktı. Bunun için çeşitli yollar var. Bütün sayfayı file_get_contents() ile çekip içinde regular expression ile arayabilirsiniz (ki ben öyle yaptım) ya da düzgün bir wrapper kütüphanesiyle sayfa içerisinde insan gibi arama yaparsınız 🙂 Tek bir şey aradığım için regular expression hayli basit oldu.

function getCode(){

  $url="https://www.istanbuleczaciodasi.org.tr/nobetci-eczane/index.php";
  $html = file_get_contents($url);

  preg_match('/<input type="hidden"[^<]+\/>/', $html, $output);

  $a = explode(' ',str_replace(['<','/>'],'',$output[0]));
  $val = str_replace(['value="','"'],'',$a[count($a)-1]);
  return $val;
}

Eczane bilgisini JSON olarak alabilmek için Postman uygulamasında denemeler yapmıştım. Belki headerlarla oynamak gerekebilirdi ama gerekmedi. Başarılı dönen bir requestin PHP-CURL çıktısını Postman’dan aldım ve kendi fonksiyonumu yazdım.

function getJson($ilce){
  $kod = getCode();
  $curl = curl_init();

  curl_setopt_array($curl, array(
    CURLOPT_URL => 'https://www.istanbuleczaciodasi.org.tr/nobetci-eczane/index.php',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_ENCODING => '',
    CURLOPT_MAXREDIRS => 10,
    CURLOPT_TIMEOUT => 0,
    CURLOPT_FOLLOWLOCATION => true,
    CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_POSTFIELDS => array('islem' => 'get_ilce_eczane','ilce' => $ilce,'jx' => '1','h' => $kod),
    CURLOPT_HTTPHEADER => array(
      'Cookie: COOKIE_DEVICE=desktop; PHPSESSID=j4rs5psi69kub6iquf02tr88r8'
    ),
  ));

  $response = curl_exec($curl);

  curl_close($curl);
  return $response;
}

Çok basit iki fonksiyon olduğu için adresi tekrar etmişim, önemsiz parametreleri silmemişim vs bunlarla uğraşmadım. Kodun çalışır hali şu adreste mevcut.

Yukarıdaki iki fonksiyonu eczane.php dosyasına koyup WP sitesinin ana klasörüne kopyaladım. Artık bu dosyaya eczane.php?ilce=Avcılar diye istek atınca önce gidip ana kaynaktan h kodunu öğreniyor. Sonra yine aynı kaynağa h ve diğer parametrelerle başvurup bu kez JSON dönüyor. Ben de o JSON’u WP sitesinde bakın nasıl ekrana basıyorum. (Hele şükür asıl mevzuya girebildik).

JSON kaynağını WP sitede görüntüleme

Kullandığım eklentinin ismi JSON Content Importer. Kullanımı oldukça kolay. Herhangi bir sayfada, post’ta ya da bir bileşende short-code kutusu ekleyip içine örneğin şu parametreleri giriyorsunuz:

[jsoncontentimporter url="/eczane.php?ilce=Avcılar" basenode="eczaneler"]
<h3>{eczane_ad}</h3>
<b>Tel:</b>
<a href="tel:{eczane_tel}">{eczane_tel}</a>
<br>
{adres:html}
{tarif:html}
<br><br><br><br>
<a href="yandexmaps://maps.yandex.com/?ll={lat}, {lng}&amp;z=12">Yandex Navigator</a> |
<a href="https://www.google.com/maps/search/?api=1&amp;query={lat},{lng}">Google Maps</a>
<hr>
[/jsoncontentimporter]

Kısaca anlatmak gerekirse:

url parametresi malum JSON adresinin yolu. Eğer tamamen farklı bir adresten JSON veriyiyi doğrudan alabiliyorsanız buraya https://falanca.com şeklinde yazıyorsunuz. Benim örneğimde eczane.php bu işi hallettiği için onu yazdım.

Görselden anlaşıldığı üzere gelen veride farklı keyler olabiliyor. Beni ilgilendiren key “eczaneler” keyi olduğu için basenode=eczaneler yazdım. Bundan sonra yazdığım her şey eczaneler key altında gelen veri kadar tekrar edececeği için eczanenin ismini <h3>{eczane_ad}</h3> şeklinde belirttim. Çünkü JSON veride gördüldüğü üzere eczanenin ismi eczane_ad key’i ile geliyor.

Eczane tarifi ve adresi kendiliğinden HTML veri içerdiği için bunu doğdurdan {adres} veya {tarif} şeklinde basmak iyi olmuyor. Çünkü HTML kodları da ekrana kod olarak basıyor. Eklentiyi yapanlar bunu da düşünmüş :html seçeneği sunmuş. Adres ve tarifi sayfaya bastırırken {adres:html} ve {tarif:html} demek yeterli oldu.

Eczanenin telefon bilgisini tıklanınca çağrı yapacak şekilde, Lat/Long bilgisini de Yandex ve Google Maps’te açılacak şekilde linkler halinde oluşturunca sayfada pırıl pırıl göründüler.

Eklentiyi kullanırken sorun yaşarsanız debugmode=”on” yazıp problemi de ekrana bastırabilirsiniz. Ayrıca ufak dökümanında JSON verisinde iç içe diziler geldiğinde onların nasıl kullanılacağına dair örnekler de yer alıyor.

Ben çok başarılı buldum bu eklentiyi. Cache mekanizması da var. Eczaneleri orda göstermek için WP eklentisi yazmayı düşünüyordum ama bu güzel eklenti sayesinde hiç gerek kalmadı.

İnşallah yazı okuyanlar için açıklayıcı olmuştur.