Veritabanı Modeli Model Kullanımı (Laravel Tarzı)
webman modeli, Eloquent ORM üzerine kuruludur. Her veritabanı tablosunun, bu tablo ile etkileşimde bulunmak için bir "modeli" vardır. Model aracılığıyla veritabanındaki verileri sorgulayabilir ve yeni kayıtlar ekleyebilirsiniz.
Başlamadan önce, veritabanı bağlantısını config/database.php
içinde yapılandırdığınızdan emin olun.
Dikkat: Eloquent ORM'in model gözlemcilerini desteklemesi için ekstra olarak
composer require "illuminate/events"
yüklemeniz gerekmektedir. örnek
Veritabanı Model Örneği
<?php
namespace app\model;
use support\Model;
class User extends Model
{
/**
* Model ile ilişkili olan tablo adı
*
* @var string
*/
protected $table = 'user';
/**
* Birincil anahtarı yeniden tanımlama, varsayılan olarak id'dir
*
* @var string
*/
protected $primaryKey = 'uid';
/**
* Zaman damgalarının otomatik olarak yönetilip yönetilmeyeceğini gösterir
*
* @var bool
*/
public $timestamps = false;
}
Tablo Adı
Özel bir veritabanı tablosunu belirtmek için model üzerinde table özelliğini tanımlayabilirsiniz:
class User extends Model
{
/**
* Model ile ilişkili olan tablo adı
*
* @var string
*/
protected $table = 'user';
}
Birincil Anahtar
Eloquent, her veritabanı tablosunun id adında bir birincil anahtar sütunu olduğunu varsayar. Varsayımları geçersiz kılmak için korumalı bir $primaryKey özelliği tanımlayabilirsiniz.
class User extends Model
{
/**
* Birincil anahtarı yeniden tanımlama, varsayılan olarak id'dir
*
* @var string
*/
protected $primaryKey = 'uid';
}
Eloquent, birincil anahtarın otomatik artan bir tamsayı olduğunu varsayar, bu da varsayılan olarak birincil anahtarın otomatik olarak int türüne dönüştürüleceği anlamına gelir. Eğer otomatik artan veya sayısal olmayan bir birincil anahtar kullanmak istiyorsanız, kamuya açık $incrementing özelliğini false olarak ayarlamanız gerekir.
class User extends Model
{
/**
* Model birincil anahtarının artan olup olmadığını gösterir
*
* @var bool
*/
public $incrementing = false;
}
Eğer birincil anahtarınız bir tamsayı değilse, model üzerindeki korumalı $keyType özelliğini string olarak ayarlamanız gerekir:
class User extends Model
{
/**
* Otomatik artan ID'nin "tipi".
*
* @var string
*/
protected $keyType = 'string';
}
Zaman Damgaları
Varsayılan olarak, Eloquent tablonuzda created_at ve updated_at sütunlarının var olduğunu bekler. Eğer Eloquent'in bu iki sütunu otomatik olarak yönetmesini istemiyorsanız, modeldeki $timestamps özelliğini false olarak ayarlayın:
class User extends Model
{
/**
* Zaman damgalarının otomatik olarak yönetilip yönetilmeyeceğini gösterir
*
* @var bool
*/
public $timestamps = false;
}
Eğer zaman damgalarının formatını özelleştirmek isterseniz, modelinizde $dateFormat özelliğini ayarlayın. Bu özellik, tarih özniteliklerinin veritabanında nasıl saklanacağını ve modelin bir dizi veya JSON olarak serileştirilme formatını belirler:
class User extends Model
{
/**
* Zaman damgalarının saklanma formatı
*
* @var string
*/
protected $dateFormat = 'U';
}
Eğer zaman damgalarını saklamak için özel alan adlarını özelleştirmek isterseniz, modeldeki CREATED_AT ve UPDATED_AT sabitlerinin değerlerini ayarlayarak gerçekleştirebilirsiniz:
class User extends Model
{
const CREATED_AT = 'creation_date';
const UPDATED_AT = 'last_update';
}
Veritabanı Bağlantısı
Varsayılan olarak, Eloquent modelleri uygulamanızda yapılandırılan varsayılan veritabanı bağlantısını kullanır. Eğer model için farklı bir bağlantı belirtmek isterseniz, $connection özelliğini ayarlayın:
class User extends Model
{
/**
* Modelin bağlantı adı
*
* @var string
*/
protected $connection = 'connection-name';
}
Varsayılan Özellik Değerleri
Eğer modelin bazı özelliklerine varsayılan değer tanımlamak istiyorsanız, modelde $attributes özelliğini tanımlayabilirsiniz:
class User extends Model
{
/**
* Modelin varsayılan özellik değerleri.
*
* @var array
*/
protected $attributes = [
'delayed' => false,
];
}
Model Sorgulama
Modeli ve ilişkili veritabanı tablosunu oluşturduktan sonra, veritabanından veri sorgulayabilirsiniz. Her Eloquent modelini, ilişkili olduğu veritabanı tablosu ile daha hızlı sorgulamak için güçlü bir sorgu oluşturucu
olarak düşünebilirsiniz. Örneğin:
$users = app\model\User::all();
foreach ($users as $user) {
echo $user->name;
}
İpucu: Eloquent modelleri de bir sorgu oluşturucu olduğundan, sorgu oluşturucu ile kullanılabilecek tüm yöntemleri de okumalısınız. Bu yöntemleri Eloquent sorgularında kullanabilirsiniz.
Ek Kısıtlamalar
Eloquent'in all yöntemi, modeldeki tüm sonuçları döndürür. Her Eloquent modeli, sorgu oluşturucu görevi gördüğü için sorgu koşulları ekleyebilir ve ardından sonuçları almak için get yöntemini kullanabilirsiniz:
$users = app\model\User::where('name', 'like', '%tom')
->orderBy('uid', 'desc')
->limit(10)
->get();
Modeli Yeniden Yükleme
Modeli yeniden yüklemek için fresh ve refresh yöntemlerini kullanabilirsiniz. fresh yöntemi modeli veritabanından yeniden alır. Mevcut model örnekleri etkilenmez:
$user = app\model\User::where('name', 'tom')->first();
$fresh_user = $user->fresh();
refresh yöntemi, mevcut modelin yeni verilerle yeniden atanmasını sağlar. Ayrıca, daha önceden yüklenmiş ilişkiler yeniden yüklenir:
$user = app\model\User::where('name', 'tom')->first();
$user->name = 'jerry';
$user = $user->fresh();
$user->name; // "tom"
Koleksiyon
Eloquent'in all ve get yöntemleri birden fazla sonuç sorgulayabilir ve bir Illuminate\Database\Eloquent\Collection
örneği döndürür. Collection
sınıfı, Eloquent sonuçlarını işlemek için birçok yardımcı işlev sağlar:
$users = $users->reject(function ($user) {
return $user->disabled;
});
İmleç Kullanımı
cursor yöntemi, veritabanı üzerinde imleç kullanmanızı sağlar ve yalnızca bir kez sorgu yürütür. Büyük veri işleme sırasında, cursor yöntemi bellek kullanımını büyük ölçüde azaltabilir:
foreach (app\model\User::where('sex', 1)->cursor() as $user) {
//
}
cursor Illuminate\Support\LazyCollection
örneğini döndürür. Lazy collections Laravel koleksiyonundaki çoğu koleksiyon yöntemini kullanmanıza izin verir ve her seferinde yalnızca bir modeli belleğe yükler:
$users = app\model\User::cursor()->filter(function ($user) {
return $user->id > 500;
});
foreach ($users as $user) {
echo $user->id;
}
Selects Alt Sorguları
Eloquent, ilgili tablolardan bilgi çekmek için gelişmiş alt sorgu desteği sağlar. Örneğin, destinations adında bir varış yeri tablosu ve flights adında varış noktasına uçuşları içeren bir tablo olduğunu varsayalım. flights tablosu, uçuşun varış noktasına ne zaman ulaşacağını gösteren bir arrival_at sütununu içerir.
Alt sorgu işleviyle sağlanan select ve addSelect yöntemlerini kullanarak, tek bir ifadeyle tüm destinasyonları sorgulayabilir ve her bir varış noktasına ulaşan son uçuşun adını çekebilirsiniz:
use app\model\Destination;
use app\model\Flight;
return Destination::addSelect(['last_flight' => Flight::select('name')
->whereColumn('destination_id', 'destinations.id')
->orderBy('arrived_at', 'desc')
->limit(1)
])->get();
Alt Sorguya Göre Sıralama
Ayrıca, sorgu oluşturucunun orderBy fonksiyonu da alt sorguları destekler. Bu özellik sayesinde, tüm destinasyonları, son uçuşun hedefe varış zamanına göre sıralayabilirsiniz. Aynı zamanda, bu işlem veritabanında yalnızca tek bir sorgu gerçekleştirir:
return Destination::orderByDesc(
Flight::select('arrived_at')
->whereColumn('destination_id', 'destinations.id')
->orderBy('arrived_at', 'desc')
->limit(1)
)->get();
Tek Bir Model/Koleksiyon Sorgulama
Belirli bir veritabanı tablosundan tüm kayıtları almak dışında, find, first veya firstWhere yöntemlerini kullanarak tek bir kayıt sorgulayabilirsiniz. Bu yöntemler, bir model örneği döndürür, bir model koleksiyonu değil:
// Bir modeli birincil anahtar üzerinden bulma...
$flight = app\model\Flight::find(1);
// Sorgu koşuluna uyan ilk modeli bulma...
$flight = app\model\Flight::where('active', 1)->first();
// Sorgu koşuluna uyan ilk modeli hızlı bir şekilde bulma...
$flight = app\model\Flight::firstWhere('active', 1);
Birincil anahtar dizisini parametre olarak çağırarak find yöntemini de kullanabilirsiniz, bu yöntem eşleşen kayıtların bir koleksiyonunu döndürür:
$flights = app\model\Flight::find([1, 2, 3]);
Bazen, ilk sonucu bulmak istediğinizde ancak değeri bulamıyorsanız başka bir işlem gerçekleştirmek isteyebilirsiniz. firstOr yöntemi, sonucu bulduğunuzda ilk sonucu döndürür, ancak bulamazsa verilen geri çağrıyı çalıştırır. Geri çağrının döndürdüğü değer, firstOr yönteminin dönüş değeri olacaktır:
$model = app\model\Flight::where('legs', '>', 100)->firstOr(function () {
// ...
});
firstOr yöntemi, sorgulamak için de sütun dizilerini kabul eder:
$model = app\model\Flight::where('legs', '>', 100)
->firstOr(['id', 'legs'], function () {
// ...
});
"Bulunamadı" Hatası
Bazen model bulunamadığında bir istisna fırlatmak isteyebilirsiniz. Bu, denetleyiciler ve yönlendirmelerde oldukça faydalıdır. findOrFail ve firstOrFail yöntemleri, sorgunun ilk sonucunu alır ve eğer bulunamazsa, Illuminate\Database\Eloquent\ModelNotFoundException istisnasını fırlatır:
$model = app\model\Flight::findOrFail(1);
$model = app\model\Flight::where('legs', '>', 100)->firstOrFail();
Koleksiyonu Sorgulama
Koleksiyonu işlemekte de, sorgu oluşturucunun sağladığı count, sum ve max gibi yöntemleri ve diğer koleksiyon işlevlerini kullanabilirsiniz. Bu yöntemler, uygun ölçek değerlerini yalnızca bir model örneği değil:
$count = app\model\Flight::where('active', 1)->count();
$max = app\model\Flight::where('active', 1)->max('price');
Ekleme
Veritabanına yeni bir kayıt eklemek için önce yeni bir model örneği oluşturun, örneğe özelliklerini ayarlayın ve ardından save yöntemini çağırın:
<?php
namespace app\controller;
use app\model\User;
use support\Request;
use support\Response;
class FooController
{
/**
* Kullanıcı tablosuna yeni bir kayıt ekler
*
* @param Request $request
* @return Response
*/
public function store(Request $request)
{
// İsteği doğrula
$user = new User;
$user->name = $request->get('name');
$user->save();
}
}
created_at ve updated_at zaman damgaları otomatik olarak ayarlanacaktır (modelde $timestamps özelliği true olduğunda), manuel bir değer atamanıza gerek yoktur.
Güncelleme
save yöntemi, veritabanında zaten var olan bir modeli güncellemek için de kullanılabilir. Modeli güncellemek için önce onu almalı, güncellenmesi gereken özellikleri ayarlamalı ve ardından save yöntemini çağırmalısınız. Aynı zamanda, updated_at zaman damgası otomatik olarak güncellenecektir, bu yüzden manuel bir değer ayarlamanıza da gerek yoktur:
$user = app\model\User::find(1);
$user->name = 'jerry';
$user->save();
Toplu Güncelleme
app\model\User::where('uid', '>', 10)
->update(['name' => 'tom']);
Özellik Değişikliklerini Kontrol Etme
Eloquent, modelin iç durumunu kontrol etmek ve özelliklerinin ilk yüklendiğinden nasıl değiştiğini belirlemek için isDirty, isClean ve wasChanged yöntemlerini sağlar.
isDirty yöntemi, model yüklendikten beri herhangi bir özelliğin değiştirilip değiştirilmediğini belirler. Belirli bir özelliğin, kirlenip kirlenmediğini görmek için belirli bir özellik adı geçirebilirsiniz. isClean yöntemi ise isDirty'nın tersidir ve isteğe bağlı bir özellik parametresini de kabul eder:
$user = User::create([
'first_name' => 'Taylor',
'last_name' => 'Otwell',
'title' => 'Developer',
]);
$user->title = 'Painter';
$user->isDirty(); // true
$user->isDirty('title'); // true
$user->isDirty('first_name'); // false
$user->isClean(); // false
$user->isClean('title'); // false
$user->isClean('first_name'); // true
$user->save();
$user->isDirty(); // false
$user->isClean(); // true
wasChanged yöntemi, mevcut istek döngüsü içinde modelin en son kaydedildiğinde herhangi bir özelliğin değişip değişmediğini belirler. Belirli bir özelliğin değiştirilip değiştirilmediğini görmek için de özellik adlarını geçebilirsiniz:
$user = User::create([
'first_name' => 'Taylor',
'last_name' => 'Otwell',
'title' => 'Developer',
]);
$user->title = 'Painter';
$user->save();
$user->wasChanged(); // true
$user->wasChanged('title'); // true
$user->wasChanged('first_name'); // false
Toplu Atama
Yeni bir model kaydetmek için create yöntemini de kullanabilirsiniz. Bu yöntem, model örneğini döndürür. Ancak, kullanmadan önce model üzerinde fillable veya guarded özelliğini tanımlamanız gerekmektedir, çünkü tüm Eloquent modelleri varsayılan olarak toplu atamaya kapalıdır.
Kullanıcı, isteğe beklenmeyen HTTP parametreleri geçirdiğinde ve bu parametreler, veritabanındaki değişiklik gerektirmeyen alanları değiştirdiğinde toplu atama açığı oluşabilir. Örneğin: kötü niyetli bir kullanıcı, HTTP isteğiyle is_admin parametresini geçebilir ve bu parametreyi create yöntemine aktarabilir, bu işlemi yaparak kendisini yönetici olarak yükseltebilir.
Bu nedenle, başlamadan önce model üzerinde hangi özelliklerin toplu atamaya açık olduğunu tanımlamalısınız. Model üzerindeki $fillable özelliğini kullanarak bunu gerçekleştirebilirsiniz. Örneğin: Flight modelinin name özelliğinin toplu atamaya açık olmasını sağlamak için:
<?php
namespace app\model;
use support\Model;
class Flight extends Model
{
/**
* Toplu atamaya açık olan özellikler.
*
* @var array
*/
protected $fillable = ['name'];
}
Bir kez toplu atamaya açık özelliklerimizi ayarladıktan sonra, create yöntemiyle veritabanına yeni veri ekleyebiliriz. create yöntemi, kaydedilen model örneğini döndürecektir:
$flight = app\model\Flight::create(['name' => 'Flight 10']);
Eğer elinizde bir model örneği varsa, fill yöntemine bir dizi geçirerek değer atayabilirsiniz:
$flight->fill(['name' => 'Flight 22']);
$fillable, toplu atama için bir "beyaz liste" olarak düşünülebilir. Ayrıca $guarded özelliğini de kullanarak gerçekleştirebilirsiniz. $guarded özelliği, toplu atamaya kapalı olan bir dizi içerir. Yani, $guarded fonksiyonel açıdan daha çok bir "kara liste" gibi çalışır. Dikkat: yalnızca $fillable veya $guarded özelliklerinden birini kullanabilirsiniz, ikisini birden kullanamazsınız. Aşağıdaki örnekte, price özelliği dışındaki tüm özellikler toplu atamaya açık olabilecektir:
<?php
namespace app\model;
use support\Model;
class Flight extends Model
{
/**
* Toplu atamaya kapalı olan özellikler.
*
* @var array
*/
protected $guarded = ['price'];
}
Eğer tüm özelliklerin toplu atamaya açık olmasını istiyorsanız, $guarded özelliğini bir boş dizi olarak tanımlayabilirsiniz:
/**
* Toplu atamaya kapalı olan özellikler.
*
* @var array
*/
protected $guarded = [];
Diğer Oluşturma Yöntemleri
firstOrCreate / firstOrNew
Burada toplu atama için kullanabileceğiniz iki yöntem: firstOrCreate ve firstOrNew. firstOrCreate yöntemi, verilen anahtar/değer çiftleri ile veritabanındaki verileri eşleştirir. Eğer veritabanında model bulunamazsa, ilk parametredeki özelliklerle ve isteğe bağlı ikinci parametre ile bir kayıt ekleyecektir.
firstOrNew yöntemi, firstOrCreate yöntemine benzer şekilde verilen özelliklerle veritabanında kayıt arar. Ancak, eğer firstOrNew yöntemi eşleşen bir model bulamazsa, yeni bir model örneği döndürecektir. Dikkat: firstOrNew tarafından döndürülen model örneği henüz veritabanına kaydedilmemiştir, bunu kaydetmek için manuel olarak save yöntemi çağırmalısınız:
// Uçuşu adı ile bul, yoksa oluştur...
$flight = app\model\Flight::firstOrCreate(['name' => 'Flight 10']);
// Uçuşu adı ile bul veya 'delayed' ve 'arrival_time' alanlarını kullanarak oluştur...
$flight = app\model\Flight::firstOrCreate(
['name' => 'Flight 10'],
['delayed' => 1, 'arrival_time' => '11:30']
);
// Uçuşu adı ile bul, yoksa yeni bir örnek oluştur...
$flight = app\model\Flight::firstOrNew(['name' => 'Flight 10']);
// Uçuşu adı ile bul veya 'delayed' ve 'arrival_time' alanlarını kullanarak bir model örneği oluştur...
$flight = app\model\Flight::firstOrNew(
['name' => 'Flight 10'],
['delayed' => 1, 'arrival_time' => '11:30']
);
Bazen, mevcut bir modeli güncellemeyi ve eğer mevcut değilse yeni bir model oluşturmayı arzulayabilirsiniz. updateOrCreate yöntemi bu iki işlemi bir arada gerçekleştirir. firstOrCreate yöntemine benzer şekilde, updateOrCreate modeli kalıcı hale getirir, bu yüzden save() yöntemi çağırmaya gerek duymaz:
// Eğer Oakland'dan San Diego'ya bir uçuş varsa fiyatı 99 dolar olarak belirleyin.
// Eğer mevcut model ile eşleşen bir kayıt yoksa, oluşturun.
$flight = app\model\Flight::updateOrCreate(
['departure' => 'Oakland', 'destination' => 'San Diego'],
['price' => 99, 'discounted' => 1]
);
Model Silme
Model örneğini silmek için delete yöntemini çağırabilirsiniz:
$flight = app\model\Flight::find(1);
$flight->delete();
Birincil Anahtara Göre Model Silme
app\model\Flight::destroy(1);
app\model\Flight::destroy(1, 2, 3);
app\model\Flight::destroy([1, 2, 3]);
app\model\Flight::destroy(collect([1, 2, 3]));
Sorguya Göre Model Silme
$deletedRows = app\model\Flight::where('active', 0)->delete();
Modeli Kopyalama
Bir model örneğini kopyalamak için replicate yöntemini kullanabilirsiniz, bu yöntem yeni ve veritabanına kaydedilmeyen bir örneği göz önünde bulundurur. Model örneği birçok aynı özelliği paylaşıyorsa, bu yöntem oldukça kullanışlıdır.
$shipping = App\Address::create([
'type' => 'shipping',
'line_1' => '123 Example Street',
'city' => 'Victorville',
'state' => 'CA',
'postcode' => '90001',
]);
$billing = $shipping->replicate()->fill([
'type' => 'billing'
]);
$billing->save();
Model Karşılaştırması
Bazen iki modelin "aynı" olup olmadığını kontrol etmeniz gerekebilir. is yöntemi, iki modelin aynı birincil anahtara, tabloya ve veritabanı bağlantısına sahip olup olmadığını hızlı bir şekilde kontrol etmek için kullanılabilir:
if ($post->is($anotherPost)) {
//
}
Model Gözlemcileri
Referans olarak Laravel'deki Model Olayları ve Gözlemci
Dikkat: Eloquent ORM'in model gözlemcilerini desteklemesi için ekstra olarak composer require "illuminate/events"
yüklemeniz gerekmektedir.
<?php
namespace app\model;
use support\Model;
use app\observer\UserObserver;
class User extends Model
{
public static function boot()
{
parent::boot();
static::observe(UserObserver::class);
}
}
İşlemler
Ayrıca veritabanı işlemleri için bakın.