Öncelikle alanları açacak butonları ayarlayalım.
Bu butonları kendimizce gruplandırmak için "sectionTabButton" diye bir class ekleyelim.
Hangi butonun hangi alanı açacağını belirtmek için de data-target-id gibi bir attribute ekleyelim.
Sonra içeriklerinizi tutacak alanlar için de "sectionContent" diye bir class ekleyelim.
Bu içeriklerin hangi butonla bağlantılı çalışacağını belirlemek için de data-section-id diye bir attribute ekleyelim.
Hangi alanın aktif olduğunu belirtmek için de "active" class'ını kullanalım.
Başlangıçta ilk alanın aktif olması için hem ilgili butona hem içeriğe bu class'ı ekleyelim.
<div>
<button class="sectionTabButton active" data-target-id="1">Alan 1</button>
<button class="sectionTabButton" data-target-id="2">Alan 2</button>
<button class="sectionTabButton" data-target-id="3">Alan 3</button>
<button class="sectionTabButton" data-target-id="4">Alan 4</button>
<button class="sectionTabButton" data-target-id="5">Alan 5</button>
<button class="sectionTabButton" data-target-id="6">Alan 6</button>
</div>
<div>
<div class="sectionContent active" data-section-id="1">Alan 1 içeriği</div>
<div class="sectionContent" data-section-id="2">Alan 2 içeriği</div>
<div class="sectionContent" data-section-id="3">Alan 3 içeriği</div>
<div class="sectionContent" data-section-id="4">Alan 4 içeriği</div>
<div class="sectionContent" data-section-id="5">Alan 5 içeriği</div>
<div class="sectionContent" data-section-id="6">Alan 6 içeriği</div>
</div>
Yalnızca "active" class'ına sahip içeriğin görünmesini, diğerlerinin gizli kalmasını istiyoruz.
Bunu javascript ile yapmak yerine css ile yapabiliriz.
.sectionContent { display:none /*...alanın diğer stilleri*/ }
.sectionContent.active { display:block; }
Şimdi butonları işler hale getiren script'i yazabiliriz.
Bir butona basıldığında, "active" class'lı butonun ve içeriğin bu class'ı silinmeli.
Basılan butona ve buna bağlı içeriğe "active" class'ı eklenmeli.
const $sectionTabButtons = document.querySelectorAll(".sectionTabButton");
const $sectionContents = document.querySelectorAll(".sectionContent");
// Aşağıdaki script'i üşendiğim için ChatGPT 3.5'e yazdırdım...
$sectionTabButtons.forEach(function ($button) {
$button.addEventListener("click", function () {
// Tüm butonlardan "active" class'ını kaldır
$sectionTabButtons.forEach($btn => {
$btn.classList.remove("active");
});
// Tüm içerik alanlarından "active" class'ını kaldır
$sectionContents.forEach($content => {
$content.classList.remove("active");
});
// Basılan butona "active" class'ını ekle
$button.classList.add("active");
// İlgili içeriği bul ve ona "active" class'ını ekle
const targetId = button.getAttribute("data-target-id");
const $targetContent = document.querySelector('.sectionContent[data-section-id="'+targetId+'"]');
$targetContent.classList.add("active");
});
});
Başına $ koyduğum değişkenler: Genel olarak bir değişkenin bir element tuttuğunu belirtmek için değişkenin başına $ işareti koyulur.
Zorunluluk değildir ama js geliştiricileri arasında bir standart olarak, kod anlaşılırlığını kolaylaştırmak için kullanılıyor.
Malesef ben de göremedim. Çin merkezli DCloud firması tarafından hazırlandığı için tüm kaynaklar da ona göre hazırlanmış.
Bu durumda ChatGPT, Gemini gibi bir aracı kullanarak dokümantasyonu takip etmek için ek bir çabaya girmek gerek.
- Gemini 1.0 Pro ile denedim ama düzgün cevaplar alamadım. Yalan yanlış bilgiler...
- ChatGPT 3.5 ile denediğimde daha düzgün cevaplar aldım. Önce uni-app'in ne olduğunu anladığından emin olduktan sonra dokümantasyon içeriğini (doğrudan erişemediği için kopyala-yapıştır ile) çevirmesini istedim ve detaylı olmasa da anlaşılır bir çeviri sundu. Detaylar için ayrıca soru-cevap şeklinde ilerlemek gerek tabi...
ChatGPT konuşmamı link vererek paylaşmak istedim ama nedense hata aldım.
Nitekim, Çin projesi olduğu için muhtemelen batı dünyasında karşılık bulmayacaktır. Haliyle düzgün İngilizce kaynak sıkıntısı hep olacaktır diye düşünüyorum. Zaten kendileri bile İngilizce içeriğe özen göstermemişler gibi görünüyor. Bu durumda, geliştirme sırasında karşınıza çıkabilecek çeşitli hataları araştırdığınızda da hep Çince sorular ve yanıtlarla karşılaşacaksınız diye düşünüyorum.
Sanırım React ile cross platform geliştirme yapmak yerine Vue ile yapmak istediğiniz için uni-app öğrenmek istiyorsunuz.
Bu durumda Vue Native önerebilirim. Tekerleği yeniden icat etmek yerine React Native altyapısını kullanır ama üst katman olarak sizin Vue kullanmanızı sağlar. İnceleyebilirsiniz...
Şu örneği inceleyebilirsiniz: https://codepen.io/ebykdrms/pen/ZEPgxmo
<div id="yenieklenensliderbuyukresim"></div>
<div class="yenieklenenslider">
<div><img class="yenieklenenresim" src='https://picsum.photos/400'></div>
<div><img class="yenieklenenresim" src='https://picsum.photos/401'></div>
<div><img class="yenieklenenresim" src='https://picsum.photos/402'></div>
<div><img class="yenieklenenresim" src='https://picsum.photos/403'></div>
</div>
#yenieklenensliderbuyukresim { height:400px; width:400px; border:1px solid #ccc; margin:20px auto; }
#yenieklenensliderbuyukresim > img { width:100%; height:100%; object-fit:cover; }
.yenieklenenslider { display:flex; flex-direction:row; align-items:center; justify-content:center; }
.yenieklenenresim { width:100px; height:100px; object-fit:cover; cursor:pointer; }
const $bigImage = document.getElementById("yenieklenensliderbuyukresim");
const $images = document.querySelector(".yenieklenenresim");
document.addEventListener("click", function(e){
const target = e.target.closest(".yenieklenenresim");
if(!target) return;
const src = target.getAttribute("src");
$bigImage.innerHTML = target.outerHTML;
});
API olarak kullanmak için PHP tek başına yeterlidir.
Ama bazı işler var ki PHP'de yapması fazla emek istiyor. Mesela websocket bağlantısı kurmak...
Ama sadece PHP üzerine inşa edilen büyük projeler de var ve PHP taleplerini gayet güzel karşılıyor.
Ben Node.js tavsiye ederim. İmkân oldukça Node.js kullanırım.
Express.js ile API'ınızı kolayca ayağa kaldırabilirsiniz.
Node.js imkânım yoksa (mesela Türkiye'den alınmış bir shared hosting üzerinde çalışmak zorundaysam) ikinci tercihim PHP olur.
Web sitesini PHP ile hazırlıyorsam servis olarak da, aynı projede farklı diller görmek istemediğimden yine PHP kullanmayı tercih ederim. Ama PHP ile karmaşık olabilecek işlere gireceksem PHP'yi çok da zorlamadan Node.js desteği almayı tercih ederim.
Sanırım bu eğitimde kullanılan sunucu ayarlarıyla ilgili bir durum.
Tüm isteklerin (eğer bir karşılığı yoksa) kök klasördeki index.php dosyasını çalıştırması sağlanmış.
Bunun için sunucu üzerinde düzenleme yaptığı bir yer göremedim. Bir .htaccess dosyası da kullanmıyor.
Muhtemelen kullandığı sunucunun varsayılan ayarı bu şekilde.
Bu sorunu aşmak için projenizin kök klasörüne .htaccess adlı bir dosya oluşturun ve içine şunları yazın:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php [L]
Bu sayede sunucu, dosya karşılığını bulamadığı istekleri index.php dosyasına yönlendirecektir.
index.php dosyası da url'ye bakıp hangi dosyayı çağırması gerektiğini bulacaktır.
Başka yanıt gelmediği için bazı linkler bırakıyorum...
https://nextjs.org/docs
https://redux.js.org/usage/nextjs
https://redux-toolkit.js.org/rtk-query/usage/server-side-rendering
https://www.linkedin.com/pulse/nextjs-redux-powerful-combination-building-web-bard-aman-singh-jaswal/
https://medium.com/@ybsweb/react-query-nedir-nasıl-kullanılır-71d933859d89#:~:text=React Query, bir React uygulamasında,birçok işlemi otomatik olarak gerçekleştirir.
https://blog.atolyedijital.com.tr/react-query-ile-server-state-yönetimi-507c85be073a
https://next-auth.js.org/getting-started/introduction
https://nextjs.org/learn/dashboard-app/getting-started
Bir kullanıcının bulunmaması gereken bir sayfada bulunması ve "no redirect" ile başka sayfaya yönlendirilmekten kurtulması...
Eğer kullanıcıyı başka sayfaya yönlendiremiyorsak, en azından bu sayfanın içeriğini görmesini engelleyebiliriz.
Mesela kullanıcı login olduktan sonra /admin/dashboard url'sine yönlendiriliyor olsun.
Ama kullanıcı login ekranını geçip direkt url üzerinden /admin/dashboard diyerek bu ekrana girmiş olsun.
Biz bu sayfada kullanıcının yetkisi olup olmadığını kontrol ediyoruz ve eğer yetkisi yoksa /login ekranına redirect ediyoruz.
Ama kullanıcının tarayıcısında bir eklenti var ve redirect işlemlerini engelliyor.
- Haliyle /login ekranına yönlendirilemiyor.
- Haliyle /admin/dashboard ekranında kalıyor.
- Haliyle /admin/dashboard ekranının içeriğini de görebiliyor veya en azından session'ı/token'ı olmadığından oluşan hata mesajlarını görebiliyor.
Bu durumda redirect komutunu verdiğimiz yerde kodların çalışmasını da durdurmak için bir komut kullanmalıyız.
Bahsettiğimiz dil php ise:
if(!$hasAccess) {
// Kullanıcının yetkisinin olmadığını anlamışız ve login ekranına yönlendiriyoruz.
header("Location:login");
// Eğer bir şekilde yönlendirme komutu engellenirse bile exit komutu sayesinde sayfa içeriğinin görünmesini engelliyoruz.
exit("Bu sayfayı görüntülemek için oturum açmanız gerekiyor. Lütfen giriş ekranına gidiniz...");
}
// Bu if bloğundan sorunsuzca geçebilirse sayfa içeriğini gösteriyoruz.
// Sayfanın içerikleri...
Tek satırlık basit bir çözüm ama yazılımcılar bunu unutabiliyorlar...
echo attığınızda else bloğuna giriyorsanız -ki aldığınız hata da bunu destekliyor- şu anlama gelir:
'Admin' adlı class'ınızın içinde 'Listele' adlı bir fonksiyona ulaşılamıyor.
O zaman düzgün bir şekilde *Admin isimli sınıfta Listele methodu bulunamadı!* yazmasını bekliyorsunuz ama hata mesajı dönüyor.
Hata mesajı: Object of class Admin could not be converted string.
Yani: Admin class'ının objesi string'e dönüştürülemedi.
$ClassName değişkeninizde Admin class'ından türetilen obje var.
'<b>' . $ClassName . '</b> isimli sınıfta <b>' . $Method . '</b> methodu bulunamadı!' şeklinde bir string birleştirme işlemi yapıyorsunuz ama string'in içine object'i yerleştiremiyor.
Bu karışıklık, değişken adınızın yanıltıcı olmasından kaynaklanıyor. Değişken adınız $ClassName sanki içinde bir string ifade barındırıyormuş gibi düşündürüyor.
Bu isim yerine yerine $ClassObject ismi verilebilir. Böylece değişkenin adı bile yanlış kullandığınız yerde sorunu fark etmenize yardımcı olur.
Yani öncelikle $ClassName değişkeninizin adını $ClassObject olarak güncellemelisiniz.
Sorunu çözmek için de, $ClassObjecti tanımladığınız satırın hemen altına bir $ClassName değişkeni tanımlayın ve sınıfın adını (string olarak) buraya atayın.
$ClassObject = new $Controller();
$ClassName = get_class($ClassObject); // Objenin türetildiği sınıfın adını string olarak verir.
if (method_exists($ClassObject, $Method)) {
call_user_func_array([$ClassObject, $Method], $Parameters);
} else {
exit("<b>$ClassName</b> isimli sınıfta <b>$Method</b> fonksiyonu bulunamadı!");
}
Gözüme çarptığı kadarıyla şu satırda da henüz karşılaşmadığınız bir sorun var:
exit('<b>' . $ControllerFile . '</b> isimli controller dosyasında <b>' . $ClassName . '</b> sınıfı bulunamadı!');
Burada kullandığınız $ClassName değişkeni hiç oluşturulmamış bir değişken. Yani bu değişken yalnızca if bloğunda oluşturuluyor. Bu yüzden else bloğunda bu değişkene erişemezsiniz. Yani PHP belki bir esneklik sunuyordur ama en iyi ihtimalle hata almak yerine boş string elde edersiniz.
Bu satırı da şu şekilde düzeltebilirsiniz:
exit("<b>$ControllerFile</b> isimli controller dosyasında <b>$Controller</b> sınıfı bulunamadı!");
/lib/view.class.php dosyasındaki render() fonksiyonu:
public function render(){
$data = $this->data;
ob_start();
include($this->path);
$content = ob_get_clean();
return $content;
}
ob_start();ile tamponlama işlemlerinin başlayacağı belirtiliyor.include($this->path);ile ilgili view dosyasının içeriği buraya yazılıyor. Yani aslında html dosyası olsa da, dosyada yazan veriler bu php dosyasına alınmış oluyor. Bu php dosyası, içindeki php komutlarını işleyebilir.$content = ob_get_clean();ile tamponlama işlemi sonlanıyor ve işlenmiş içerik$contentdeğişkenine aktarılıyor.return $content;ile bu fonksiyon, içeriğin işlenmiş halini (yani php kodlarının işlenip html içine yazılmış, yani php kodları barındırmayan halini) döndürüyor.
Yani regex ile arayıp bulup işlem yapmasına gerek kalmadan ob_get_clean() ile php kodunu işlemiş.
Sanırım şu site tam istediğiniz işi yapıyor:
https://mocki.io/fake-json-api
- Nasıl bir json çıktısı almak istediğinizi yazıyorsunuz.
- Create API diyorsunuz.
- Size bir endpoint veriyor.
- Endpoint'e istek attığınızda, oluşturduğunuz json'u response olarak alabiliyorsunuz.
Kayıt olunduğunda daha detaylı özellikler sunuyordur muhtemelen. Ücretsiz deneme için kayıt olmadım.
Bu tip size özel endpoint'lere çokça ihtiyacınız oluyorsa aylık 10$ uygun bir fiyat gibi.
Özellikle username, avatar ve email key'lerine ihtiyacınız varsa şurası da iş görür sanıyorum:
https://fakeapi.platzi.com
Burada ücretle ilgili bi'şey belirtmemişler.