Herkese çok detaylı, uzun ve teknik cevaplar vermeye çalışmamın nedeni aslında cevabı doğrudan soruyu sorana yönelik yazmamam.
Aslında çoğu kez soruyu soranların zaten cevaplarımda anlattıklarımın çoğunu bildiklerini farkındayım.
Ama ben cevaplarımı, konu hakkında az bilgisi olup da araştırırken cevabımı gören olursa onun için de anlaşılır olsun diye düşünerek yazıyorum.
Ama tabi prototurk.com soru cevap bölümünün arama özelliği henüz iyileştirilmediği için çoğunlukla yazdıklarım boşa gidiyor tabi... :( Ama bir gün arama bölümü geliştirilirse kaynaklar hazır olsun istiyorum.
Tayfun Erbilen'e instagram üzerinden buraların geliştirilmesine destek olabileceğimi söyledim ama ya görmedi ya güvenmedi. :)
Açıkçası Chrome eklentisi yazmak üzerine "Merhaba Dünya" dışında pek pratiğim yok.
Extension yazarken storage'a bu şekilde veri basıldığını bile sorunuzdan öğrendim. :)
Cevabım çalışsaymış iyiymiş. :/
Ben sorunuzu görüp diğer cevaplarınızı da okuyup anlayıp cevap yazmaya başladığımda pes etmişsiniz :D
Doğru cevabınızı görmeden bir cevap yazmış oldum (aşağılarda bulabilirsiniz).
Benim cevabımı yazmaya başlamam asenkron bir fonksiyon olsun ve bir obje döndürecek olsun.
Sizin doğru cevap olarak işaretlediğiniz cevap da asenkron bir fonksiyon olsun ve o da obje döndürecek olsun.
Benim fonksiyonum sizinkinden önce başladı ama sonucu sizinkinden sonra döndü.
Eğer sizin cevabınızın sonunda console.log(ebykdrms.cevap, munzevi.cevap)
diye bir komut olsaydı
normalde beklenen şey benim cevabım henüz oluşmadığı için (çünkü sizin fonksiyonunuzdayız) ilk parametre için undefined, ikinci parametre için sizin cevabınız olurdu.
Gel gelelim javascript (cevaplar obje oldukları için) ikimizin de cevabını ekrana basacaktı.
Ama şöyle doğrudan string'ler içeren bir komut verseydiniz:
console.log(ebykdrms.cevap.metin, munzevi.cevap.metin);
o zaman ilk parametre undefined olarak görünecekti.
Bu da öylesine bir cevap olsun :D
Adım adım işlemleri okuduğumda şöyle bir işleyiş gördüm:
1) Sınıftan nesne oluşturduğunuz anda kurucu fonksiyon çalışıyor.
2) conf = {}
ataması yapıyorsunuz.
3) storageData() fonksiyonunu çağırarak data = { lang: 'en', testData1: 1, testdata2: 2 }
işlemini sağlyorsunuz.
4) data
daki veriyi Object.entries()
işlevinden geçirip şu diziyi elde ediyorsunuz:
[ ["lang", "en"], ["testData1", 1], ["testData2", 2] ]
5) forEach()
ile bu dizi üzerinde dönmeye başlıyorsunuz. Döngüyü adım adım işlersek:
5.1) key="lang"
ve val="en"
iken chrome.storage.local.get("lang", (obj) => {...})
işlevini çağırıyorsunuz. Bu asenkron bir fonksiyon olduğu için henüz sonuçlanmadan döngünün 2.adımına geçiyorsunuz.
5.2) key="testData1"
ve val=1
iken chrome.storage.local.get("testData1", (obj) => {...})
işlevini çağırıyorsunuz. Bu asenkron bir fonksiyon olduğu için henüz sonuçlanmadan döngünün 3.adımına geçiyorsunuz.
5.3) key="testData2"
ve val=2
iken chrome.storage.local.get("testData2", (obj) => {...})
işlevini çağırıyorsunuz. Bu asenkron bir fonksiyon olduğu için henüz sonuçlanmadan döngünüz bitiyor.
6) Döngü bitti. Henüz asenkron fonksiyonlar sonuç döndürmedi. Yani getData2()
fonksiyonu çalışmadığı için henüz conf.lang
değeri de dolmadı.
7) conf.now
key'ini doldurduğunuz sırada henüz conf.lang
key'i tanımlanmadı.
console.log(this.conf, this.conf.lang)
sizi yanıltıyor. İlk parametrede obje, ikinci parametrede string gönderdiğiniz için, javascript de objelere ve string'lere farklı yaklaşımlar sergilediği için size yanıltıcı sonuçlar gösteriyor.
console.log()
fonksiyonu okunduğu andan ekrana basma işlemini gerçekleştirene kadar geçen sürede this.conf.lang
değeri dolmuş oluyor.
Yani console.log(this.conf, this.conf.lang)
komutunu verdiğiniz anda şunu söylemiş oluyorsunuz: console.log(obje, "string")
Ekrana basılma sırasında console.log()
string değeri doğrudan hafızasında tutarken, ilk parametredeki objenin sadece referansını tutuyor. Bu yüzden ekrana basılırkenki string değer gerçekten console.log()
komutu ilk çağırıldığındaki değer olurken obje değeri ekrana basılma anındaki değer neyse o oluyor.
Eğer objenin de o andaki değerini almak istiyorsanız komutu şu şekilde düzeltmelisiniz:
console.log(JSON.stringify(this.conf), this.conf.lang);
Böylece iki parametrede de string değer aldığı için çağırıldığı andaki değerler neyse onu yazdıracaktır.
Yani sizin obje olarak basınca değer var ama direkt değeri basınca değer yok olarak bahsettiğiniz olay javascript'in objeleri tutuş biçimindeki yaklaşımından kaynaklanıyor. (Ki aslında bu tutuş biçimi javascript'in yüksek performanslı olmasını sağlayan en büyük etkenlerden biri)
Sorunun çözümü olarak, emin değilim ama, conf.now
key'ine değer atama işlemini callback fonksiyonunun içinde yapmanız gerekiyor olabilir.
Yani:
constructor() {
this.conf = {};
Object.entries(this.storageData().data).forEach(([key, val]) => {
chrome.storage.local.get(key, obj => {
if(!obj[key]) chrome.storage.local.set({[key]:val}, this.getData2({[key]:val}));
else this.getData2(obj);
if(key=="lang") {
this.conf.now = new Intl.DateTimeFormat(this.conf.lang, {
weekday: 'long',
year: 'numeric',
month: 'long',
day: 'numeric',
hour: '2-digit',
minute: '2-digit',
second: '2-digit',
timeZoneName: 'longGeneric',
timeZone: this.conf.timeZone
}).format(new Date(Date.now()));
console.log("in callback: ", JSON.parse(JSON.strinify(this.conf)), this.conf.lang);
}
});
});
console.log("in constructor: ", JSON.parse(JSON.strinify(this.conf)), this.conf.lang);
}
React ile site yazıyorsanız aslında tek bir sayfaya sahipsiniz.
React projenizden build aldığınızda size bir grup dosya çıkaracak. Bu dosyalar node.js ile artık bir bağı kalmamış dosyalardır.
.htaccess yardımıyla PHP'ye gelen istekleri buraya yönlendirirseniz react projeniz PHP sunucuda çalışacaktır.
Eğer veritabanından sorgu sonucu dönmüyorsa query()
fonksiyonu false dönüyordur.
Bu durumda siz if koşulunda aslında false->rowCount()
yazmış gibi oluyorsunuz.
Hata da bundan bahsediyor: boolean bir değer üzerinde sanki objeymiş gibi rowCount() fonksiyonu çağırıyorsun
Bu hatadan kurtulmak için if koşulunu değiştirmelisiniz.
$vList = $db->query("SELECT * FROM news where news_category='30'", PDO::FETCH_ASSOC);
if($vList){
foreach ($vList as $vkey => $List) {
$Dizi[] = $List["news_title"];
}
}
Çalışan bir örneği incelemek için codepen hesabıma bakabilirsiniz: https://codepen.io/ebykdrms/pen/yLKyLgX
codepen'den silinirse diye burada da kodları paylaşıyorum:
Diyelim ki şöyle bir html yapınız var:
<div id="content">
<div class="selectbox-wrapper">
<select name="product[]">
<option value=0 selected>ÜRÜN SEÇİNİZ</option>
</select>
<button>Sil</button>
</div>
<div class="button-wrapper">
<button disabled>+ Yeni Ekle</button>
</div>
</div>
Örnek olarak şöyle bir yapı kurulabilir:
// Seçilebilecek Ürünlerimiz
const products = [
{ id: 1, name: "Ürün 1" },
{ id: 2, name: "Ürün 2" },
{ id: 3, name: "Ürün 3" },
{ id: 4, name: "Ürün 4" }
];
// Seçilmiş ürünlerimizi tutacak bir dizi.
const selectedProducts = [];
/**************************************/
// DOM'dan kullanacağımız elementleri (başlangıçta hazır olanları) değişkenlere alıyoruz:
const $content = $("#content");
const $addNewProductButton = $content.find(".button-wrapper button").prop("disabled",true);
/**************************************/
// Bir selectbox'a istediğimiz ürünleri append edebildiğimiz fonksiyon:
function addProductsToSelectBox($selectbox, products) {
for(let i=0; i < products.length; i++) {
$selectbox.append('<option value="'+products[i].id+'">'+products[i].name+'</option>');
}
}
// Yeni select elementi ekleyen fonksiyon:
function addNewProductSelectBox($willCloneSelectBox) {
// Parametrelerden gelen elementi clone ediyoruz.
const $newProductSelectBox = $willCloneSelectBox.clone();
// Butonun üstüne bu klonu ekliyoruz.
$addNewProductButton.parent().before($newProductSelectBox.hide());
// Select elementinin bir fade efektiyle görünmesini sağlıyoruz.
$newProductSelectBox.fadeIn(300);
// Yeni bir select elementi geldiyse henüz seçim yapılmamıştır.
// Seçim yapılmamış bir select elementi varsa buton pasif olmalı.
$addNewProductButton.prop("disabled",true);
}
// Select elementinin yanındaki "Sil" butonuna tıklandığında...
$content.on("click",".selectbox-wrapper button", function(){
// Butonun kapsayan selectbox-wrapper elementini seçelim.
const $wrapper = $(this).closest(".selectbox-wrapper");
// Eğer bu tıklanan ilk selectbox ise (normalde olmamalı ama) silme fonksiyonu çalışmayacak.
if($wrapper.index()==0) return;
// Elementi direkt siliyoruz:
$wrapper.remove();
})
/**************************************/
// Başlangıçta elimizde olan ilk select elementine ürünleri ekliyoruz:
addProductsToSelectBox($content.find(".selectbox-wrapper > select"), products);
// "+ Yeni Ekle" butonuna tıklandığında...
$addNewProductButton.on("click",function(){
// Son eklenmiş olan .selectbox-wrapper klonlanarak yeni bir .selectbox-wrapper oluşturulacak:
addNewProductSelectBox($content.find(".selectbox-wrapper").last());
});
// Herhangi bir select elementinden seçim yapıldığında...
$content.on("change",".selectbox-wrapper select", function(){
// Değişim yaşanan select elementinin bize lazım verilerini alalım:
const selectboxIndex = $(this).parent().index();
const selectedValue = $(this).val();
const selectedText = $(this).find("option:selected").text();
// Eğer seçilen değer 0 ise (normalde olmamalı ama)
if(selectedValue=='0') {
// Boş bir select elementi olduğu için "+ Yeni Ekle" butonu pasif olacak.
$addNewProductButton.prop("disabled",true);
// selectedProducts dizindeki ilgili index'i boşaltıyoruz.
selectedProducts[selectboxIndex] = null;
// Fonksiyonun işi burada bitmiş olacağı için fonksiyonu sonlandırıyoruz.
return;
}
// selectedProducts dizisinin ilgili index'ine seçilen ürünü ekliyoruz.
selectedProducts[selectboxIndex] = { id: selectedValue, name: selectedText };
// selectedProducts dizisini kontrol edip, herhangi bir boş seçim var mı diye bakacağız.
for(let i=0; i<selectedProducts.length; i++) {
// Eğer seçim yapılmamış bir selectbox varsa buton pasif olmalı.
if(!selectedProducts[i]) {
$addNewProductButton.prop("disabled",true);
// Fonksiyonun işi burada bittiği için return ile fonksiyonu sonlandırıyoruz.
return;
}
// Fonksiyon bu satıra kadar gelebilmişse her şey yolundadır. Butonu aktif edebiliriz.
$addNewProductButton.prop("disabled",false);
}
});
Buradaki selectedProduct dizisine muhtemelen sizin ihtiyacınız yoktur.
Ben yazmayı özlemişim, yazdıkça yazdım... Kurgusal olarak kendinize bir örnek çıkarabilirsiniz umarım.
Facebook size bir API sağlıyor. Bu API'nin özelliklerini bilmiyorum ama muhtemelen erişim yetkiniz olan verilere bu API ile ulaşabilirsiniz.
https://apikutuphanesi.com/facebook-api-nedir
// $i=1 ve $x=0 olduğu durum:
for ($i = 1; 1 <= 9; $i++) {
for (0; 0 <= 400; $x += 200) {
switch (1) { /* $i değeri 3 veya 6 olmadığı için switch koşulu sağlanmadı*/ }
echo "i: 1<br>";
$img->crop(200, 200, 0, 0)->save('img/shared-photos/1.jpg');
}
}
// $i=1 ve $x=200 olduğu durum:
for ($i = 1; 1 <= 9; $i++) {
for (200; 200 <= 400; $x += 200) {
switch (1) { /* $i değeri 3 veya 6 olmadığı için switch koşulu sağlanmadı*/ }
echo "i: 1<br>";
$img->crop(200, 200, 200, 0)->save('img/shared-photos/1.jpg');
}
}
// $i=1 ve $x=400 olduğu durum:
for ($i = 1; 1 <= 9; $i++) {
for (400; 400 <= 400; $x += 200) {
switch (1) { /* $i değeri 3 veya 6 olmadığı için switch koşulu sağlanmadı*/ }
echo "i: 1<br>";
$img->crop(200, 200, 400, 0)->save('img/shared-photos/1.jpg');
}
}
// $i=1 ve $x=600 olduğu durum:
for ($i = 1; 1 <= 9; $i++) {
for (600; 600 <= 400; $x += 200) { /* $x değeri 400'den büyük olduğu için for koşulu sağlanmadı */ }
}
// $i=2 ve $x=600 olduğu durum:
for ($i = 1; 2 <= 9; $i++) {
for (600; 600 <= 400; $x += 200) { /* $x değeri 400'den büyük olduğu için for koşulu sağlanmadı */ }
}
// $i=3 ve $x=600 olduğu durum:
for ($i = 1; 3 <= 9; $i++) {
for (600; 600 <= 400; $x += 200) { /* $x değeri 400'den büyük olduğu için for koşulu sağlanmadı */ }
}
// $i=4 ve $x=600 olduğu durum:
for ($i = 1; 4 <= 9; $i++) {
for (600; 600 <= 400; $x += 200) { /* $x değeri 400'den büyük olduğu için for koşulu sağlanmadı */ }
}
Sorun şu ki;
$x değişkenine for içinde başlangıç değeri atamadığınız için her seferinde eski değerinden devam ediyor.
$x bir kez 400'ü geçtiğinde bir daha $x'i 0 yapacak bir komut satırına ulaşamıyor çünkü içteki döngü koşulu sağlanmadığı için switch sorgusuna ulaşılamıyor.
Aslında $i değeri 3 olduğunda döngü sonlanmıyor. $x değeri 600 olduğunda (yani içteki döngü 3 kez döndükten sonra) içteki döngünin koşulu sağlanmadığı için döngü geçersiz kalıyor.
Sizin bütün işlemleriniz de içteki döngüde olduğu için 3 kez çıktı elde edebilmiş oluyorsunuz.
Bu arada crop işlemi de aynı dosya adını birkaç kez kullanıyor. Yani içteki döngü ilk dönüşünde 1.jpg dosyası oluşuyor. İkinci dönüşünde yine 1.jpg dosyası oluşuyor. Üçüncü dönüşünde de yine 1.jpg dosyası oluşuyor. Tabi aynı dosya adı aynı klasörde olamayacağı için muhtemelen 2. ve 3. dönüşlerde 1.jpg dosyasının üzerine yazılyor.
Eğer içteki döngüde for($x=0; $x<=400; $x++) {
şeklinde $x değerini sıfırlayamayacaksanız (kurgunuz buna uygun değilse) baştan kurgulamalısınız. Çünkü bu şekliyle döngüler sağlıklı çalışıyor olsaydı bile aynı dosyayı tekrar tekrar yazma sorununuz olacaktı.
Sadece PHP ile yapacaksanız (her seçimde sayfa yenilenecek şekilde) bu <select>
elementlerini bir <form>
elementiyle sarmalayın. Bu form elementinin method
attribute'si post olsun.
Ayrıca her bir <select>
elementine onchange
attribute'si vererek değeri değiştiğinde form'un submit işlemi gerçekleştirmesini (form verilerini post yöntemiyle iletmesini) sağlayın.
Başlangıçta sadece ilk <select>
elementinin <option>
'ları PHP ile doldurulmuş olacak. Diğer <select>
elementleri boş olacak.
Diğer select elementleri sadece bir önceki select'in değeri alınabilmişse PHP tarafından doldurulacak.
<?php
// her bir select'in elemanlarını PHP dizilerinde tutuyoruz.
$car_select_1 = ["BMV","TOYOTA","MERCEDES"]; // İlk select'in elemanları baştan belli.
$car_select_2 = []; // İkinci select'in elemanları sadece ilk select'te seçim yapıldıysa doldurulacak.
$car_select_3 = []; // Üçüncü select'in elemanları sadece ikinci select'te seçim yapıldıysa doldurulacak.
$car_select_4 = []; // Dördüncü select'in elemanları sadece üçüncü select'te seçim yapıldıysa doldurulacak.
$select1 = ""; // 1.select'te seçilmiş olan değer. Şu an boş.
$select2 = ""; // 2.select'te seçilmiş olan değer. Şu an boş.
$select3 = ""; // 3.select'te seçilmiş olan değer. Şu an boş.
$select4 = ""; // 4.select'te seçilmiş olan değer. Şu an boş.
$allItems = []; // Tüm seçimler yapıldığında listelenecek araçların verilerini tutacak dizi.
// Eğer ilk select'te seçim yapılmışsa
if(isset($_POST["car_select_1"])) {
$select1 = $_POST["car_select_1"];
$car_select_2 = getSelectItems($select1, "select2"); // Bu fonksiyonu uydurdum. Burada $select1 verisini kullanarak ikinci select'e hangi verilerin geleceğini veritabanından çekmişsiniz ve $car_select_2 değişkenine atamışsınız gibi düşünün.
// $car_select_2 = ["1-Serisi", "2-Serisi", "3-Serisi"] gibi bir değer atanmış olmalı.
}
// Eğer ikinci select'te de seçim yapıldıysa ve birinci select'te seçilmiş olan değer belliyse (ilk if'e girilmiş olacağı için belli olmalı)
if($select1!="" && isset($_POST["car_select_2"]) && $_POST["car_select_2"]!="0") {
$select2 = $_POST["car_select_2"];
$car_select_3 = getSelectItems($select2, "select3"); // Bu fonksiyonla $select2 değerine bakılarak üçüncü select'te hangi veriler olacağı veritabanından çekiliyor.
// $car_select_3 = ["E81 - 2005 -> 2007", "E81 - 2008 -> 2010", "E81 - 2010 -> 2012"] gibi bir değer atanmış olmalı.
}
// Eğer ücüncü select'te de seçim yapıldıysa ve ilk iki select'in seçimleri de belliyse (ilk 2 if'e de girilmiş olacağına göre belli olmalı)
if($select1!="" && $select2!="" && isset($_POST["car_select_3"]) && $_POST["car_select_3"]!="0") {
$select3 = $_POST["car_select_3"];
$car_select_4 = getSelectItems($select3, "select4"); // Bu fonksiyonla $select3 değerine bakılarak dördücü select'te hangi veriler olacağı veritabanından çekiliyor.
// $car_select_4 = ["116i - 115HP", "120i - 230HP"] gibi bir değer atanmış olmalı.
}
// Eğer dördüncü select'te de seçim yapılmışsa artık ilgili verileri seçebiliriz.
if($select1!="" && $select2!="" && $select3!="" && isset($_POST["car_select_4"]) && $_POST["car_select_4"]!="0") {
$select4 = $_POST["car_select_4"];
$allItems = getItems($select1, $select2, $select3, $select4); // Burada da tüm seçimlere göre veritabanından listelenecek araçları getiren bir fonksiyon var.
}
// Böylece kaç tane seçim yapılmışsa ona göre verileri elimizde topladık.
// Artık bu verileri html'de göstermemiz için bütün veriler elimizde.
?>
<!-- select'lerin olduğu form elementi -->
<form method="post">
<select name="car_select_1" onchange="if(this.value != 0) { this.form.submit(); }">
<?php foreach($car_select_1 as $item) { ?>
<option <?=($item===$select1 ? "selected" : "")?> value="<?=$item?>"><?=$item?></option>
<?php } ?>
</select>
<select name="car_select_2" onchange="if(this.value != 0) { this.form.submit(); }">
<option value="0" disabled>Seçiniz</option>
<?php foreach($car_select_2 as $item) { ?>
<option <?=($item===$select2 ? "selected" : "")?> value="<?=$item?>"><?=$item?></option>
<?php } ?>
</select>
<select name="car_select_3" onchange="if(this.value != 0) { this.form.submit(); }">
<option value="0" disabled>Seçiniz</option>
<?php foreach($car_select_3 as $item) { ?>
<option <?=($item===$select3 ? "selected" : "")?> value="<?=$item?>"><?=$item?></option>
<?php } ?>
</select>
<select name="car_select_4" onchange="if(this.value != 0) { this.form.submit(); }">
<option value="0" disabled>Seçiniz</option>
<?php foreach($car_select_4 as $item) { ?>
<option <?=($item===$select4 ? "selected" : "")?> value="<?=$item?>"><?=$item?></option>
<?php } ?>
</select>
</form>
<!-- Seçilen içeriğin gösterileceği alan -->
<div>
<?php if(count($allItems)==0) { ?>
<div>Tüm select'lerde seçim yaptıktan sonra burada içerik görüntülecenek.</div>
<?php } else { ?>
<?php foreach($allItems as $item) { ?>
<div><?=print_r($item)?></div>
<?php } ?>
<?php } ?>
</div>
Kodları test etmedim. Kurgusal olarak böyle bir yapı kullanabilirsiniz.
<select>
elementlerindeki onchange
attribute'leri sayesinde herhangi bir elementte değişiklik olduğunda kapsayıcı form verileri aynı sayfaya post ediyor. Biz de sayfanın başında post edilmiş verilere göre gereken aksiyonu alıyoruz.
Kısaca cookie değiştirme işini ayrı bir sayfada yapın ve cookie oluştuktan sonra kullanıcıyı geldiği sayfaya geri gönderin.
Sayfa yenilenmiş olacağı için cookie değeri de direkt okulabilir.