PHP kullanırsan sitenin header, footer gibi bölümlerini ayrı dosyalara ayırabilir ve sayfalarına bu dosyaları çağırabilirsin. Böylece bu dosyalarda yaptığın değişiklikler tüm sayfalara uygulanmış olur.
Örneğin:
header.php:
<header>
<img src="logo.png" />
<nav>
<a>Anasayfa</a>
<a>Hakkımızda</a>
<a>İletişim</a>
</nav>
</header>
footer.php:
<footer>
<nav>
<a>Sıkça Sorulan Sorular</a>
<a>Bilgilendirme Metni</a>
<a>Telefon: +90 123 456 78 90</a>
<a>E-posta: [email protected]</a>
</nav>
</footer>
Tüm sayfalarda aynı olan header ve footer bölümlerini bu şekilde 2 dosyaya ayırdım. Şimdi bu header ve footer'a sahip sayfalarımda header ve footer gelen yerleri silip yerlerine bu dosyaları çağırabilirim.
anasayfa.php
<html>
<head>
<title>Ana Sayfa</title>
</head>
<body>
<?php include("header.php"); ?>
<section id="content">
<h1>Merhaba Dünya</h1>
<p>Burası ana sayfanın içeriği</p>
</section>
<?php include("footer.php"); ?>
</body>
</html>
Aynı şekilde hakkımızda sayfası:
hakkimizda.php
<html>
<head>
<title>Hakkımızda</title>
</head>
<body>
<?php include("header.php"); ?>
<section id="content">
<img src="hakkimizda-banner.png" />
<h1>Biz Kimiz?</h1>
<p>lorem ipsum dolor sit amet</p>
</section>
<?php include("footer.php"); ?>
</body>
</html>
Böylece hem sayfalarda koca koca yer tutan header ve footer kısımlarını birer satıra indirmiş olduk, hem de mesela header.php dosyasında yapacağımız bir değişikliği bu dosyanın çağırıldığı tüm sayfalarda aktif edebiliyor olduk.
Son kullanıcı sayfa kaynağını görüntülediğinde PHP kodlarını görmez. Çünkü sunucu, sayfayı son kullanıcıya göndermeden önce dosyaları birleştirir. Yani son kullanıcı mesela ana sayfanın kaynağını görüntülemek istediğinde şununla karşılaşır:
<html>
<head>
<title>Ana Sayfa</title>
</head>
<body>
<header>
<img src="logo.png" />
<nav>
<a>Anasayfa</a>
<a>Hakkımızda</a>
<a>İletişim</a>
</nav>
</header>
<section id="content">
<h1>Merhaba Dünya</h1>
<p>Burası ana sayfanın içeriği</p>
</section>
<footer>
<nav>
<a>Sıkça Sorulan Sorular</a>
<a>Bilgilendirme Metni</a>
<a>Telefon: +90 123 456 78 90</a>
<a>E-posta: [email protected]</a>
</nav>
</footer>
</body>
</html>
Böylece bir back-end dili olarak PHP'ye de giriş yapmış olursun.
PHP'yi kurmak da öğrenmek de (diğer back-end dillerine göre) kolaydır.
1) https://www.apachefriends.org/tr adresinden bilgisayarına XAMPP'i kurarsın. Kurulumda yardımcı olması için şu videonun ilk 2 dakikasını da izleyebilirsin: https://www.youtube.com/watch?v=mg-588VDyuI
2) XAMPP kontrol panelinden Apache sunucusunu aktif ettiğinde artık bilgisayarın bir sunucu haline gelir.
3) C:/xampp/htdocs senin sunucunun kök klasörü. Web sitelerini burada barındıracaksın. Buraya mesela testsitem diye bir klasör aç. İçine de, senin üzerinde çalıştığın web sitesinin html/css/js dosyalarını at.
4) Tarayıcını açıp localhost/testsitem adresine gittiğinde html web sitenin dosyalarına erişebildiğini göreceksin. (Varsayılan olarak index.html sayfası açılacaktır)
5) Tüm html uzantılı sayfalarının uzantılarını php olarak değiştir. Örn: index.html > index.php olsun.
6) Tüm sayfalardaki linkleri de yeni dosya adına göre düzenlemen gekerecek. Örn: <a href="hakkimizda.html">Hakkımızda</a> link'i, dosya uzantısı değiştiği için dosyayı bulamayacaktır. Buradaki html uzantısını da php olarak değiştir.
Böylece web siten tamamen PHP alt yapısına taşınmış oldu. Bundan sonraki tüm web sitelerini bu htdocs klasörü altında klasörler açarak geliştirebilirsin. Yukarıda verdiğim örnekteki gibi siteni bileşenlerine ayırıp birleştirebilirsin.
Başlangıçta bunlar "ooo çok iş" dedirtebilir. Ama 1-2 projende ısrar edip PHP kullanırsan aslında işini çok rahatlattığını göreceksin. Derinlemesine PHP bilmede de gerek yok. Aslında tek kullandığın komut <?php include("header.php") ?> şeklindeki tek satırlık komut.
Not: Sen PHP'yi hiç kullanmamış olabilirsin veya PHP'yi iyi biliyor da olabilirsin. Ben bu konuda soru işaretleri olanlara fikir vermek için bu kadar ayrıntılı bir cevap yazıyorum. :)
Vue, React gibi bir yapı kullanmak basit projelerde yorucu olur çünkü modüllerin internetten inmesini beklemek, güncellenen sürümlerin henüz güncellenmemişlerle uyumsuzluğu, projenin çalışmak için derlenmeye ihtiyaç duyması...
Bilgisayarına apache sunucusu kurarak php ile site geliştirmek her türlü bilgisayarına nodejs sunucusu kurup react ile site geliştirmekten daha kolay ve hızlıdır.
Sen de muhtemelen birbiriyle pek benzerliği olmayan farklı farklı siteleri hızlıca geliştirebilmek/düzenleyebilmek istiyorsun. Önerim: PHP.
Tabi tüm dosya uzantılarındaki ve dosya içeriklerindeki html'nin php'ye çevrilmesi zaman alıcı. Ama PHP'de biraz ilerlersen veya Chat GPT'den yardım alırsan bu değişikliği senin için otomatik olarak yapan bir php dosyası oluşturabilirsin. :) Bu dosyayı çağırdığında PHP senin için tüm dosya uzantılarını ve linkerde geçen .html ifadelerini php'ye çevirir. Nitekim, PHP candır. :)
Bu liste oluşturulurken de bu işlem yapılabilir, oluşturulduktan sonra da yapılabilir.
Ben oluşturuluktan sonra, yani DOM'a yukarıdaki ul (ve içindekiler) eklendikten sonra çalıştırılacak bir kod örneği vereceğim.
// 1) Öncelikle ul'yi seçelim.
const $list = $('ul'); // daha ayrıntılı bir seçici kullanmak gerek tabi...
// 2) ul içindeki li'leri de seçelim.
const $listItems = $list.find('li');
// 3) Tüm li'leri dönerek incelememiz gerekecek:
$listItems.each(function (index, element) {
// 3.1) Şu an baktığımız li elementini seçelim.
const $item = $(element);
// 3.2) Bu li elementinin içindeki ilk span elementini seçelim.
const $firstSpan = $item.find('span').first();
// 3.3) Bu span elementinin "title" class'ı var mı?
const isFirstSpanTitle = $firstSpan.hasClass('title');
// 3.4) Eğer title class'ı yoksa...
if(!isFirstSpanTitle) {
// 3.4.1) Baktığımız li elementinin data-id attribute'sini alalım.
const dataId = $item.attr('data-id');
// 3.4.2) Baktığımız li elementinin ilk elementi olarak BAŞLIK yazan, title class'ına sahip span'ımızı ekleyelim.
$item.prepend(`<span class="title" data-id="${dataId}">BAŞLIK</span>`);
}
});
Bu işlemleri tekrarlama ihtimaline karşı bunları bir fonksiyon haline getirmek daha uygun olacak:
// Fonksiyonumuz ul seçicisini ve başlık olarak yazılacak string'i parametrelerden alsın.
const fixTheList = (ulSelector, title="BAŞLIK") => {
// yukarıda yazdığım kodların aynısını ekliyorum.
// Fark sadece parametreden gelen değerlerin yerlerine yazılması...
const $list = $(ulSelector);
const $listItems = $list.find('li');
$listItems.each(function (index, element) {
const $item = $(element);
const $firstSpan = $item.find('span').first();
const isFirstSpanTitle = $firstSpan.hasClass('title');
if(!isFirstSpanTitle) {
const dataId = $item.attr('data-id');
$item.prepend(`<span class="title" data-id="${dataId}">${title}</span>`);
}
}
Bu fonksiyonu, ul elementi DOM'a eklendikten sonra çalıştırırsan title class'ına sahip span'ı olmayan tüm li elementlerine ilk element olarak bu span'ı ekler.
Fonksiyonu şu şekilde kullanabilirsin:
fixTheList('ul', "SONRADAN EKLENEN BAŞLIK");
Not: Kodları denemeden yazdım. Hatalı yazdığım yerler olabilir.
1. IP Kontrolü: PHP'de sadece web sitenin IP adresinden gelen isteklere yanıt verilmesini sağla.
$_SERVER['REMOTE_ADDR'] sana isteğin geldiği IP adresini verir. Bir if kontrolüyle, bu IP'den gelmeyen isteklere hata dönebilirsin.
Kullanıcı, header'dan giden IP bilgisini değiştirebilir ve isteği sitenden yapılmış gibi gösterebilir. Bu yüzden sadece bu koruma yeterli değil.
2. Token Kontrolü: CSRF açıklarından korunmak için iyidir. Front end önce PHP'ye istek atıp token alır ve bundan sonra yapacağı tüm isteklerde header üzerinden bu token'ı iletir. PHP, gelen isteğin header'ında bu token'ı kontrol eder.
Burada bahsettiğim token, PHP tarafında sadece senin bildiğin bir anahtar ile şifrelenmiş bir string ifade. Sana bu token ile bir istek yapıldığında elindeki anahtarla token'ı açtığında, senin token'ın içine koyduğun verilere ulaşamıyorsan servisine hata döndürebilirsin.
Kullanıcı anahtar olmadan bu token'ı kendisi üretemeyeceği için bir güvenlik sağlar. Ama kullanıcı siteye bir kez giriş yaptığında bir token elde edebileceğine göre bu token ile sunucuya yine isteklerde bulunabilir. Bu yüzden token'ların içine bir son kullanım tarihi de eklemek iyi olur. Ama bu token'ın kullanım süresi boyunca kullanıcı bu token ile sunucuya istekler atabilir. Ayrıca token süresi dolsa bile yine siteye girip yeni token bir alabilir. Yani bu koruma da tam olarak yeterli değil.
3. HTTPS: HTTPS protokolü, iletişimi şifreleyerek istekleri güvenli hale getirir. Bu nedenle, sadece HTTPS kullanımına izin vermek de ek bir güvenlik sağlar.
if (empty($_SERVER['HTTPS']) || $_SERVER['HTTPS'] === 'off') { // HTTPS ile istek yapılmamış... şeklinde bir kontrol eklenebilir.
Kullanıcı https üzerinden de istek atabilir. Bu da yeterli değil.
4. CAPTCHA: Botların otomatik isteklerini engellemek için kullanılan bir güvenlik önlemi olsun diye kullanılabilir. Bu sitede olduğu gibi...
Kullanıcı sitene girmeden de servisinin endpoint'lerine istek atabilir. Bu elbette senin soruna binaen yeterli bir önlem değil.
5. DDoS: Sunucu tarafında bu saldırıları önmelek için güvenlik duvarı kullanmak, tüm kaynakları kendi sitende barındırmak yerine cdn kullanmak iyi olabilir.
Bunun da doğrudan soruyla ilgisi yok ama yapmak iyi olur. Paylaşımlı sunucularda genelde bu hazırda vardır. Sunucu seninse bu kontrolleri de senin yapman gerekebilir.
Böyle şeyler... Bunlar geldi aklıma. Bunlar içinde özellikle token kullanmak, istenmeyen istekleri reddetmek için kullanılabilir. Çoğu sistem bu şekilde çalışıyor.
Sanki kütüphaneyi sayfaya çağıramıyor gibisin. Belki şu kodlar işe yarayabilir:
use ElephantIO\Client;
use ElephantIO\Engine\SocketIO\Version2X;
Eğer composer gibi bir bağımlılık yöneticisi kullanıyorsan kütüphaneyi yükleyip yüklemediğini kontrol edebilirsin:
composer require elephantio/elephantio
Bir de kütüphanenin doğru yolu (vendor/autoload.php) kullanılarak yüklendiğinden emin olmalısın.
Bu dosya, composer tarafından yüklenen bağımlılıkları otomatik olarak yüklemekten sorumlu.
Kodunun başına şu satırları ekleyerek bu dosyayı çağırabilirsin:
require __DIR__ . '/vendor/autoload.php';
.item {
width: 33%;
aspect-ratio: 1
}
Aşağıdaki kodu https://onlinephp.io sitesinde PHP sürümünü 5.6.40'a çekerek denediğimde sorunsuz çalışıyor.
<?php
date_default_timezone_set("Europe/Istanbul");
$array = "1234|4756|1|31.01.2023,5678|6453|2|01.02.2021,5678|6453|2|01.02.2022";
$fixedArray = [];
$groups = explode(",", $array);
// input ($array): "1234|4756|1|31.01.2023,5678|6453|2|01.02.2021"
// output ($groups): ["1234|4756|1|31.01.2023", "5678|6453|2|01.02.2021"]
foreach($groups as $group) $fixedArray[] = explode("|", $group);
// input ($groups): ["1234|4756|1|31.01.2023", "5678|6453|2|01.02.2023"]
// output ($fixedArray): [["1234", "4756", "1", "31.01.2023"], ["5678", "6453", "2", "01.02.2021"]]
usort($fixedArray, function ($a, $b) {
if(strtotime($a[3]) < strtotime($b[3])) return -1;
if(strtotime($a[3]) > strtotime($b[3])) return 1;
return 0;
});
// input ($fixedArray): [["1234", "4756", "1", "31.01.2023"], ["5678", "6453", "2", "01.02.2021"]]
// output ($fixedArray): [["5678", "6453", "2", "01.02.2021"], ["1234", "4756", "1", "31.01.2023"]]
print_r($fixedArray);
Eğer hem hata vermiyor hem de sıralama yapmıyorsa muhtemelen ekrana doğru değişkeni basmıyorsunuz veya yanlış zamanda basıyorsunuz veya tarihler karşılaştırma yaptığınız index'te (3.index) bulunmuyor. Kodlarınızı görmeden bu aşamadan sonra yanıt vermem zor.
Belki sorun date'tedir diyerek farklı bi'şey deneyebiliriz. date yerine doğrudan string üzerinde de tarih sıralaması yapabiliriz.
Eğer tarihi yıl-ay-gün şeklinde yyyy.mm.dd formatında bir string'e çevirirsek ve alfabetik olarak sıralamaya çalışırsak yine doğru tarih sıralamasına ulaşabiliriz.
Bunu da şu şekilde yapmak mümkün:
usort($fixedArray, function ($a, $b) {
$date1 = explode(".", $a[3]); // "01.02.2022" -> ["01", "02", "2022"]
$date1 = array_reverse($date1); // ["01", "02", "2022"] -> ["2022", "02", "01"]
$date1 = implode(".", $date1); // ["2022", "02", "01"] -> "2022.02.01"
$date2 = implode(".", array_reverse(explode(".", $b[3]))); // Üsttekinin tek satır hali
return strcmp($date1, $date2); // strcmp() fonksiyonu string ifadeleri karşılaştırır. Tam sort'un istediği şekilde -1, 0 veya 1 döner.
});
Bu kodları da aynı sitede denedim ve doğru şekilde tarihleri eskiden yeniye doğru sıralandı.
kullanıcı adres seçince devam et gübi bir butonu aktif etmekten bahsediyorsun sanırım.
diyorsun ki: kullanıcı kendisi dom'u manipule edip kendisi bir adres eklerse ve o adresi seçerse buton yine aktif olacak. o yüzden adres seçildiğinde adresin varlığını kontrol etmek için sunucuma istek atayım ve dönen sonuca göre butonu aktif edeyim.
doğru anladıysam,
böyle bir isteği atmana gerek yok. kullanıcı senin sunucuya istek atacağın fonksiyonu da manipule edebilir. veya sunucuya istek atmana fırsat vermeden butona kendisi de active class'ı verebilir veya disabled prop'unu false yapabilir. hatta kullanıcının bu işlemi yapması için web sitene girmesine bile gerek yok. sunucuna postman gibi bir program üzerinden doğrudan post isteği de atabilir. yani kötü niyetli kullanıcıyı o aşamada durduramazsın.
o yüzden sunucuya ek yük bibdirmene ve performans kaybı yaşamana gerek yok.
senin yapman gereken sayfada performansa odaklanmak olmalı. kullanıcı devam et butonuna bastıktan sonra sunucuya istek atmalısın. sunucu isteği karşıladığında önce adres seçilmiş mi diye bakar. sonra adresin varlığını kontrol eder. bu aşamalarda sorun varsa sonraki sayfayı göstermeden direkt hata sayfasına redirect edilir veya aynı sayfaya bir hata mesajıyla redirect edilir.
eğer sunucu kontrolünde bir sorun yoksa kullanıcı doğru sayfaya (sonraki aşamaya) benzersiz bir token ile redirect edilir. bu token içinde benzersizliği sağlayan bir şifre haricinde şifrelenmiş halde adres bilgisi de bulunur.
sonraki aşamada da sunucu önce token kontrolü yapar. token doğru değilse bu sayfaya kötü niyetli bir istek atılmış demektir. sunucu sayfayı göstermeden kullanıcıyı direkt hata sayfasına redirect eder. token doğruysa içindeki adres bilgisi okunur. böylece yeni sayfada adres bilgileri için yeniden veritabanına sorgu da atılmamış olur. veritabanına ne kadar az istek atılırsa o kadar iyi...
her bir devam et butonu olan sayfanda bu yöntemle ilerlersen hem front end'de performanstan ödün vermemiş olursun, hem veriyi token'larla taşıdığın için veritabanına yük bindirmemiş olursun, hem de kimse senin şifreleme anahtarını bilemeyeceği için istemediğin bir sayfaya erişemez.
Daha önce yazdığım cevabı düzenledim.
// Giriş verilerimiz:
$array = "1234|4756|1|31.01.2023,5678|6453|2|01.02.2021"
// Düzenlenmiş array'i tutacak değişkenimiz:
$fixedArray = [];
// Önce "," karakterinden gruplara ayırıyoruz:
$groups = explode(",", $array);
// input ($array): "1234|4756|1|31.01.2023,5678|6453|2|01.02.2021"
// output ($groups): ["1234|4756|1|31.01.2023", "5678|6453|2|01.02.2021"]
// Sonra her grubu kendi içinde "|" karakterinden ayırıyoruz:
foreach($groups as $group) $fixedArray[] = explode("|", $group);
// input ($groups): ["1234|4756|1|31.01.2023", "5678|6453|2|01.02.2023"]
// output ($fixedArray): [["1234", "4756", "1", "31.01.2023"], ["5678", "6453", "2", "01.02.2021"]]
// Düzenlenmiş grubumuzu tarihe göre küçükten büyüğe sıralıyoruz:
usort($fixedArray, fn($a, $b) => strtotime($a[3]) <=> strtotime($b[3]));
// input ($fixedArray): [["1234", "4756", "1", "31.01.2023"], ["5678", "6453", "2", "01.02.2021"]]
// output ($fixedArray): [["5678", "6453", "2", "01.02.2021"], ["1234", "4756", "1", "31.01.2023"]]
// Sonuç $fixedArray dizisinde bulunuyor:
print_r($fixedArray);
PHP'nin 7'den eski sürümlere uyumlu olması için usort() fonksiyonu şöyle de olabilir:
usort($fixedArray, function ($a, $b) {
if(strtotime($a[3]) < strtotime($b[3])) return -1;
if(strtotime($a[3]) > strtotime($b[3])) return 1;
return 0;
});
Almak istediğin değerlerin hepsini ayrı ayrı hesaplamalısın.
var ntime = new Date("2023-02-20 00:53:00");
var otime = new Date("2023-02-18 00:40:00");
var dtime = (ntime - otime)/(1000);
const days = Math.floor(dtime / (60*60*24)) + " gün";
const hours = Math.floor((dtime / (60*60)) % 24) + " saat";
const minutes = Math.floor((dtime / 60) % 60) + " dakika";
const seconds = Math.floor(dtime % 60) + " saniye";
const text = [days, hours, minutes, seconds].filter(x=>x.split(" ")[0]!=="0").join(" ");
// Çıktı: "2 gün 13 dakika"