- Oluşan hatanın ne olduğunu bilmiyoruz.
- Anasayfadaki sosyal medya linklerinin hangi kod yapısıyla listelendiğini bilmiyoruz.
Evet, if
koşulu ile eğer veri yoksa PHP'nin olmayan değeri ekrana basmaya çalışmasını engellemek gerekir.
Örneğin aşağıdaki kod, Trying to access array offset on value of type null
şeklinde hata verebilir:
<a href="<?= $linkler["facebook"]["link"] ?>">FACEBOOK</a>
Şu şekilde kontrol edilmesi gerekir:
<?php if(isset($linkler["facebook"]["link"])) { ?>
<a href="<?= $linkler["facebook"]["link"] ?>">FACEBOOK</a>
<?php } ?>
Üst Not: @fatihkurtl benden önce cevap vermiş. Benim cevabım biraz daha farklı oldu. Her yiğidin yoğurt yiyişi farklı tabi. :) Aşağıda benim kendimce cevabım var:
~ Kişi makale oku linkine tıkladığında html sayfasını mı görecek?
~ Evet. Direkt html sayfasını görmeli. PHP'ye hiç iş ilişmemeli. Veritabanını meşgul etmemeli. Çünkü makaleler sürekli güncellenen, anlık işleme girmesi gereken içerik değildirler. Mesela bir e-ticaret sitesinde ürün detay sayfaları da böyledir. Buralarda nadiren yapılan güncellemeler olur. Bu durumda da yeni bir cache dosyası oluşturulur. Ama mesela kullanıcının sepeti, anlık olarak işlem görmesi gereken, hassas bir yerdir. Mutlaka veritabanından kontrolü gerekir.
~ HTML sayfası PHP sayfasına include mu edilecek?
~ Hayır. HTML sayfası direkt bir dosya olarak oluşturulmalı ve mesela FTP'yle sunucudaki dosyalarınıza baktığınızda html uzantılı bir dosya olarak görülebilmeli. PHP olmasa bile kendi başına çalışabilir bir dosya olmalı. Böyle bir çıktıyı nasıl üretebileceğinizi şimdilik geçiyorum ama aslında zor değil. Sayfayı oluşturdunuz diyelim. Bu sayfaya yönlendirme işlemi PHP .htaccess dosyası ile sağlanabilir. Dosyanın adı aslında url'deki adıdır. Mesela yapay-zekanin-yukselisi.html
adlı bir dosya. .htaccess
dosyasında uygun bir yönlendirmeyle kullanıcının bu sayfaya http://siteadi.com/makale/yapay-zekanin-yukselisi
url'siyle ulaşması sağlanmalı.
Örneğin bu dosyaları yönetim panelinden düzenledikten sonra /makaleler
adlı bir klasöre PHP yardımıyla kaydettiniz. Şu an /makaleler/yapay-zekanin-yukselisi.html
diye bir dosyanız var. Bu dosyaya, http://siteadi.com/makale/yapay-zekanin-yukselisi
linki ile ulaşılabilsin istiyorsunuz.
Sitenizin kök klasöründeki .htaccess dosyasında şu şekilde yönlendirme sağlayabilirsiniz:
RewriteEngine On
RewriteRule ^makale/(.+)/?$ /makaleler/$1.html [L,R=301]
Bu sayede kullanıcı http://siteadi.com/makale/yapay-zekanin-yukselisi
url'sini çağırırsa sunucu tarafından direkt /makaleler/yapay-zekanin-yukselisi.html
dosyasına yönlendirilir.
Tabi CodeIgniter, Laravel gibi framework'ler kullanıyorsanız bu cache mekanizmasının framework'ler içinde kendi çözümleri var.
~ Her makalenin html dosyası olmalı mı?
~ Evet. Her makalenin bir html dosyası olmalı. Tabi binlerce makale olduğunda bu sistemi de optimize etmek gerekir. Bu çok daha detaylı bir konu.
Elbette küçük çaplı projelerde bu kadar optimizasyona gerek yok. Anlık kullanıcı sayısının çok artabileceği, sunucunun isteklere yetişemeyebileceği projeler için tüm bunlar yapılmalı ama zaten anlık 10-15 kullanıcıdan yukarı pek çıkmayan bir proje için bu kadar uğraşmak gerekmez.
Aldığınız hata: foreach() argument must be of type array|object, bool given in ... on line 70
Yani 70. satırda foreach, array veya object değeri ararken bool değerle karşılaşmış.
Muhtemelen 70. satır dediği yer sizin <?php foreach($ust_yorumlar as $ust_yorum): ?>
satırınıza denk geliyordur.
Buna göre sanırım 67. satırınıza denk gelen $ust_yorumlar = yorumlar($mak_id, $ust_yorum_id);
satırınızda $ust_yorumlar
değişkeninize false
değeri atanıyor olabilir.
Ama genel olarak kurgunuzda bir sorun var. foreach
döngüsü içinde yorumlar()
fonksiyonunu çağırmamalısınız. Bu fonksiyon veritabanına istek atıyor. Bu durumda dönünün her adımında veritabanı isteği atmış oluyorsunuz.
Çözüm olarak, makaleye ait tüm yorumları tek seferde çekmelisiniz ve PHP ile bir obje oluşturarak bu yorumların hiyerarşisini düzenlemelisiniz.
Yani mesela "SELECT * FROM yorumlar INNER JOIN uyeler ON uyeler.uye_id = yorumlar.uye_id WHERE makale_id = :mak_id";
şeklinde tüm yorumları tek seferde veren tek bir sorgu.
Bu sorgunun sonucu $yorumlar
değişkenine aldınız varsayalım. Sonrasında mesela $duzenlenmisYorumlar
adlı boş bir dizi oluşturup, $yorumlar
dizinizde dolaşarak gerekli hiyerarşide yorumlarınızı yeni diziye aktarabilirsiniz.
<?php
$yorumlar = tumYorumlar($mak_id);
$duzenlenmisYorumlar = [];
foreach($yorumlar as $yorum) {
// Baktığımız yorumun üst yorumu yoksa, ana yorum olarak eklensin.
if($yorum['ust_yorum_id'] === 0) {
$duzenlenmisYorumlar[ 'yorum_'.$yorum['yorum_id'] ] = ['yorum'=>$yorum, 'alt_yorumlar'=>[]];
}
// Baktığımız yorumun üst yorumu varsa, o yorumun alt yorumu olarak eklensin
else {
$duzenlenmisYorumlar[ 'yorum_'.$yorum['yorum_id'] ]['alt_yorumlar'][] = $yorum;
}
}
?>
Artık foreach
ile dolaşıp yorumları dom'a basabilirsiniz.
<?php foreach($duzenlenmisYorumlar as $key=>$data) { ?>
<div class="ana_yorum" data-key="<?= $key ?>">
<div><?= $data['yorum']['yorum_adi'] ?></div>
<div><?= $data['yorum']['yorum_icerik'] ?></div>
<a href="#" class="mt-2">Cevapla</a>
<?php foreach($data['alt_yorumlar'] as $altYorum) { ?>
<div class="cevap_yorum">
<div><?= $altYorum['yorum_adi'] ?></div>
<div><?= $altYorum['yorum_icerik'] ?></div>
<a href="#" class="mt-2">Cevapla</a>
</div>
<?php } ?>
</div>
<?php } ?>
Uzun zamandır PHP kullanmıyorum. Yukarıdaki kodları test etmeden yazdım. Yani hatalı olabilir. Ama kurgusal olarak ne yapmaya çalıştığımı aşağı yukarı belli ediyordur.
Not: PHP'de string ifade belirtirken çift tırnak "
ve tek tırnak '
farklı amaçlarla kullanılır.
Eğer string ifade içinde değişken kullanmayacaksanız (Örn: "Benim adım $isim. Seninki ne?"
) tek tırnak kullanmalısınız. Çünkü PHP, çift tırnak içinde bir değişken olabileceğini varsayar. Ama tek tırnak içinde değişken aramaz. Çok çok küçük bir performans maliyeti olsa da, büyük çaplı projeler için milisaniyeler bile önemli olduğundan, alışkanlık kazanmak iyi olur.
Not: Yanlış anlamayın, bu notları size özel yazmıyorum. Ben cevaplarımda, herkesin okuyabileceğini düşünerek böyle detaylar paylaşıyorum. :)
Tamamen örnek bir senaryo üzerinden yazıyorum:
1) yorum_id | makale_id | uye_id | yorum_icerik | ust_yorum_id
diye bir sütun daha eklenebilir.
Ahmet bir yorum yazdı. yorum_id=1, ust_yorum_id=null
Mehmet, Ahmet'e cevap yazdı. yorum_id=2, ust_yorum_id=1
Ahmet, Mehmet'e cevap yazdı. yorum_id=3, ust_yorum_id=2
Hüseyin de Mehmet'e cevap yazdı. yorum_id=4, ust_yorum_id=2
Mehmet, Hüseyin'e cevap yazdı. yorum_id=5, ust_yorum_id=4
2) Sayfaya sadece makale basılır ve makale en hızlı şekilde kullanıcıya iletilir.
Sayfa yüklendikten sonra yorumları almak için sunucuya makale_id ile birlikte GET isteği atılır.
Not: Yorumlar sayfaya direkt PHP ile basılmaz.
Kullanıcı bu makaleyi görüntülemek istediğinde asıl amacı makaleyi görmektir.
Makale kullanıcıya en hızlı şekilde gösterilmelidir.
O yüzden yorumların da veritabanından çekilmesi, hizaya sokulması vs. ek işlemler için kullanıcı bekletilmez.
Not: Mümkünse yorumlar, sayfa yüklendikten sonra hemen istenmez.
Kullanıcı belki de makalede yorumları okuyacak kadar kalmayacak.
Sunucuya ne kadar az yük bindirirsek o kadar rahat ederiz.
O yüzden, kullanıcı scroll yapıp makalenin sonuna gelip yorumların bulunacağı kısma yaklaşırsa o zaman yorumlar için istek atılır.
Böylece belki sadece 3-5 cümle okuyup sayfadan çıkacak kullanıcılar için gereksiz yere veritabanına iş bindirmemiş oluruz.
Not: Sayfanın kendisi bile php olmamalıdır.
Makale metni oluşturulduktan sonra bir html dosyası olarak kaydedilmelidir.
Kullanıcılar bu makaleyi görüntülemek istediğinde makale verisi her istek atan kullanıcı için veritabanından sorgulanmamalıdır.
Makale bir kez html dosyası olarak kaydedilip (cache'lenip) kullanıcılara doğrudan bu html dosyası iletilmelidir.
3) Sunucu, yorumları makale_id ile veritabanından çektikten sonra yorumlar üzerinde -güvenlik tedbirleri hariç- ek bir işlem yapmadan front-end'e json formatında iletir.
Not: Bu yorumların sıralanması, hiyerarşik olarak hangi yorumun hangi yoruma cevap olarak verildiği vs. gibi işlemler için sunucu yorulmamalıdır.
Bir işlemi sunucu tarafında yapmamız gerekiyorsa muhtemelen güvenlik gerekçesiyle olur. Ama yorumların sıralanması bir güvenlik sorunu değil.
Bu tür işlemleri kullanıcının tarayıcısına, yani kullanıcının bilgisayarının işlemcisine yıkarak sunucumuzu gereksiz iş yükünden koruruz.
4) Front-end'de JavaScript ile yorumlar belli bir hiyerarşi içinde organize edilir ve DOM'a basılır.
Son Not: Araya girdiğim bu notlar, sunucunun çok sayıda kullanıcıyı kaldırabilecek halde tutulması için. 3-5 kullanıcı için sunucu çok hızlı cevaplar verebilir ama 1000 kullanıcı aynı anda istek attığında her biri için veritabanını ayrı php'yi ayrı yorarsak kullanıcıların yanıt alma süresi çok uzar. Kullanıcılar belki hemen görebileceği bir makaleyi -iş sırasına alındığı için- 3-5 saniye beklemek zorunda kalırlar. Ama sayfa html olarak hazırda tutuluyorsa kullanıcılar istek atınca sunucu sadece html dosyasını iletip sıradaki işleme geçebilir. Ayrıca veritabanıyla iletişim minimumda tutulursa güvenlik açığı riski de azaltılmış olur.
Güvenlik demişken tabi bu aşamalarda bazı güvenlik adımları da araya sokulmalı. Çünkü kullanıcıdan alınan bir input'un ekrana basılması güvenlik açısından titiz davranılması gereken bir konu.
const barcode = new window.BarcodeDetector({formats: ['qr_code', 'ean_13']});
yerine
const barcode = new BarcodeDetector({formats: ["qr_code","ean_13"]});
kullanılıp denenebilir. Yani window
kullanmadan...
Öncelikle, eğer amacın şifrelemeyse bunu front-end tarafında yapmamalısın.
Şu anda haftalık 6 milyon indirmesi olan crypto-js paketini kullanabilirsin.
https://www.npmjs.com/package/crypto-js
<link rel="stylesheet" href="//simgbb.com/2801/ibb.css">
Bu stil için de rel="preconnect"
kullanabilirsin.
Ayrıca yazmadan geçemeyeceğim: Çok reklam var.
Linke tıkladığınızda görünüyor. Ama sonra sayfa yenileniyor. Yeni sayfa yüklenene kadar geçen sürede butonu görüyorsunuz. Sonra sayfa yenilendiği için her şey ilk haline geri dönüyor.
Linke tıkladığınızda sayfanın yenilenmesi gerekiyorsa, sayfa yenilendikten sonra bir şekilde sayfanın yenilendiğini anlayıp butonu görünür yapmanız gerek.
linke tıkladığınızda aynı sayfaya "?idcek=..." şeklinde parametre gönderiyorsunuz ve aynı sayfaya bu parametreyle gelmiş oluyorsunuz. buradan anlayabilirsiniz.
js tarafında butonu display:none yapmadan önce, query string'te idcek parametresi var mı diye kontrol edebilirsiniz. Eğer varsa butonu display:none yapmazsınız.
Belirttiğiniz 3 satırlık js kodu yerine aşağıdaki script tag'ı içeriklerini yazıp deneyebilirsiniz.
getQueryParam fonksiyonunu ChatGPT'ye yazdırdım, test etmedim.
<script>
function getQueryParam(key) {
var regex = new RegExp('[?&]' + key + '(=([^&#]*)|&|#|$)');
var results = regex.exec(window.location.search);
if (!results) return null; // anahtar yoksa null döndür
if (!results[2]) return ''; // anahtara değer atanmamışsa veya "=" işareti yoksa boş string döndür
return decodeURIComponent(results[2].replace(/\+/g, ' '));
}
const thisProjectId = "<?=$yeniprojegoster['yeniproje_id']?>";
const queryString_cekId = getQueryParam('idcek');
if(queryString_cekId !== thisProjectId) { document.getElementById("firstHref").style.display = "none"; }
document.getElementById("secondHref").onclick = function() {
document.getElementById("firstHref").style.display = "block";
}
</script>
Bu script ile, sayfaya idcek parametresiyle gelinmiş mi ve bu parametrenin değeri php'deki $yeniprojegoster['yeniproje_id']
değeriyle aynı mı diye bakıyoruz.
Çok da detaylı inceleyemedim ama sanki şu satırların sıralaması hatalı:
// Bind variables to the prepared statement as parameters
mysqli_stmt_bind_param($stmt, "s", $param_username);
// Set parameters
$param_username = $username;
Yani $param_username
değişkenine henüz değer atamamışken bind etmeye çalışıyor olabilirsin. Bu da "?" karakteri yerine değer girilememesine neden oluyordur. Çünkü aldığın hata da "?" ile alakalı:
You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '?' at line 1
Şimdi örnek yazmam mümkün değil ama sanırım şu kütüphaneler yardımcı olabilir:
box-shadow için: react-native-neomorph-shadows
gradient için: react-native-linear-gradient
ChatGPT4'ten bu kütüphaneleri kullanarak bir örnek hazırlamasını istedim:
import React from 'react';
import { View, Text, TouchableOpacity } from 'react-native';
import LinearGradient from 'react-native-linear-gradient';
import { Neomorph } from 'react-native-neomorph-shadows';
const StyledButton = () => {
return (
<Neomorph
inner // <- enable shadow inside of neomorph
swapShadows // <- change zIndex of each shadow color
style={{
shadowRadius: 4,
borderRadius: 48,
backgroundColor: '#FFF',
width: 200,
height: 60,
alignItems: 'center',
justifyContent: 'center',
}}>
<TouchableOpacity
style={{
borderRadius: 48,
borderColor: '#FFF',
height: '100%',
width: '100%',
alignItems: 'center',
justifyContent: 'center',
}}
activeOpacity={0.6}>
<LinearGradient
colors={['#FFF2DC', '#FFF']}
style={{
position: 'absolute',
left: 0,
right: 0,
top: 0,
height: '100%',
borderRadius: 48,
}}
start={{ x: 0, y: 0 }}
end={{ x: 1, y: 0 }}/>
<Text style={{ color: '#CE7F41', fontWeight: 'bold' }}>Test Button</Text>
</TouchableOpacity>
</Neomorph>
);
};
export default StyledButton;
Ama tabi muhtemelen düzgün çalışmaz. GPT bu kütüphanelerin çok eski hallerinden örnek veriyor.
Ama sen kütüphanelerin dokümantasyonu üzerinden ihtiyacına uygun bi'şeyler yapabilirsin.
Bol bol YouTube videoları izleyip örnekleri kendin de tekrarlayarak öğrenmek...
Bir yazılım şirketinde işe girip gerekirse ücretsiz çalışarak işi uzmanlarından öğrenmek...
Dokümantasyonu takip etmek...
Hazine ve Maliye Bakanlığının 1Milyonİstihdam projesine katılıp js derslerini almak...
Udemy'den kurs alıp...
Bunların hepsi birer yol ama bir konuyu derinlemesine öğrenmek için bence en iyi yol onu öğretmek:
JS üzerine yazılar yazacağın bir blog sayfası aç ve js'nin nasıl kullanılabileceğiyle ilgili özgün içerikler üret. En az haftada 2 tane yayın oluştur.
Örneğin bir yayınında reduce fonksiyonunun ne şekillerde kullanılabileceğini örneklerle açıkla. Hiç JS bilmeyen birine JS öğretirmiş gibi yaz. Konu aldığın fonksiyonun tüm özelliklerini örneklerle açıklamanın yanında nasıl ilk görünen amacı dışında kullanılabileceğine dair de örnekler hazırlayıp temel mantığını iyice öğret.
JS üzerine "zero to hero" seti oluştur ve düzenli olarak içerik gir. Kaliteli ve özgün içerik üretmek birinci hedefin olsun.
Yani senin hedefin JS öğrenmek değil, hiç bilmeyen birini JS uzmanı yapacak özgün bir eğitim seti oluşturmak olsun.
Böyle bir eğitim içeriği oluştururken doğru ve kaliteli bir iş çıkarmak için fonksiyonları ve js mantığını derinlemesine inceleme mecburiyetinde kalacaksın ve tam olarak ne araştırman gerektiğini bileceksin. Çünkü başlangıçta konuyu sen de iyi bilmiyorsun ve hiç bilmeyen birinin neleri merak edebileceğine dair sağlam fikirlerin var.
Blog sitenin tasarımı çok önemli değil. Önemli olan içeriğin kalitesi. Bu nedenle herhangi bir ücretsiz blog sayfası sağlayıcı platform kullanabilirsin.
https://app.gitbook.com kullanmayı öğrenmeni ve içeriklerini buraya girmeni öneririm. İçeriklerini prototurk'tekine benzer şekilde markup dili kullanarak yazarsın ve github'la doğrudan entegre çalışabilirsin.
İngilizce kesinlikle gerekiyor. Onu geliştirmelisin. Hatta İngilizceyi çözünce orda da durmayıp başka bir dil daha öğrenmeni öneririm. Özellikle Araplarda (Arabistan, Katar) iyi para var. Zaten gelecekte de çok kullanacağız gibi görünüyor...