Selamlar değerli üyeler, AR-Ge ekibinden bendeniz Watnea. Özlediniz değil mi? Serimizi son zamanalarda uğraştığımız projelerden sebep devam ettiremiyorum elimden geldiğince böyle boş vakitleri yararınıza değerlendireceğim.
Sıfırdan İleri Seviye PHP serimizin #8 Bölümündeyiz. Bu konumda sizlere
Oturumlar, Hata Yönetimi ve Basit CRUD Uygulamasını göstereceğim. Eğitim sonunda yine bir projemiz olacak. Kendi not sitemizi yapacağız giriş sistemi yapacağız. Giriş yaptığımızda yetkilerimiz olacak. İyi okumalar
Öğrenim Hedefleri:
PHP'de oturum ve çerez yönetimini anlayacaksınız,
Hata yönetimi tekniklerini öğreneceksiniz,
Veritabanı bağlantısı kurabileceksiniz.
CRUD (Create, Read, Update, Delete) işlemlerini yapabileceksiniz.
Temel güvenlik önlemlerini uygulayabileceksiniz.
1. Oturum (Session) ve Çerez (Cookie) Yönetimi
Hedef: Kullanıcı oturumlarını yönetmeyi ve çerez kullanımını öğrenmek.
Session Nedir?: Session yani oturum, kullanıcının web sitesinde geçirdiği süre boyunca bilgilerin saklanmasını sağlar. Kullanıcı tarayıcısını kapattığında veya belirli bir süre işlem yapmadığında oturum sonlanır.
Session Mantığı Nedir?: Kullanıcı siteye girdiğinde benzersiz bir session ID oluşturulur. Bu ID genellikle çerez olarak kullanıcının tarayıcısında saklanır. Sunucu tarafında bu ID'ye ait bilgiler tutulur. Her sayfa isteğinde session ID kontrol edilir ve ilgili veriler yüklenir
KOD:
PHP:
<?php
// Session başlatma
session_start();
// Session değişkenlerine değer atayalım
$_SESSION['kullanici_adi'] = 'watnea';
$_SESSION['email'] = '[email protected]';
// Session değişkenlerini okumak için
echo "Hoş geldiniz, " . $_SESSION['kullanici_adi'];
// Session değişkenini silelim
unset($_SESSION['email']);
// Tüm session'ı sonlandırma
session_destroy();
?>
Anlamadın mı? Dert değil ben anlatırım
COOKİE
Cookie Nedir?: Cookie yani çerez, kullanıcının bilgisayarında saklanan küçük veri parçacıklarıdır. Session'dan farklı olarak kullanıcı tarafından silinene veya süresi dolana kadar saklanır. Çokta mantığı yok bu şekilde en net tabir olur.
Kod:
COOKİE
Cookie Nedir?: Cookie yani çerez, kullanıcının bilgisayarında saklanan küçük veri parçacıklarıdır. Session'dan farklı olarak kullanıcı tarafından silinene veya süresi dolana kadar saklanır. Çokta mantığı yok bu şekilde en net tabir olur.
Kod:
PHP:
<?php
// Çerez oluşturma zaman skalalı 1 saat
setcookie('kullanici_tercihi', 'koyu_tema', time() + 3600, "/");
// Çerezimizi okuyalım
if(isset($_COOKIE['kullanici_tercihi'])) {
echo "Tercihiniz: " . $_COOKIE['kullanici_tercihi'];
}
// Çerez silme süresi geçmiş olarak
setcookie('kullanici_tercihi', '', time() - 3600, "/");
?>
Çerezler anında göremezsiniz. Sayfa yenileme gerekir
Anladın mı? Olsun bir daha dinle:
2. Hata Yönetimi:
Hedef: PHP'de hata yakalama ve yönetim tekniklerini öğrenmek
Hata Yönetimi Nedir?: Uygulamanızın beklenmedik durumlarla karşılaştığında nasıl davranacağını kontrol etmenizi sağlar.
KOD:
PHP:
<?php
// bana tüm hataları göster
error_reporting(E_ALL);
// bana önemli hataları göster
error_reporting(E_ERROR | E_WARNING | E_PARSE);
// hta loglayalım
function hataLogla($hata) {
$log = date("Y-m-d H:i:s") . " - " . $hata . "\n";
file_put_contents('hata_log.txt', $log, FILE_APPEND);
}
// çzel hata işleyici
set_error_handler(function($seviye, $mesaj, $dosya, $satir) {
hataLogla("$mesaj - $dosya:$satir");
});
?>
Şimdi kısıtlı hata oluşturalım ki çıktı görelim:
KOD:
PHP:
<?php
// hata ayar
error_reporting(E_ALL);
// hata log
function hataLogla($hata) {
$log = date("Y-m-d H:i:s") . " - " . $hata . "\n";
file_put_contents('hata_log.txt', $log, FILE_APPEND);
echo "📝 Hata log dosyasına yazıldı: $hata<br>";
}
// hata işle
set_error_handler(function($seviye, $mesaj, $dosya, $satir) {
$hataMesaji = "SEVİYE $seviye: $mesaj - $dosya:$satir";
hataLogla($hataMesaji);
});
// hata yapalm
// tanımsız değişken
echo $tanimsizDegisken;
// sıfıra bölmek de bir hatadır.
echo 10 / 0; // HATA!
// olmayan fonksiyon çağıralım
olmayanFonksiyon(); // HATA!
echo "Bu satıra ulaşabilir misin?";
?>
Hata tetiklemede yapabiliriz ama ödev olsun. Manuel hata tetikleme kodu yapan olursa başarılı öğrenci olur
3. Veritabanı Bağlantısı ve CRUD İşlemleri
Hedef: PDO ile veritabanı bağlantısı kurmak ve CRUD işlemlerini öğrenmek.
PDO KOD:
PHP:
<?php
class Veritabani {
private $host = 'localhost';
private $dbname = 'mini_blog';
private $username = 'root';
private $password = '';
private $pdo;
public function __construct() {
try {
$this->pdo = new PDO(
"mysql:host={$this->host};dbname={$this->dbname}",
$this->username,
$this->password
);
$this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch(PDOException $e) {
die("Bağlantı hatası: " . $e->getMessage());
}
}
public function getConnection() {
return $this->pdo;
}
}
?>
CRUD KOD:
PHP:
<?php
class Veritabani {
private $host = 'localhost';
private $dbname = 'mini_blog';
private $username = 'root';
private $password = '';
private $pdo;
public function __construct() {
try {
$this->pdo = new PDO(
"mysql:host={$this->host};dbname={$this->dbname}",
$this->username,
$this->password
);
$this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch(PDOException $e) {
die("Bağlantı hatası: " . $e->getMessage());
}
}
public function getConnection() {
return $this->pdo;
}
}
?>
💻 CRUD İşlemleri Kodu:
php
<?php
class Yazilar {
private $pdo;
public function __construct($pdo) {
$this->pdo = $pdo;
}
// Yeni yazı ekleme
public function ekle($baslik, $icerik, $yazar) {
$sql = "INSERT INTO yazilar (baslik, icerik, yazar, tarih) VALUES (?, ?, ?, NOW())";
$stmt = $this->pdo->prepare($sql);
return $stmt->execute([$baslik, $icerik, $yazar]);
}
// Tüm yazıları getirme
public function tumunuGetir() {
$sql = "SELECT * FROM yazilar ORDER BY tarih DESC";
$stmt = $this->pdo->query($sql);
return $stmt->fetchAll(PDO::FETCH_ASSOC);
}
// Tek yazı getirme
public function getir($id) {
$sql = "SELECT * FROM yazilar WHERE id = ?";
$stmt = $this->pdo->prepare($sql);
$stmt->execute([$id]);
return $stmt->fetch(PDO::FETCH_ASSOC);
}
// yazı güncelleme
public function guncelle($id, $baslik, $icerik) {
$sql = "UPDATE yazilar SET baslik = ?, icerik = ? WHERE id = ?";
$stmt = $this->pdo->prepare($sql);
return $stmt->execute([$baslik, $icerik, $id]);
}
// Yazı silme
public function sil($id) {
$sql = "DELETE FROM yazilar WHERE id = ?";
$stmt = $this->pdo->prepare($sql);
return $stmt->execute([$id]);
}
}
?>
PHP:
class Veritabani {
private $host = 'localhost';
private $dbname = 'mini_blog';
private $username = 'root';
private $password = '';
private $pdo;
VERİTABANI İSMİ mini_blog oldu mesela .db ile config database uyuşmalı.
Güvenlik Rütuşları Messi'nin Top Sürüşü Kadar Güzel Konu
Hedef: Temel güvenlik önlemlerini uygulamak
Web Pentest ilk başlayanların ilk öğrendiği SQL açığını hemen kapatalım.
KOD:
PHP:
<?php
// SQL Injection'a açık kod yapısı bu
$id = $_GET['id'];
// Tehlikenin mimari
$sql = "SELECT * FROM yazilar WHERE id = $id";
// Güvendesiniz rahat olun çünkü watnea öğretiyor.
$id = $_GET['id'];
$sql = "SELECT * FROM yazilar WHERE id = ?";
$stmt = $pdo->prepare($sql);
$stmt->execute([$id]);
?>
Ana amaç: Kullanıcıdan gelen verileri güvenli hale getirmek ve kontrol etmek. Web güvenliği için hayati öneme sahip bu yüzden giriş doğrulama sistemi yapalım
Giriş Doğrulama Kod:
PHP:
<?php
function temizle($veri) {
$veri = trim($veri);
$veri = stripslashes($veri);
$veri = htmlspecialchars($veri);
return $veri;
}
function dogrulaEmail($email) {
return filter_var($email, FILTER_VALIDATE_EMAIL);
}
function dogrulaMetin($metin, $min = 1, $max = 255) {
$uzunluk = strlen($metin);
return ($uzunluk >= $min && $uzunluk <= $max);
}
$email = temizle($_POST['email']);
if(!dogrulaEmail($email)) {
echo "Geçersiz email!";
}
?>
Bunda zafiyet var mı? Var tabi ki php öğrendikçe ne kadar karmaşık olduğunu anlayacaksınız ama temel için kafidir. Zafiyetleri özel olarak ele alacağım.
CRUD Uygulaması
Proje Hedefi: Session yönetimi ve CRUD işlemlerini içeren basit bir blog uygulaması
Dosya Yapısı:
localhost üzerinden phpmyadmine gidin ve veritabanı oluşturalım neydi ismi? Okumazsan atlarsın git kodlara öğren gel.
Ardından sql girip aşağıda ki tabloyu atıyoruz.
Kod:
USE mini_blog;
CREATE TABLE yazilar (
id INT AUTO_INCREMENT PRIMARY KEY,
baslik VARCHAR(255) NOT NULL,
icerik TEXT NOT NULL,
yazar VARCHAR(100) NOT NULL,
tarih DATETIME DEFAULT CURRENT_TIMESTAMP
);
-- Test verisi ekle
INSERT INTO yazilar (baslik, icerik, yazar) VALUES
('Hoş Geldiniz!', 'Watnea php öğretiyor.', 'Admin'),
('PHP Öğreniyorum', 'Watnea php öğret artık!', 'Admin');
Dosya Yapısı:
index.php:
PHP:
<?php
error_reporting(E_ALL);
ini_set('display_errors', 1);
session_start();
echo "🔍 DEBUG: Session başlatıldı<br>";
$gerekliDosyalar = [
'config/database.php',
'classes/Yazilar.php'
];
foreach($gerekliDosyalar as $dosya) {
if(!file_exists($dosya)) {
die("❌ Eksik dosya: <strong>$dosya</strong> - Lütfen bu dosyayı oluşturun!<br>
📁 Klasör yapısı kontrol edin.");
} else {
echo "✅ Dosya mevcut: $dosya<br>";
}
}
try {
require_once 'config/database.php';
require_once 'classes/Yazilar.php';
echo "✅ Dosyalar başarıyla yüklendi<br>";
$db = new Veritabani();
echo "✅ Veritabanı bağlantısı oluşturuldu<br>";
$yazilar = new Yazilar($db->getConnection());
echo "✅ Yazilar sınıfı oluşturuldu<br>";
$tumYazilar = $yazilar->tumunuGetir();
echo "✅ Yazılar getirildi: " . count($tumYazilar) . " adet<br>";
} catch (Exception $e) {
die("❌ Hata: " . $e->getMessage());
}
?>
<!DOCTYPE html>
<html>
<head>
<title>Mini Blog</title>
<style>
body { font-family: Arial, sans-serif; max-width: 800px; margin: 0 auto; padding: 20px; }
.yazi { margin: 20px 0; padding: 15px; border: 1px solid #ddd; border-radius: 5px; }
.admin-menu { background: #f5f5f5; padding: 10px; margin: 10px 0; border-radius: 5px; }
a { color: #007bff; text-decoration: none; margin: 0 10px; padding: 5px 10px; }
a:hover { text-decoration: underline; background: #e9ecef; }
.debug-info { background: #fff3cd; padding: 10px; margin: 10px 0; border-radius: 5px; }
</style>
</head>
<body>
<h1>📝 Mini Blog</h1>
<div class="debug-info">
<strong>🔧 Debug Bilgisi:</strong><br>
- Session: <?php echo isset($_SESSION['admin']) ? 'Giriş yapılmış' : 'Giriş yapılmamış'; ?><br>
- Yazı Sayısı: <?php echo count($tumYazilar); ?><br>
- PHP Sürüm: <?php echo phpversion(); ?>
</div>
<div class="admin-menu">
<?php if(isset($_SESSION['admin'])): ?>
<strong>👋 Hoş geldiniz, <?php echo $_SESSION['admin']; ?>!</strong>
<a href="pages/yazi_ekle.php">➕ Yeni Yazı Ekle</a>
<a href="pages/logout.php">🚪 Çıkış Yap</a>
<?php else: ?>
<a href="pages/login.php">🔑 Giriş Yap</a>
<small>(Kullanıcı: admin, Şifre: 123456)</small>
<?php endif; ?>
</div>
<div class="yazilar">
<?php if(count($tumYazilar) > 0): ?>
<?php foreach($tumYazilar as $yazi): ?>
<div class="yazi">
<h2><?php echo htmlspecialchars($yazi['baslik']); ?></h2>
<p><?php echo nl2br(htmlspecialchars($yazi['icerik'])); ?></p>
<small>
✍️ Yazar: <?php echo htmlspecialchars($yazi['yazar']); ?> |
📅 Tarih: <?php echo date('d.m.Y H:i', strtotime($yazi['tarih'])); ?>
</small>
<?php if(isset($_SESSION['admin'])): ?>
<div style="margin-top: 10px;">
<a href="pages/yazi_duzenle.php?id=<?php echo $yazi['id']; ?>">✏️ Düzenle</a>
<a href="pages/yazi_sil.php?id=<?php echo $yazi['id']; ?>"
onclick="return confirm('Bu yazıyı silmek istediğinize emin misiniz?')">🗑️ Sil</a>
</div>
<?php endif; ?>
</div>
<?php endforeach; ?>
<?php else: ?>
<div class="yazi">
<p>📭 Henüz hiç yazı bulunmuyor.</p>
<?php if(isset($_SESSION['admin'])): ?>
<p><a href="pages/yazi_ekle.php">İlk yazınızı eklemek için tıklayın</a></p>
<?php else: ?>
<p>Yazı eklemek için lütfen giriş yapın.</p>
<?php endif; ?>
</div>
<?php endif; ?>
</div>
</body>
</html>
Yazilar.php:
PHP:
<?php
class Yazilar {
private $pdo;
public function __construct($pdo) {
$this->pdo = $pdo;
}
// Yeni yazı ekleme
public function ekle($baslik, $icerik, $yazar) {
$sql = "INSERT INTO yazilar (baslik, icerik, yazar, tarih) VALUES (?, ?, ?, NOW())";
$stmt = $this->pdo->prepare($sql);
return $stmt->execute([$baslik, $icerik, $yazar]);
}
// Tüm yazıları getirme
public function tumunuGetir() {
$sql = "SELECT * FROM yazilar ORDER BY tarih DESC";
$stmt = $this->pdo->query($sql);
return $stmt->fetchAll(PDO::FETCH_ASSOC);
}
// ek yazı getirme
public function getir($id) {
$sql = "SELECT * FROM yazilar WHERE id = ?";
$stmt = $this->pdo->prepare($sql);
$stmt->execute([$id]);
return $stmt->fetch(PDO::FETCH_ASSOC);
}
// Yazı güncelleme
public function guncelle($id, $baslik, $icerik) {
$sql = "UPDATE yazilar SET baslik = ?, icerik = ? WHERE id = ?";
$stmt = $this->pdo->prepare($sql);
return $stmt->execute([$baslik, $icerik, $id]);
}
// Yazı silme
public function sil($id) {
$sql = "DELETE FROM yazilar WHERE id = ?";
$stmt = $this->pdo->prepare($sql);
return $stmt->execute([$id]);
}
}
?>
database.php:
PHP:
<?php
class Veritabani {
private $host = 'localhost';
private $dbname = 'mini_blog';
private $username = 'root';
private $password = '';
private $pdo;
public function __construct() {
try {
$this->pdo = new PDO(
"mysql:host={$this->host};dbname={$this->dbname}",
$this->username,
$this->password,
[
PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8",
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
]
);
} catch(PDOException $e) {
die("❌ Veritabanı bağlantı hatası: " . $e->getMessage());
}
}
public function getConnection() {
return $this->pdo;
}
}
?>
auth.php:
PHP:
<?php
function adminGirisKontrol() {
if(!isset($_SESSION['admin'])) {
header('Location: login.php');
exit();
}
}
function adminGirisYap($kullanici_adi) {
$_SESSION['admin'] = $kullanici_adi;
$_SESSION['giris_zamani'] = time();
}
function adminCikisYap() {
session_destroy();
header('Location: ../index.php');
exit();
}
?>
login.php:
PHP:
<?php
session_start();
if(isset($_SESSION['admin'])) {
header('Location: ../index.php');
exit();
}
if($_SERVER['REQUEST_METHOD'] == 'POST') {
$kullanici_adi = $_POST['kullanici_adi'] ?? '';
$sifre = $_POST['sifre'] ?? '';
// Basit giriş kontrolü
if($kullanici_adi === 'admin' && $sifre === '123456') {
$_SESSION['admin'] = $kullanici_adi;
header('Location: ../index.php');
exit();
} else {
$hata = "Geçersiz kullanıcı adı veya şifre!";
}
}
?>
<!DOCTYPE html>
<html>
<head>
<title>Giriş Yap - Mini Blog</title>
<style>
body { font-family: Arial; max-width: 400px; margin: 100px auto; padding: 20px; }
.login-form { background: #f5f5f5; padding: 20px; border-radius: 5px; }
input[type="text"], input[type="password"] { width: 100%; padding: 10px; margin: 5px 0; }
button { background: #007bff; color: white; padding: 10px 20px; border: none; border-radius: 3px; }
.error { color: red; }
</style>
</head>
<body>
<h1>🔑 Giriş Yap</h1>
<?php if(isset($hata)): ?>
<div class="error">❌ <?php echo $hata; ?></div>
<?php endif; ?>
<div class="login-form">
<form method="post">
<p><strong>Kullanıcı Adı:</strong> admin</p>
<p><strong>Şifre:</strong> 123456</p>
<input type="text" name="kullanici_adi" placeholder="Kullanıcı Adı" required>
<input type="password" name="sifre" placeholder="Şifre" required>
<button type="submit">Giriş Yap</button>
</form>
</div>
<p><a href="../index.php">← Ana Sayfaya Dön</a></p>
</body>
</html>
logout.php:
PHP:
<?php
session_start();
session_destroy();
header('Location: ../index.php');
exit();
?>
yazi_duzenle.php:
JavaScript:
<?php
session_start();
require_once '../includes/auth.php';
adminGirisKontrol();
require_once '../config/database.php';
require_once '../classes/Yazilar.php';
$db = new Veritabani();
$yazilar = new Yazilar($db->getConnection());
// URL'den id parametresini al
$id = $_GET['id'] ?? 0;
$mevcutYazi = $yazilar->getir($id);
if(!$mevcutYazi) {
die("❌ Yazı bulunamadı!");
}
if($_SERVER['REQUEST_METHOD'] == 'POST') {
$baslik = trim($_POST['baslik']);
$icerik = trim($_POST['icerik']);
if(!empty($baslik) && !empty($icerik)) {
if($yazilar->guncelle($id, $baslik, $icerik)) {
header('Location: ../index.php');
exit();
} else {
$hata = "Yazı güncellenirken hata oluştu!";
}
} else {
$hata = "Lütfen tüm alanları doldurun!";
}
}
?>
<!DOCTYPE html>
<html>
<head>
<title>Yazı Düzenle - Mini Blog</title>
</head>
<body>
<h1>✏️ Yazı Düzenle</h1>
<?php if(isset($hata)): ?>
<div style="color: red;">❌ <?php echo $hata; ?></div>
<?php endif; ?>
<form method="post">
<p>
<label>Başlık:</label><br>
<input type="text" name="baslik" value="<?php echo htmlspecialchars($mevcutYazi['baslik']); ?>" style="width: 100%; padding: 8px;" required>
</p>
<p>
<label>İçerik:</label><br>
<textarea name="icerik" style="width: 100%; height: 200px; padding: 8px;" required><?php echo htmlspecialchars($mevcutYazi['icerik']); ?></textarea>
</p>
<button type="submit">Yazıyı Güncelle</button>
<a href="../index.php">İptal</a>
</form>
</body>
</html>
yazi_ekle.php
PHP:
<?php
session_start();
require_once '../includes/auth.php';
adminGirisKontrol();
require_once '../config/database.php';
require_once '../classes/Yazilar.php';
$db = new Veritabani();
$yazilar = new Yazilar($db->getConnection());
if($_SERVER['REQUEST_METHOD'] == 'POST') {
$baslik = trim($_POST['baslik']);
$icerik = trim($_POST['icerik']);
$yazar = $_SESSION['admin'];
if(!empty($baslik) && !empty($icerik)) {
if($yazilar->ekle($baslik, $icerik, $yazar)) {
header('Location: ../index.php');
exit();
} else {
$hata = "Yazı eklenirken hata oluştu!";
}
} else {
$hata = "Lütfen tüm alanları doldurun!";
}
}
?>
<!DOCTYPE html>
<html>
<head>
<title>Yazı Ekle - Mini Blog</title>
</head>
<body>
<h1>➕ Yeni Yazı Ekle</h1>
<?php if(isset($hata)): ?>
<div style="color: red;">❌ <?php echo $hata; ?></div>
<?php endif; ?>
<form method="post">
<p>
<label>Başlık:</label><br>
<input type="text" name="baslik" style="width: 100%; padding: 8px;" required>
</p>
<p>
<label>İçerik:</label><br>
<textarea name="icerik" style="width: 100%; height: 200px; padding: 8px;" required></textarea>
</p>
<button type="submit">Yazıyı Ekle</button>
<a href="../index.php">İptal</a>
</form>
</body>
</html>
yazi_sil.php:
PHP:
<?php
session_start();
require_once '../includes/auth.php';
adminGirisKontrol();
require_once '../config/database.php';
require_once '../classes/Yazilar.php';
$db = new Veritabani();
$yazilar = new Yazilar($db->getConnection());
$id = $_GET['id'] ?? 0;
if($id > 0) {
$yazilar->sil($id);
}
header('Location: ../index.php');
exit();
?>
Örnek Resimler:
@0x1A7 php öğrenmek istiyormuş selam gönderelim
Acele oldu mahrum bırakmamak adın hazırladım. Umarım faydanıza olmuştur. Klasik tarzımızda kapatalım.
Oy Asiye ile iyi forumlar
Son düzenleme:





