SQL Yaklaşımı
Nette Database iki yol sunar: SQL sorgularını kendiniz yazabilir (SQL yaklaşımı) veya otomatik olarak oluşturulmalarını sağlayabilirsiniz (bkz. Explorer). SQL yaklaşımı size sorgular üzerinde tam kontrol sağlarken, güvenli bir şekilde oluşturulmalarını da garanti eder.
Veritabanı bağlantısı ve yapılandırmasıyla ilgili ayrıntıları Bağlantı ve Yapılandırma bölümünde bulabilirsiniz.
Temel Sorgulama
Veritabanına sorgu yapmak için query()
metodu kullanılır. Bu metot, sorgu sonucunu temsil eden bir ResultSet nesnesi döndürür. Başarısızlık
durumunda metot istisna fırlatır. Sorgu sonucunu foreach
döngüsüyle gezebilir veya
yardımcı fonksiyonlardan birini kullanabiliriz.
SQL sorgularına güvenli bir şekilde değer eklemek için parametreli sorgular kullanırız. Nette Database bunları son derece basit hale getirir – SQL sorgusundan sonra virgül ve değeri eklemeniz yeterlidir:
Birden fazla parametre olduğunda iki yazım seçeneğiniz vardır. SQL sorgusunu parametrelerle „serpiştirebilirsiniz“:
Veya önce tüm SQL sorgusunu yazıp sonra tüm parametreleri ekleyebilirsiniz:
SQL Injection'dan Korunma
Parametreli sorguları kullanmak neden önemlidir? Çünkü sizi, saldırganın kendi SQL deyimlerini ekleyerek veritabanındaki verilere erişebileceği veya zarar verebileceği SQL injection adlı saldırıdan korurlar.
Asla değişkenleri doğrudan SQL sorgusuna eklemeyin! Sizi SQL injection'dan koruyan parametreli sorguları her zaman kullanın.
Olası güvenlik riskleri hakkında bilgi edinin.
Sorgulama Teknikleri
WHERE Koşulları
WHERE koşullarını, anahtarların sütun adları ve değerlerin karşılaştırma için veriler olduğu ilişkisel bir dizi olarak yazabilirsiniz. Nette Database, değerin tipine göre en uygun SQL operatörünü otomatik olarak seçer.
Anahtarda karşılaştırma için operatörü açıkça belirtebilirsiniz:
Nette, null
değerleri veya diziler gibi özel durumları otomatik olarak işler.
Negatif koşullar için NOT
operatörünü kullanın:
Koşulları birleştirmek için AND
operatörü kullanılır. Bu, ?or yer
tutucu sembolü kullanılarak değiştirilebilir.
ORDER BY Kuralları
ORDER BY
sıralaması bir dizi kullanılarak yazılabilir. Anahtarlarda sütunları belirtiriz ve değer, artan
sırada sıralanıp sıralanmayacağını belirleyen bir boolean olur:
Veri Ekleme (INSERT)
Kayıt eklemek için INSERT
SQL deyimi kullanılır.
getInsertId()
metodu, son eklenen satırın ID'sini döndürür. Bazı veritabanlarında (örn. PostgreSQL),
ID'nin oluşturulacağı sıra adını $database->getInsertId($sequenceId)
kullanarak parametre olarak belirtmek
gerekir.
Parametre olarak dosyalar, DateTime nesneleri veya enum tipleri gibi özel değerler de iletebiliriz.
Aynı anda birden fazla kayıt ekleme:
Çoklu INSERT çok daha hızlıdır, çünkü birçok tekil sorgu yerine tek bir veritabanı sorgusu yürütülür.
Güvenlik uyarısı: Asla $values
olarak doğrulanmamış verileri kullanmayın. Olası riskler hakkında bilgi edinin.
Veri Güncelleme (UPDATE)
Kayıtları güncellemek için UPDATE
SQL deyimi kullanılır.
Etkilenen satır sayısı $result->getRowCount()
tarafından döndürülür.
UPDATE için +=
ve -=
operatörlerini kullanabiliriz:
Zaten varsa bir kaydı ekleme veya düzenleme örneği. ON DUPLICATE KEY UPDATE
tekniğini kullanıyoruz:
Nette Database'in, parametreyi dizi ile SQL deyiminin hangi bağlamına eklediğini tanıdığına ve buna göre SQL kodunu
oluşturduğuna dikkat edin. Yani ilk diziden (id, name, year) VALUES (123, 'Jim', 1978)
oluştururken, ikincisini
name = 'Jim', year = 1978
şekline dönüştürdü. Buna SQL Oluşturma
İpuçları bölümünde daha ayrıntılı olarak değiniyoruz.
Veri Silme (DELETE)
Kayıtları silmek için DELETE
SQL deyimi kullanılır. Silinen satır sayısını alma örneği:
SQL Oluşturma İpuçları
İpucu, parametre değerinin SQL ifadesine nasıl çevrileceğini belirten SQL sorgusundaki özel bir yer tutucu semboldür:
İpucu | Açıklama | Otomatik olarak kullanılır |
---|---|---|
?name |
tablo veya sütun adı eklemek için kullanılır | – |
?values |
(key, ...) VALUES (value, ...) üretir |
INSERT ... ? , REPLACE ... ? |
?set |
key = value, ... atamasını üretir |
SET ? , KEY UPDATE ? |
?and |
dizideki koşulları AND operatörüyle birleştirir |
WHERE ? , HAVING ? |
?or |
dizideki koşulları OR operatörüyle birleştirir |
– |
?order |
ORDER BY yan tümcesini üretir |
ORDER BY ? , GROUP BY ? |
Tablo ve sütun adlarını sorguya dinamik olarak eklemek için ?name
yer tutucu sembolü kullanılır. Nette
Database, tanımlayıcıların ilgili veritabanının kurallarına göre (örn. MySQL'de geri tırnak içine alma) doğru bir
şekilde işlenmesini sağlar.
Uyarı: ?name
sembolünü yalnızca doğrulanmış girdilerden gelen tablo ve sütun adları için
kullanın, aksi takdirde güvenlik riskine maruz kalırsınız.
Diğer ipuçlarını genellikle belirtmeye gerek yoktur, çünkü Nette SQL sorgusunu oluştururken akıllı otomatik algılama
kullanır (tablonun üçüncü sütununa bakın). Ancak, örneğin koşulları AND
yerine OR
ile
birleştirmek istediğiniz bir durumda kullanabilirsiniz:
Özel Değerler
Normal skaler tiplerin (string, int, bool) yanı sıra, parametre olarak özel değerler de iletebilirsiniz:
- dosyalar:
fopen('image.gif', 'r')
dosyanın ikili içeriğini ekler - tarih ve saat:
DateTime
nesneleri veritabanı formatına dönüştürülür - enum tipleri:
enum
örnekleri değerlerine dönüştürülür - SQL literalleri:
Connection::literal('NOW()')
ile oluşturulanlar doğrudan sorguya eklenir
datetime
veri tipi için yerel desteği olmayan veritabanlarında (SQLite ve Oracle gibi), DateTime
veritabanı yapılandırmasındaki formatDateTime
öğesiyle belirtilen değere
dönüştürülür (varsayılan değer U
– unix zaman damgasıdır).
SQL Literalleri
Bazı durumlarda, değer olarak doğrudan SQL kodu belirtmeniz gerekir, ancak bu kodun bir karakter dizisi olarak
anlaşılmaması ve kaçış yapılmaması gerekir. Bunun için Nette\Database\SqlLiteral
sınıfının nesneleri
kullanılır. Bunları Connection::literal()
metodu oluşturur.
Veya alternatif olarak:
SQL literalleri parametreler içerebilir:
Bu sayede ilginç kombinasyonlar oluşturabiliriz:
Veri Alma
SELECT Sorguları için Kısayollar
Veri alımını basitleştirmek için Connection
, query()
çağrısını ardından
fetch*()
ile birleştiren birkaç kısayol sunar. Bu metotlar, query()
ile aynı parametreleri kabul
eder, yani SQL sorgusu ve isteğe bağlı parametreler. fetch*()
metotlarının tam açıklaması aşağıda bulunabilir.
fetch($sql, ...$params): ?Row |
Sorguyu yürütür ve ilk satırı Row nesnesi olarak döndürür |
fetchAll($sql, ...$params): array |
Sorguyu yürütür ve tüm satırları Row nesneleri dizisi olarak döndürür |
fetchPairs($sql, ...$params): array |
Sorguyu yürütür ve ilk sütunun anahtar, ikinci sütunun değer olduğu ilişkisel bir dizi döndürür |
fetchField($sql, ...$params): mixed |
Sorguyu yürütür ve ilk satırdaki ilk hücrenin değerini döndürür |
fetchList($sql, ...$params): ?array |
Sorguyu yürütür ve ilk satırı indeksli bir dizi olarak döndürür |
Örnek:
foreach
– Satırlar Üzerinde Yineleme
Sorgu yürütüldükten sonra, sonuçları birkaç şekilde gezmenizi sağlayan bir ResultSet nesnesi döndürülür. Bir sorguyu
yürütmenin ve satırları almanın en kolay yolu foreach
döngüsünde yinelemektir. Bu yöntem bellek açısından
en verimli olanıdır, çünkü verileri kademeli olarak döndürür ve hepsini aynı anda bellekte saklamaz.
ResultSet
yalnızca bir kez yinelenebilir. Tekrar tekrar yinelemeniz gerekiyorsa, önce verileri bir
diziye yüklemeniz gerekir, örneğin fetchAll()
metodunu kullanarak.
fetch(): ?Row
Satırı Row
nesnesi olarak döndürür. Başka satır yoksa null
döndürür. Dahili göstericiyi
bir sonraki satıra taşır.
fetchAll(): array
ResultSet
'ten kalan tüm satırları Row
nesneleri dizisi olarak döndürür.
fetchPairs(string|int|null $key = null, string|int|null $value = null): array
Sonuçları ilişkisel bir dizi olarak döndürür. İlk argüman, dizide anahtar olarak kullanılacak sütun adını belirtir, ikinci argüman değer olarak kullanılacak sütun adını belirtir:
Yalnızca ilk parametreyi belirtirsek, değer tüm satır, yani Row
nesnesi olacaktır:
Yinelenen anahtarlar durumunda, son satırdaki değer kullanılır. Anahtar olarak null
kullanıldığında, dizi
sıfırdan başlayarak sayısal olarak indekslenir (o zaman çakışma olmaz):
fetchPairs(Closure $callback): array
Alternatif olarak, parametre olarak her satır için ya değeri ya da anahtar-değer çiftini döndürecek bir geri arama (callback) belirtebilirsiniz.
fetchField(): mixed
Geçerli satırdaki ilk hücrenin değerini döndürür. Başka satır yoksa null
döndürür. Dahili göstericiyi
bir sonraki satıra taşır.
fetchList(): ?array
Satırı indeksli bir dizi olarak döndürür. Başka satır yoksa null
döndürür. Dahili göstericiyi bir
sonraki satıra taşır.
getRowCount(): ?int
Son UPDATE
veya DELETE
sorgusundan etkilenen satır sayısını döndürür. SELECT
için bu, döndürülen satır sayısıdır, ancak bu bilinmeyebilir – bu durumda metot null
döndürür.
getColumnCount(): ?int
ResultSet
'teki sütun sayısını döndürür.
Sorgu Bilgileri
Hata ayıklama amacıyla, son yürütülen sorgu hakkında bilgi alabiliriz:
Sonucu HTML tablosu olarak görüntülemek için şunu kullanabilirsiniz:
ResultSet, sütun tipleri hakkında bilgi sunar:
Sorgu Günlüklemesi
Kendi sorgu günlüklememizi uygulayabiliriz. onQuery
olayı, her yürütülen sorgudan sonra çağrılacak geri
arama (callback) dizisidir: