Input'lara php ile veri basılıyorsa, input için value özelliği kullanılır ama checkbox için checked özelliği kullanılır.
Veritabanından aldığın veriyi hangi değişkenlerle aldığını bilmediğim için uyduracağım:
Tüm kayıtları çektiysen (örneğimizde Veri 1 ve Veri 3 olm.üz. 2 kayıt var) şöyle bir değişkenin var diye varsayalım:
$datas = [
["ekle_ad" => "yazilimyolcusu", "ekle_ozellik" => "Veri 1"],
["ekle_ad" => "yazilimyolcusu", "ekle_ozellik" => "Veri 3"]
];
Bu durumda ekle_ad bölümü zaten aynı olduğu için ilk kaydı alabiliriz:
$ad = $datas[0]->ekle_ad;
ekle_ozellik verilerini de düz bir dizi içinde toplarsak html içine gömmek kolaylaşır.
foreach($datas as $data) $aktifOzellikler[] = $data->ekle_ozellik;
// $aktifOzellikler dizisi şöyle oldu: ["Veri 1", "Veri 3"]
$checkbox1_attr = array_search("Veri 1", $aktifOzellikler)===false ? '' : 'checked'; // 'checked'
$checkbox2_attr = array_search("Veri 2", $aktifOzellikler)===false ? '' : 'checked'; // ''
$checkbox3_attr = array_search("Veri 3", $aktifOzellikler)===false ? '' : 'checked'; // 'checked'
<form action="x.php" method="post">
<input class="x-text" type="text" name="ad" placeholder="Ad" value="<?=$ad?>" ><br>
<input class="x-checkbox" type="checkbox" <?=$checkbox1_attr?> name="ozellikler[]" value="Veri 1" placeholder="Veri 1" ><br>
<input class="x-checkbox" type="checkbox" <?=$checkbox2_attr?> name="ozellikler[]" value="Veri 2" placeholder="Veri 2" ><br>
<input class="x-checkbox" type="checkbox" <?=$checkbox3_attr?> name="ozellikler[]" value="Veri 3" placeholder="Veri 3" ><br>
</form>
Kodları denemeden direkt buraya yazdığım için syntax hataları veya kurgusal hatalar olabilir.
$ad = $_POST['ad'];
$ozellikler = $_POST['ozellikler'];
Burada $ozellikler
dizisi yalnızca seçili checkbox'ların değerlerini taşır.
Mesela "Veri 1" ve "Veri 3" seçili, "Veri 2" seçili değil.
O zaman $ozellikler
dizisi şunu içerir: ["Veri 1", "Veri 3"]
foreach($ozellikler as $ozellik) {
$query = "INSERT INTO ekle (ekle_ad, ekle_ozellik) VALUES ('$ad', '$ozellik')";
// diğer işlemler...
}
Burada ekle_ozellik
alanına $ozellik
değerini atıyoruz.
Yukarıdaki örneğe göre "Veri 1" ve "Veri 3" için 2 kez insert sorgusu çalışacak, yani 2 kayıt insert edilmiş olacaktır.
form tarafında input'lara php ile veri basılıyorsa, input için value özelliği kullanılır ama checkbox için checked özelliği kullanılır.
Veritabanından aldığın veriyi hangi değişkenlerle aldığını bilmediğim için uyduracağım:
Tüm kayıtları çektiysen (örneğimizde Veri 1 ve Veri 3 olm.üz. 2 kayıt var) şöyle bir değişkenin var diye varsayalım:
$datas = [
["ekle_ad" => "yazilimyolcusu", "ekle_ozellik" => "Veri 1"],
["ekle_ad" => "yazilimyolcusu", "ekle_ozellik" => "Veri 3"]
];
Bu durumda ekle_ad bölümü zaten aynı olduğu için ilk kaydı alabiliriz:
$ad = $datas[0]->ekle_ad;
ekle_ozellik verilerini de düz bir dizi içinde toplarsak html içine gömmek kolaylaşır.
foreach($datas as $data) $aktifOzellikler[] = $data->ekle_ozellik;
// $aktifOzellikler dizisi şöyle oldu: ["Veri 1", "Veri 3"]
$checkbox1_attr = array_search("Veri 1", $aktifOzellikler)===false ? '' : 'checked'; // 'checked'
$checkbox2_attr = array_search("Veri 2", $aktifOzellikler)===false ? '' : 'checked'; // ''
$checkbox3_attr = array_search("Veri 3", $aktifOzellikler)===false ? '' : 'checked'; // 'checked'
<form action="x.php" method="post">
<input class="x-text" type="text" name="ad" placeholder="Ad" value="<?=$ad?>" ><br>
<input class="x-checkbox" type="checkbox" <?=$checkbox1_attr?> name="ozellikler[]" value="Veri 1" placeholder="Veri 1" ><br>
<input class="x-checkbox" type="checkbox" <?=$checkbox2_attr?> name="ozellikler[]" value="Veri 2" placeholder="Veri 2" ><br>
<input class="x-checkbox" type="checkbox" <?=$checkbox3_attr?> name="ozellikler[]" value="Veri 3" placeholder="Veri 3" ><br>
</form>
Kodları denemeden direkt buraya yazdığım için syntax hataları veya kurgusal hatalar olabilir.
SQL injection açığından kurtulmak için PDO kullanmalısın.
XSS açığından korunmak için de ekrana basacağın verileri htmlspecialchars()
ile düzenlemen yeterli.
XSS açığını doğuran şey, tarayıcının yorumlayabileceği verinin DOM'a basılması.
Yalnızca veriyi ekrana basarken buna dikkat etmen yeterli olur.
Ama eğer veritabanına htmlspecialchars()
ile eklersen, ekrana basarken tekrar htmlspecialchars()
tekrar ile düzenlemene gerek kalmaz.
Bana sorarsan veritabanında verinin orijinal halini (sql injection'dan sakınarak) saklamalısın. Sadece veriyi ekrana basarken htmlspecialchars()
ile basmalısın.
Ö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...