PHP, MySQL'e bağlanmak için üç farklı API sunar. Bunlar mysql
(PHP 7'den itibaren kaldırılmıştır) mysqli
ve PDO
uzantılardır.
mysql_*
Fonksiyonları çok popüler olarak kullanılan, ancak bunların kullanımı artık teşvik edilmez. Dokümantasyon ekibi, veritabanı güvenlik durumunu tartışıyor ve kullanıcıları yaygın olarak kullanılan ext / mysql uzantısından uzaklaşmaları için eğitiyor .
Ve daha sonra PHP geliştiricisi takım oluşturmak için karar aldı E_DEPRECATED
, içinden Kullanıcıların, MySQL bağlandıklarında hataları mysql_connect()
, mysql_pconnect()
ya yerleşik örtülü bağlantı işlevselliği ext/mysql
.
ext/mysql
oldu resmen PHP 5.5 tarihinden itibaren kullanımdan kaldırılmıştır ve olmuştur PHP 7'nin olarak uzaklaştırıldı .
Kırmızı Kutuyu görüyor musun?
Herhangi bir mysql_*
işlev kılavuzu sayfasına gittiğinizde, artık kullanılmaması gerektiğini açıklayan kırmızı bir kutu görürsünüz.
Neden
Uzaklaşmak ext/mysql
sadece güvenlikle ilgili değil, aynı zamanda MySQL veritabanının tüm özelliklerine erişim ile ilgilidir.
ext/mysql
MySQL 3.23 için üretildi ve o zamandan beri sadece çok az sayıda ekleme aldı ve kodun bakımını biraz zorlaştıran bu eski sürümle uyumluluğu korudu. Tarafından desteklenmeyen eksik özellikler ext/mysql
şunlardır: ( PHP kılavuzundan ).
mysql_*
Fonksiyonu kullanmama nedeni :
- Aktif gelişme altında değil
- PHP 7'den kaldırıldı
- OO arayüzü yok
- Engellemeyen, eşzamansız sorguları desteklemez
- Hazırlanan ifadeleri veya parametreli sorguları desteklemez
- Saklı yordamları desteklemiyor
- Birden fazla ifadeyi desteklemiyor
- İşlemleri desteklemiyor
- MySQL 5.1'deki tüm işlevleri desteklemez
Quentin'in cevabından alıntılanan yukarıdaki nokta
Hazırlanan ifadeler için destek eksikliği, ayrı bir işlev çağrısıyla manüel olarak kaçmaktan daha çok, daha açık, daha az hataya eğilimli bir dış veri kaçırma ve alıntılama yöntemi sağladığından önemlidir.
SQL uzantılarının karşılaştırmasına bakın .
Kullanımdan kaldırma uyarılarını bastırmak
Kod dönüştürülen edilirken MySQLi
/ PDO
, E_DEPRECATED
ayarlayarak hatalar bastırılabilir error_reporting
içinde php.ini dışlamak içinE_DEPRECATED:
error_reporting = E_ALL ^ E_DEPRECATED
Bunun ayrıca , MySQL dışındaki şeyler için olabilecek diğer kullanımdan çıkarma uyarılarını da gizleyeceğini unutmayın . ( PHP kılavuzundan )
PDO ve MySQLi makalesi : Hangisini Kullanmalısınız? tarafından Dejan Marjanovic seçtiğiniz için yardımcı olacaktır.
Ve daha iyi bir yol PDO
, ve şimdi basit bir PDO
öğretici yazıyorum .
Basit ve kısa PDO eğitimi
S. Aklımdaki ilk soru şuydu: `PDO` nedir?
A. “ PDO - PHP Veri Nesneleri - birden çok veritabanına tek tip bir erişim yöntemi sağlayan bir veritabanı erişim katmanıdır.”
MySQL'e bağlanma
İle mysql_*
biz eski şekilde söyleyebiliriz fonksiyonu ya da (yukarıda PHP'de 5.5 ve kullanımdan kaldırıldı)
$link = mysql_connect('localhost', 'user', 'pass');
mysql_select_db('testdb', $link);
mysql_set_charset('UTF-8', $link);
İle PDO
: Tek yapmanız gereken yeni bir PDO
nesne yaratmak . Yapıcı veritabanı kaynağı belirlemek için parametreleri kabul PDO
sitesindeki yapıcı çoğunlukla dört parametre yer alır DSN
, isteğe bağlı olarak (veri kaynağı adı) ve username
, password
.
Burada bence her şeyi biliyorsunuz DSN
; bu yeni PDO
. A DSN
temel olarak PDO
hangi sürücünün kullanılacağını ve bağlantı ayrıntılarını belirten bir seçenek dizesidir . Daha fazla referans için PDO MySQL DSN'yi kontrol edin .
$db = new PDO('mysql:host=localhost;dbname=testdb;charset=utf8', 'username', 'password');
Not: Ayrıca kullanabilirsiniz charset=UTF-8
, ancak bazen bir hataya neden olur, bu nedenle kullanmak daha iyidir utf8
.
Herhangi bir bağlantı hatası varsa, daha fazla PDOException
işlemek için yakalanabilecek bir nesne atar Exception
.
İyi okuma : Bağlantılar ve Bağlantı yönetimi ¶
Ayrıca dördüncü parametreye dizi olarak çeşitli sürücü seçeneklerini de aktarabilirsiniz. PDO
İstisna moduna geçiren parametreyi geçirmenizi öneririm . Bazı PDO
sürücüler yerel hazırlanmış ifadeleri desteklemediğinden PDO
, hazırlamanın öykünmesini gerçekleştirir. Ayrıca bu öykünmeyi el ile etkinleştirmenizi sağlar. Sunucu tarafında hazırlanan yerel ifadeleri kullanmak için, ifadeyi açıkça ayarlamanız gerekir false
.
Diğeri, MySQL
varsayılan olarak sürücüde etkinleştirilmiş olan öykünme hazırlamayı kapatmaktır , ancak PDO
güvenli bir şekilde kullanmak için öykünme hazırlığı kapatılmalıdır .
Daha sonra öykünme hazırlamanın neden kapatılması gerektiğini açıklayacağım. Sebep bulmak için lütfen bu gönderiyi kontrol edin .
Yalnızca önermediğim eski bir sürümünü kullanıyorsanız kullanılabilir MySQL
.
Aşağıda bunu nasıl yapabileceğinize bir örnek verilmiştir:
$db = new PDO('mysql:host=localhost;dbname=testdb;charset=UTF-8',
'username',
'password',
array(PDO::ATTR_EMULATE_PREPARES => false,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION));
PDO yapımından sonra nitelikleri ayarlayabilir miyiz?
Evet , PDO yapıldıktan sonra setAttribute
yöntemle bazı öznitelikler de ayarlayabiliriz :
$db = new PDO('mysql:host=localhost;dbname=testdb;charset=UTF-8',
'username',
'password');
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
Hata yönetimi
Hata işleme de çok daha kolaydır PDO
daha mysql_*
.
Kullanırken yaygın bir uygulama mysql_*
:
//Connected to MySQL
$result = mysql_query("SELECT * FROM table", $link) or die(mysql_error($link));
OR die()
bir şeyi işleyemediğimiz için hatayı işlemek için iyi bir yol değildir die
. Sadece komut dosyasını aniden sonlandıracak ve sonra hatayı genellikle son kullanıcılarınıza göstermek istemediğiniz ekrana yansıtacak ve kanlı bilgisayar korsanlarının şemanızı keşfetmesine izin verecektir. Alternatif olarak, mysql_*
işlevlerin dönüş değerleri genellikle hataları işlemek için mysql_error () ile birlikte kullanılabilir .
PDO
daha iyi bir çözüm sunar: istisnalar. Yaptığımız her şey PDO
bir try
- catch
bloğa sarılmalıdır . PDO
Hata modu özelliğini ayarlayarak üç hata modundan birine girebiliriz . Üç hata işleme modu aşağıdadır.
PDO::ERRMODE_SILENT
. Sadece hata kodlarını ayarlamak ve mysql_*
her bir sonucu kontrol etmeniz gereken yere benzer şekilde davranır ve daha sonra $db->errorInfo();
hata ayrıntılarını almak için bakın.
PDO::ERRMODE_WARNING
Yükselt E_WARNING
. (Çalışma zamanı uyarıları (önemli olmayan hatalar). Komut dosyasının yürütülmesi durdurulmaz.)
PDO::ERRMODE_EXCEPTION
: İstisnalar atın. PDO tarafından oluşturulan bir hatayı temsil eder. PDOException
Kendi kodunuzdan a atmamalısınız . PHP'deki istisnalar hakkında daha fazla bilgi için Kural Dışı Durumlar konusuna bakın . or die(mysql_error());
Yakalanmadığı zaman çok benzer . Ama aksine or die()
, PDOException
bunu seçerseniz yakalanabilir ve ele alınabilir.
İyi okuma :
Sevmek:
$stmt->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT );
$stmt->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING );
$stmt->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
Ve aşağıdaki gibi try
- içine sarabilirsiniz catch
:
try {
//Connect as appropriate as above
$db->query('hi'); //Invalid query!
}
catch (PDOException $ex) {
echo "An Error occured!"; //User friendly message/message you want to show to user
some_logging_function($ex->getMessage());
}
Bununla başa çıkmak zorunda değilsiniz try
- catch
şu anda. İstediğiniz zaman yakalayabilirsiniz, ancak kullanmanızı kesinlikle öneririz try
- catch
. Ayrıca, PDO
öğeleri çağıran fonksiyonun dışında yakalamak daha mantıklı olabilir :
function data_fun($db) {
$stmt = $db->query("SELECT * FROM table");
return $stmt->fetchAll(PDO::FETCH_ASSOC);
}
//Then later
try {
data_fun($db);
}
catch(PDOException $ex) {
//Here you can handle error and show message/perform action you want.
}
Ayrıca, idare edebilirsin or die()
ya da böyle diyebiliriz mysql_*
, ama gerçekten değişecektir. Üretimdeki tehlikeli hata mesajlarını display_errors off
, hata günlüğünüzü çevirip okuyarak gizleyebilirsiniz .
Şimdi, yukarıdaki her şeyi okuduktan sonra, muhtemelen düşünüyorsun: halt ne olduğunu ben sadece basit eğilerek başlamak istediğinizde SELECT
, INSERT
, UPDATE
veya DELETE
ifadeleri? Endişelenme, işte başlıyoruz:
Veri Seçme
Yani yaptığınız mysql_*
şey:
<?php
$result = mysql_query('SELECT * from table') or die(mysql_error());
$num_rows = mysql_num_rows($result);
while($row = mysql_fetch_assoc($result)) {
echo $row['field1'];
}
Şimdi PDO
, bunu şöyle yapabilirsiniz:
<?php
$stmt = $db->query('SELECT * FROM table');
while($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
echo $row['field1'];
}
Veya
<?php
$stmt = $db->query('SELECT * FROM table');
$results = $stmt->fetchAll(PDO::FETCH_ASSOC);
//Use $results
Not : Aşağıdaki yöntem ( query()
) gibi bir yöntem kullanıyorsanız , bu yöntem bir PDOStatement
nesne döndürür . Sonuç almak istiyorsanız, yukarıdaki gibi kullanın.
<?php
foreach($db->query('SELECT * FROM table') as $row) {
echo $row['field1'];
}
PDO Verilerinde, ->fetch()
deyim tanıtıcısının bir yöntemi aracılığıyla elde edilir . Getirmeyi çağırmadan önce, en iyi yaklaşım PDO'ya verilerin nasıl getirilmesini istediğinizi söylemektir. Aşağıdaki bölümde bunu açıklıyorum.
Getirme Modları
Yukarıdaki ve kodundaki kullanımına dikkat PDO::FETCH_ASSOC
edin . Bu , satırların alan adları ile ilişkilendirilebilir bir dizi olarak anahtarlar olarak döndürülmesini söyler . Tek tek açıklayacağım başka birçok getirme modu da var.fetch()
fetchAll()
PDO
Her şeyden önce, getirme modunun nasıl seçileceğini açıklarım:
$stmt->fetch(PDO::FETCH_ASSOC)
Yukarıda, kullanıyorum fetch()
. Ayrıca kullanabilirsiniz:
Şimdi getirme moduna geliyorum:
PDO::FETCH_ASSOC
: sonuç kümenizde döndürülen sütun adına göre dizine eklenen bir dizi döndürür
PDO::FETCH_BOTH
(varsayılan): sonuç kümenizde döndürülen şekilde hem sütun adı hem de 0 dizinli sütun numarasıyla dizinlenmiş bir dizi döndürür
Daha fazla seçenek var! Bunların hepsini PDOStatement
Getirme belgelerinde okuyun . .
Satır sayısını elde etme :
mysql_num_rows
Döndürülen satır sayısını almak için kullanmak yerine, a PDOStatement
ve do komutlarını alabilirsiniz rowCount()
, örneğin:
<?php
$stmt = $db->query('SELECT * FROM table');
$row_count = $stmt->rowCount();
echo $row_count.' rows selected';
Son Eklenen Kimliği Alma
<?php
$result = $db->exec("INSERT INTO table(firstname, lastname) VAULES('John', 'Doe')");
$insertId = $db->lastInsertId();
Ekleme ve Güncelleme veya Silme
mysql_*
İşlev olarak ne yapıyoruz :
<?php
$results = mysql_query("UPDATE table SET field='value'") or die(mysql_error());
echo mysql_affected_rows($result);
Ve pdo'da aynı şey şu şekilde yapılabilir:
<?php
$affected_rows = $db->exec("UPDATE table SET field='value'");
echo $affected_rows;
Yukarıdaki sorguda PDO::exec
bir SQL deyimi yürütün ve etkilenen satır sayısını döndürür.
Ekle ve sil daha sonra ele alınacaktır.
Yukarıdaki yöntem, yalnızca sorguda değişken kullanmadığınızda kullanışlıdır. Ancak bir sorguda bir değişken kullanmanız gerektiğinde, asla yukarıdaki gibi denemeyin ve orada hazırlanmış deyimi veya parametreli deyimi vardır.
Hazırlanan İfadeler
S. Hazırlanan ifade nedir ve neden bunlara ihtiyacım var?
A. Hazırlanan deyim, yalnızca verileri sunucuya göndererek birden çok kez çalıştırılabilen önceden derlenmiş bir SQL deyimidir.
Hazırlanan bir ifadeyi kullanmanın tipik iş akışı aşağıdaki gibidir ( Wikipedia üç 3 maddeden alıntılanmıştır ):
Hazırla : İfade şablonu uygulama tarafından oluşturulur ve veritabanı yönetim sistemine (DBMS) gönderilir. Parametreler, yer tutucular veya bağlama değişkenleri ( ?
aşağıda etiketli ) adı verilen belirli değerler belirtilmemiş olarak bırakılır :
INSERT INTO PRODUCT (name, price) VALUES (?, ?)
DBMS, ifade şablonunda sorgu optimizasyonunu ayrıştırır, derler ve gerçekleştirir ve sonucu yürütmeden saklar.
- Yürüt : Daha sonra uygulama, parametreler için değerler sağlar (veya bağlar) ve DBMS ifadeyi yürütür (muhtemelen bir sonuç döndürür). Uygulama, ifadeyi farklı değerlerle istediği kadar yürütebilir. Bu örnekte, birinci parametre ve
1.00
ikinci parametre için 'Ekmek' sağlayabilir .
SQL'inize yer tutucular ekleyerek hazırlanmış bir ifade kullanabilirsiniz. Temel olarak yer tutucuları olmayan üç tane vardır (bunu birincisi değişkeniyle denemeyin), biri isimsiz yer tutucuları ve diğeri adlandırılmış yer tutucuları ile.
S. Şimdi, yer tutucular olarak adlandırılan nedir ve nasıl kullanılır?
A. Adlandırılmış yer tutucular. Soru işaretleri yerine iki nokta üst üste işareti bulunan açıklayıcı adları kullanın. İsim yer sahibindeki konum / değer sırası umursamıyoruz:
$stmt->bindParam(':bla', $bla);
bindParam(parameter,variable,data_type,length,driver_options)
Ayrıca bir yürütme dizisi kullanarak da bağlanabilirsiniz:
<?php
$stmt = $db->prepare("SELECT * FROM table WHERE id=:id AND name=:name");
$stmt->execute(array(':name' => $name, ':id' => $id));
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
OOP
Arkadaşlar için bir diğer güzel özellik , adlandırılmış yer tutucuların, özelliklerin adlandırılan alanlarla eşleştiği varsayılarak doğrudan veritabanınıza nesne ekleme yeteneğine sahip olmasıdır. Örneğin:
class person {
public $name;
public $add;
function __construct($a,$b) {
$this->name = $a;
$this->add = $b;
}
}
$demo = new person('john','29 bla district');
$stmt = $db->prepare("INSERT INTO table (name, add) value (:name, :add)");
$stmt->execute((array)$demo);
S. Şimdi, adlandırılmamış yer tutucular nedir ve bunları nasıl kullanırım?
A. Bir örnek verelim:
<?php
$stmt = $db->prepare("INSERT INTO folks (name, add) values (?, ?)");
$stmt->bindValue(1, $name, PDO::PARAM_STR);
$stmt->bindValue(2, $add, PDO::PARAM_STR);
$stmt->execute();
ve
$stmt = $db->prepare("INSERT INTO folks (name, add) values (?, ?)");
$stmt->execute(array('john', '29 bla district'));
Yukarıda, ?
bir ad yer tutucusundaki gibi bir ad yerine bunları görebilirsiniz . Şimdi ilk örnekte, çeşitli yer tutuculara ( $stmt->bindValue(1, $name, PDO::PARAM_STR);
) değişkenler atarız . Ardından, bu yer tutuculara değerler atar ve ifadeyi yürütürüz. İkinci örnekte, ilk dizi elemanı, birinci gider ?
ve ikinci ikinci ?
.
NOT : Adsız yer tutucularda , diziye PDOStatement::execute()
yönteme geçirdiğimiz öğelerin uygun sırasına dikkat etmeliyiz .
SELECT
, INSERT
, UPDATE
, DELETE
Sorgular hazırlanan
SELECT
:
$stmt = $db->prepare("SELECT * FROM table WHERE id=:id AND name=:name");
$stmt->execute(array(':name' => $name, ':id' => $id));
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
INSERT
:
$stmt = $db->prepare("INSERT INTO table(field1,field2) VALUES(:field1,:field2)");
$stmt->execute(array(':field1' => $field1, ':field2' => $field2));
$affected_rows = $stmt->rowCount();
DELETE
:
$stmt = $db->prepare("DELETE FROM table WHERE id=:id");
$stmt->bindValue(':id', $id, PDO::PARAM_STR);
$stmt->execute();
$affected_rows = $stmt->rowCount();
UPDATE
:
$stmt = $db->prepare("UPDATE table SET name=? WHERE id=?");
$stmt->execute(array($name, $id));
$affected_rows = $stmt->rowCount();
NOT:
Ancak PDO
ve / veya MySQLi
tamamen güvenli değildir. Cevabı kontrol edin PDO hazırlanmış ifadeler SQL enjeksiyonunu önlemek için yeterli mi? ircmaxell tarafından . Ayrıca, cevabından bir kısmını alıntılıyorum:
$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$pdo->query('SET NAMES GBK');
$stmt = $pdo->prepare("SELECT * FROM test WHERE name = ? LIMIT 1");
$stmt->execute(array(chr(0xbf) . chr(0x27) . " OR 1=1 /*"));