conkal / yoksis-rest-client
YÖKSİS (Yükseköğretim Bilgi Sistemi) OBS REST servisleri için PHP istemcisi
Requires
- php: >=7.2.5
- ext-json: *
- guzzlehttp/guzzle: ^6.5.8 || ^7.4.5
- psr/log: ^1.0 || ^2.0 || ^3.0
Requires (Dev)
- laravel/framework: ^6.0 || ^7.0 || ^8.0 || ^9.0 || ^10.0 || ^11.0 || ^12.0
- phpunit/phpunit: ^8.5 || ^9.6
Suggests
- illuminate/support: Laravel entegrasyonu için (service provider ve facade)
Provides
None
Conflicts
None
Replaces
None
README
YÖKSİS (Yükseköğretim Bilgi Sistemi) OBS REST servisleri için PHP istemcisi.
A PHP client for the Turkish Council of Higher Education (YÖK) YÖKSİS OBS REST services.
Gereksinimler
- PHP 7.2.5 veya üzeri (PHP 8.x desteklenir)
- Guzzle 6.5 veya 7.x
Kurulum
composer require conkal/yoksis-rest-client
0.2.x sürümünden yükseltiyorsanız geriye uyumsuz değişiklikler için CHANGELOG.md dosyasına bakın.
Kullanım
use Conkal\YOKSIS\REST\YOK; require __DIR__ . '/vendor/autoload.php'; // canlı ortam için YOK::PRODUCTION_URI $client = YOK::create(YOK::TEST_URI, getenv('YOKSIS_USERNAME'), getenv('YOKSIS_PASSWORD'));
YOK::create() zaman aşımı (30 sn) ve geçici hatalarda yeniden deneme ayarlarıyla hazır bir istemci döndürür;
ayrıntılar için Yeniden deneme ve loglama bölümüne bakın.
İstemciyi elle de kurabilirsiniz. Proxy gibi özel ayarlar için kendi Guzzle istemcinizi verin:
use Conkal\YOKSIS\REST\Utilities\BasicAuth; $http = new \GuzzleHttp\Client(['timeout' => 30]); $client = new YOK(YOK::TEST_URI, $http, new BasicAuth($user, $pass));
Kaynak metotları
| Metot | Açıklama |
|---|---|
all() |
Tüm kayıtları entity dizisi olarak döndürür. |
query(array $query) |
Sorgu parametreleriyle arama yapar, entity dizisi döndürür (sonuç yoksa []). |
find($id) |
Tek kayıt dönerse entity, birden fazla kayıt dönerse entity dizisi, hiç kayıt yoksa null döndürür. |
create(Entity $entity) |
Kaydı gönderir, servisin yanıtını döndürür. |
delete($id) |
Kaydı siler. |
Desteklenen servisler
Servisler YÖK'ün "REST Servisler Yardım Dökümanı" (sürüm 2.0) esas alınarak hazırlanmıştır. Bölüm numaraları dokümandakilerdir.
| Bölüm | Erişim | Servis | Metotlar |
|---|---|---|---|
| 4 | $client->ogrenciCezalar() |
ogrencicezalar |
all, query, find, create, update, delete |
| 4 | $client->cezaTurleri() |
cezaturleri |
all |
| 5 | $client->ogrenciIzinler() |
ogrenciizinler |
query, find, create, update, delete |
| 6 | $client->mezunlar() |
mezunlar |
query, paginate, cursor |
| 7 | $client->duyurular() |
duyurular |
all |
| 8 | $client->universiteler() |
universiteler |
all |
| 9 | $client->teyitlesme() |
sonbasariliteyitlesme |
sonBasarili |
| 10 | $client->hazirlikTurleri() |
hazirlikturleri |
all |
| 10 | $client->hazirlikDetay() |
hazirlikdetay |
all, query, find, create, update, delete |
| 11 | $client->pedagojikFormasyonAlanlari() |
pedagojikformasyonalanlari |
all |
| 11 | $client->pedagojikFormasyon() |
pedagojikFormasyon |
all, query, find, create, update, delete |
| 12 | $client->askerlikDurum() |
askerlikDurumSorgula |
sorgula |
| 12 | $client->askerlikErtelemeReferans() |
askerlikErtelemeReferans |
find |
| 12 | $client->askerlikErtelemeTalep() |
askerlikErtelemeTalep |
create, sonuc, delete, query |
| 13 | $client->yatayGecisler() |
yatayGecisListele |
query, yilaGore |
| 14 | $client->yerlestirmeVeri() |
yerlestirmeveri |
query, paginate, cursor |
| 14 | $client->fotografIndir() |
fotografindir, toplufotografindir |
find, save, toplu, topluKaydet |
| 14 | $client->vakifOgrenimUcreti() |
vakifogrenimucreti |
bildir |
| 15 | $client->ogrenciTranskript() |
ogrencitranskript |
find, findByTcKimlikNo, create, delete |
| 16 | $client->mebMezunDetay() |
mebmezundetaysorgula |
sorgula |
| 17 | $client->saglikBakanligiTescil() |
saglikbakanligitescilsorgula |
sorgula |
| 18 | $client->kykOgrenciSorgula() |
kykogrencisorgula ve ilgili servisler |
sorgula, query, topluSorgula, ogrenciSayisi, ogrenciSayisiYilaGore |
| 19 | $client->yurtDisindanYatayGecis() |
yurtDisindanYatayGecis |
all, query, find, create, update, delete |
| 20 | $client->ogrenciIletisimBilgileri() |
ogrenciIletisimBilgi |
create, update, delete, deleteByTcKimlikNo |
Dokümandaki kod listeleri Conkal\YOKSIS\Constants altında sabit olarak bulunur: DonemTuru (YKS, DGS, ...),
OgrenciIzin\IzinTuru, Ceza\CezaMahkemeIptal, HazirlikDetay\HazirlikTuru, Askerlik\* (referans türleri,
durum ve sonuç kodları) ve Kyk\KrediTuru.
Doğrulanmamış varsayımlar: Dokümanda yolu ya da parametre yeri açıkça gösterilmeyen üç çağrı diğer servislerle aynı kalıba göre yazılmıştır:
pedagojikFormasyon()->update()(PUT pedagojikFormasyon/{id}),ogrenciIzinler()->find()(GET ogrenciizinler/{id}) vevakifOgrenimUcreti()->bildir()(parametreler hem sorgu dizesinde hem gövdede gönderilir). İzin türleri servisinin (izinTurleriniListele) yolu dokümanda olmadığından eklenmedi; değerlerIzinTurusabitlerindedir.
Listede olmayan bir servisi ham olarak çağırmak için send() kullanılabilir:
$response = $client->send('servisAdi', ['query' => ['tcKimlikNo' => '<tckno>']]); $data = json_decode((string) $response->getBody());
Örnekler
Pedagojik Formasyon
use Conkal\YOKSIS\REST\Entities\PedagojikFormasyon; $pedagojikFormasyon = new PedagojikFormasyon(); $pedagojikFormasyon->tcKimlikNo = '<tckno>'; $pedagojikFormasyon->alanId = 1; $pedagojikFormasyon->belgeNo = '<belge no>'; $pedagojikFormasyon->belgeTarihi = '<d/m/Y>'; $pedagojikFormasyon->universiteId = '<universite id>'; $pedagojikFormasyon->fakulteId = '<fakülte id>'; // kaydet $client->pedagojikFormasyon()->create($pedagojikFormasyon); // sorgula $kayitlar = $client->pedagojikFormasyon()->query(['tcKimlikNo' => '<tckno>']); // sil $client->pedagojikFormasyon()->delete($kayitlar[0]->id);
Entity'ler dizi ile de doldurulabilir:
$pedagojikFormasyon = new PedagojikFormasyon([ 'tcKimlikNo' => '<tckno>', 'alanId' => 1, ]);
Yerleşen Verisi
Servis sayfalı yanıt döndürür. query() yalnızca istenen sayfadaki kayıtları dizi olarak verir:
/** @var \Conkal\YOKSIS\REST\Entities\YerlestirmeVeri[] $yerlesenler */ $yerlesenler = $client->yerlestirmeVeri()->query(['tur' => 'YKS', 'yil' => '2019']);
Toplam kayıt ve sayfa sayısı gibi bilgiler için paginate() kullanın. Dönen Page nesnesi dizi gibi gezilebilir:
$sayfa = $client->yerlestirmeVeri()->paginate(['tur' => 'YKS', 'yil' => '2019', 'page' => 0, 'size' => 100]); $sayfa->getTotalElements(); // toplam kayıt $sayfa->getTotalPages(); // toplam sayfa $sayfa->getPageNumber(); // 0'dan başlayan sayfa numarası $sayfa->hasMorePages(); foreach ($sayfa as $yerlesen) { /* ... */ }
Tüm sayfaları tek tek elle çekmek yerine cursor() sayfaları ihtiyaç duyuldukça çeker; bellekte tek seferde yalnızca bir sayfa tutulur:
foreach ($client->yerlestirmeVeri()->cursor(['tur' => 'YKS', 'yil' => '2019'], 500) as $yerlesen) { // ... }
Parametreler: yil ve tur zorunludur (tur için Constants\DonemTuru). İsteğe bağlı olarak tcKimlikNo,
ekayitOlanlar ('true'/'false') ve ekayitTarihi (dd/MM/yyyy) ile filtrelenebilir. page 0'dan başlar
(varsayılan 0), size sayfa boyutudur (varsayılan 1000). Servis sayfa parametresini yok sayarsa cursor()
sonsuz döngüye girmez, durur.
Hazırlık Detay
use Conkal\YOKSIS\Constants\HazirlikDetay\MuafiyetDurumu; use Conkal\YOKSIS\REST\Entities\HazirlikDetay; $detay = new HazirlikDetay(); $detay->tckno = '<tckno>'; $detay->hazirlikTuru = 2; $detay->ogretimDili = 1; $detay->hazirlikDonemNo = 1; $detay->muafiyetDurumu = MuafiyetDurumu::MUAF_DEGIL; $detay->birimId = '<birim id>'; // kaydet $client->hazirlikDetay()->create($detay);
Ceza Alan Öğrenciler
use Conkal\YOKSIS\Constants\Ceza\CezaMahkemeIptal; use Conkal\YOKSIS\REST\Entities\OgrenciCeza; $ceza = new OgrenciCeza([ 'tcKimlikNo' => '<tckno>', 'birimID' => '<birim id>', 'cezaID' => 1, // $client->cezaTurleri()->all() ile alınan kod 'yonetmelikMaddeFikra' => '2', 'cezaMahkemeIptalMi' => CezaMahkemeIptal::HAYIR, 'cezaTarihi' => '12/07/2017', 'cezaBaslangicTarihi' => '13/07/2017', 'cezaBitisTarihi' => '13/09/2018', ]); $sonuc = $client->ogrenciCezalar()->create($ceza); // "ID:96375" $cezalar = $client->ogrenciCezalar()->query(['tcKimlikNo' => '<tckno>']); $cezalar[0]->cezaBitisTarihi = '18/07/2018'; $client->ogrenciCezalar()->update($cezalar[0]);
Mezunlar, Duyurular, Üniversiteler, Teyitleşme
foreach ($client->mezunlar()->cursor() as $mezun) { echo $mezun->tcKimlikNo, ' ', $mezun->adi, ' ', $mezun->soyadi, PHP_EOL; } $duyurular = $client->duyurular()->all(); $universiteler = $client->universiteler()->all(); $teyit = $client->teyitlesme()->sonBasarili(); // $teyit->sonBasariliTeyitlesmeTarihi
Öğrenci İzinleri
use Conkal\YOKSIS\REST\Entities\OgrenciIzin; $izin = new OgrenciIzin([ 'tcKimlikNo' => '<tckno>', 'birimID' => '<birim id>', 'kararTarihi' => '01/01/2020', 'izinBaslangicTarihi' => '01/01/2020', 'izinBitisTarihi' => '01/01/2021', 'izinSuresi' => 1, ]); $client->ogrenciIzinler()->create($izin); $izinler = $client->ogrenciIzinler()->query(['tcKimlikNo' => '<tckno>']);
Askerlik Erteleme
use Conkal\YOKSIS\REST\Entities\AskerlikErtelemeTalep; // teklif nedenleri $nedenler = $client->askerlikErtelemeReferans()->find('ERTELEME_TEKLIF_NEDENLERI'); $talep = new AskerlikErtelemeTalep(); $talep->tcKimlikNo = '<tckno>'; $talep->birimId = '<birim id>'; $talep->teklifTuru = 'E'; // Erteleme için E, iptal için I $talep->teklifNedeniNo = 501; $talep->imzalayanTcNo = '<yetkili tckno>'; $talep->imzalayanAdSoyad = '<yetkili ad soyad>'; $yanit = $client->askerlikErtelemeTalep()->create($talep); // 3-15 gün içinde sonuçlanır; günde en fazla bir kez sorgulanması önerilir. $sonuc = $client->askerlikErtelemeTalep()->sonuc($yanit->talepKayitUid); if ($sonuc->beklemedeMi()) { // henüz sonuçlanmadı (HTTP 206) } elseif ($sonuc->sonuc === \Conkal\YOKSIS\Constants\Askerlik\TalepSonucu::ERTELEME) { echo $sonuc->ertBitTarihi; }
Talepten önce öğrencinin askerlik durumunu sorgulayabilirsiniz:
$durum = $client->askerlikDurum()->sorgula('<tckno>'); // $durum->askerlikDurumKod, $durum->askerlikErtDurumKod (bkz. Constants\Askerlik\DurumKodu, ErtelemeDurumu)
KYK Öğrenci Sorgulama
$kyk = $client->kykOgrenciSorgula(); $ogrenci = $kyk->sorgula('<tckno>'); // $ogrenci->krediBursDurumu->ad, $ogrenci->yurtBarinmaDurumu->ad $liste = $kyk->topluSorgula($tcKimlikNolar); // 100'den fazlaysa otomatik parçalara bölünür $sayilar = $kyk->ogrenciSayisi('<birim id>'); $yillik = $kyk->ogrenciSayisiYilaGore('<birim id>', '<birim tür>', 2024);
MEB ve Sağlık Bakanlığı
$liseMezuniyeti = $client->mebMezunDetay()->sorgula('<tckno>'); $tescil = $client->saglikBakanligiTescil()->sorgula('<tckno>');
Yurt Dışından Yatay Geçiş ve Öğrenci İletişim Bilgileri
Bu servislerin {"returnCode", "data", "count"} zarfı kütüphane tarafından açılır:
use Conkal\YOKSIS\REST\Entities\OgrenciIletisimBilgi; $kayitlar = $client->yurtDisindanYatayGecis()->query(['tcKimlikNo' => '<tckno>']); $yanit = $client->ogrenciIletisimBilgileri()->create(new OgrenciIletisimBilgi([ 'tcKimlikNo' => '<tckno>', 'birimId' => '<birim id>', 'ePosta' => 'ogrenci@example.com', ])); // $yanit->id
Fotoğraf İndirme
// dosyaya kaydet $client->fotografIndir()->save('<tckno>', '/tmp/<tckno>.jpg'); // bir yerleştirmenin tüm fotoğrafları (zip, belleğe alınmadan diske yazılır) $client->fotografIndir()->topluKaydet(2024, \Conkal\YOKSIS\Constants\DonemTuru::YKS, '/tmp/fotograflar.zip'); // ya da ham yanıtı al $response = $client->fotografIndir()->find('<tckno>');
Öğrenci Transkript
use Conkal\YOKSIS\REST\Entities\Transkript\Ders; use Conkal\YOKSIS\REST\Entities\Transkript\Donem; use Conkal\YOKSIS\REST\Entities\Transkript\OgrenciTranskript; $transkript = new OgrenciTranskript(); $transkript->ogrenciId = '<ogrenci id>'; $transkript->tcKimlikNo = '<tckno>'; $transkript->birimId = '<birim id>'; $transkript->donemler = [ new Donem([ 'donemYili' => '2018-2019', 'donemNumarasi' => '1', 'dersler' => [ new Ders(['dersinKodu' => 'MAT101', 'dersinAdi' => 'Matematik', 'not' => 'AA']), ], ]), ]; $client->ogrenciTranskript()->create($transkript); $kayit = $client->ogrenciTranskript()->find('<ogrenci id>'); $kayit = $client->ogrenciTranskript()->findByTcKimlikNo('<tckno>', '<birim id>');
Hata yönetimi
Tüm hatalar Conkal\YOKSIS\REST\Exceptions altındaki istisnalarla fırlatılır:
| İstisna | Durum |
|---|---|
AuthenticationException |
401, 403: kullanıcı adı, şifre ya da servis yetkisi hatalı |
NotFoundException |
404 |
ValidationException |
400, 409, 422: gönderilen veri reddedildi |
RateLimitException |
429 (getRetryAfter() bekleme süresini verir) |
RequestFailedException |
Diğer 4xx; yukarıdakilerin üst sınıfı |
ServerErrorException |
5xx |
ConnectionException |
Bağlantı hatası, zaman aşımı |
Hepsi YoksisException arayüzünü uygular. HTTP hatalarında (ApiException) durum kodu, yanıt gövdesi ve
yanıttan ayrıştırılabilen hata mesajı alınabilir:
use Conkal\YOKSIS\REST\Exceptions\AuthenticationException; use Conkal\YOKSIS\REST\Exceptions\ValidationException; use Conkal\YOKSIS\REST\Exceptions\YoksisException; try { $client->pedagojikFormasyon()->create($pedagojikFormasyon); } catch (ValidationException $e) { echo $e->getErrorMessage(); // servisin döndürdüğü hata mesajı (varsa) echo $e->getResponseBody(); // ham yanıt gövdesi } catch (AuthenticationException $e) { // kimlik bilgilerini kontrol edin } catch (YoksisException $e) { // diğer tüm YÖKSİS hataları }
İstisnalar Guzzle'ın kendi sınıflarından türer (ClientException, ServerException, ConnectException),
bu yüzden 1.0'daki catch (ClientException $e) gibi kodlar değiştirilmeden çalışmaya devam eder.
Yeniden deneme ve loglama
YOK::create() ile oluşturulan istemci, geçici hatalarda (bağlantı hatası, 429, 502, 503, 504)
isteği artan bekleme süreleriyle yeniden dener. Retry-After başlığına uyar. Varsayılan olarak yalnızca GET/HEAD
istekleri yeniden denenir; create() gibi POST istekleri mükerrer kayıt oluşturmamak için denenmez.
$client = YOK::create(YOK::TEST_URI, $kullanici, $sifre, [ 'timeout' => 30, // saniye 'connect_timeout' => 10, // saniye 'retries' => 2, // 0 yeniden denemeyi kapatır 'retry_delay' => 500, // ms; her denemede iki katına çıkar 'logger' => $logger, // herhangi bir PSR-3 logger (Monolog vb.) ]);
logger verildiğinde her deneme metot, yol, durum kodu, süre ve deneme numarasıyla loglanır.
T.C. kimlik numarası gibi kişisel verilerin log'a düşmemesi için sorgu parametreleri, istek/yanıt gövdeleri
ve Authorization başlığı loglanmaz.
Laravel
Paket, Laravel'in paket keşfi (auto-discovery) ile otomatik olarak kaydolur. .env dosyasına bilgileri ekleyin:
YOKSIS_BASE_URI=https://servisler.yok.gov.tr/resttest/obs/ YOKSIS_USERNAME=... YOKSIS_PASSWORD=... # isteğe bağlı YOKSIS_TIMEOUT=30 YOKSIS_RETRIES=2 YOKSIS_LOG_CHANNEL=daily
Ayarları özelleştirmek için config dosyasını yayınlayın:
php artisan vendor:publish --tag=yoksis-config
İstemciyi facade ya da bağımlılık enjeksiyonu ile kullanın:
use Conkal\YOKSIS\Laravel\Facades\Yoksis; use Conkal\YOKSIS\REST\YOK; $turler = Yoksis::hazirlikTurleri()->all(); class YerlesenController { public function index(YOK $yoksis) { return $yoksis->yerlestirmeVeri()->paginate(['tur' => 'YKS', 'yil' => '2019']); } }
Laravel 6 ve sonraki sürümler desteklenir.
Geliştirme
composer install composer test # birim testleri (ağ bağlantısı gerekmez) composer test:integration # YÖKSİS test ortamına gerçek istek gönderir
Entegrasyon testleri YOKSIS_USERNAME ve YOKSIS_PASSWORD ortam değişkenleri tanımlı değilse atlanır.
Ek olarak YOKSIS_BASE_URI, TEST_TCKNO, TEST_BIRIMID ve TEST_UNIVERSITEID değişkenleri kullanılır.
Katkıda bulunmak için CONTRIBUTING.md dosyasına bakın.