15 Soru: PHP'de mysql_ * fonksiyonlarını neden kullanmamalıyım?

tarafından oluşturulan soru Wed, Dec 13, 2017 12:00 AM

mysql_* işlevini kullanmama nedeninin teknik nedenleri nelerdir? (örneğin, mysql_query(), mysql_connect() veya mysql_real_escape_string())?

Sitemde çalışsalar bile neden başka bir şey kullanmalıyım?

Sitemde çalışmıyorlarsa neden böyle hatalar alıyorum

  

Uyarı: mysql_connect (): Böyle bir dosya veya dizin yok

    
2377
  1. Beğenilecek hata: Ölümcül hata: Yakalanmamış Hata: tanımsız işlev çağrısı mysql_connect () ...
    2017-12-02 08: 04: 02Z
  2. Yalnız reddedilmiş onlardan kaçınmak için yeterli nedendir
    2017-12-17 05: 43: 00Z
15 Yanıtlar                              15                         

MySQL uzantısı:

  • Etkin geliştirilme aşamasında değil
  • PHP 5.5'ten itibaren resmi olarak kullanımdan kaldırıldı (PHP 2013’ten itibaren kaldırıldı) ).
  • PHP 7.0'dan itibaren kaldırıldı oldu (PHP 7.0). Aralık 2015’te yayımlandı)
    • Bu, 31 Ara 2018 'den itibaren desteklenen bir PHP sürümünde bulunmayacağı anlamına gelir . Şu anda yalnızca güvenlik güncellemelerini alıyor.
  • Bir OO arayüzüne sahip değil
  • desteklemiyor:
    • Engellenmeyen, zaman uyumsuz sorgular
    • Hazırlanan ifadeler veya parametreli hale getirilmiş sorgular
    • Saklı yordamlar
    • Birden Fazla Tablo
    • İşlemler
    • "Yeni" şifre doğrulama yöntemi (varsayılan olarak MySQL 5.6'da açıktır; 5.7'de zorunludur)
    • MySQL 5.1'deki tüm işlevler

Kullanımından kaldırıldığı için, kullanılması kodunuzu daha az geleceğe hazır hale getirir.

Hazırlanan ifadelere verilen destek eksikliği, harici verilerden kaçmak ve ayrı bir işlev çağrısı ile manuel olarak çıkmaktan daha açık ve daha az hataya açık bir yöntem sunmak için özellikle önemlidir.

Bkz. SQL uzantılarının karşılaştırılması .

    
1984
2017-12-25 14: 56: 51Z
  1. Yalnız reddedilmiş, onlardan kaçınmak için yeterli nedendir. Bir gün orada olmayacaklar ve onlara güvenirseniz mutlu olmazsınız. Gerisi, eski uzantıları kullanmanın insanları öğrenmekten alıkoyan şeylerin bir listesi.
    2012-10-12 13: 26: 43Z
  2. İtiraz, herkesin düşündüğü gibi görünen sihirli mermi değildir. PHP'nin kendisi orada bir gün olmayacak, ancak bugün elimizdeki araçlara güveniyoruz. Araçları değiştirmek zorunda kaldığımızda, yapacağız.
    2012-12-24 14: 29: 34Z
  3. @ LightnessRacesinOrbit - İtiraz sihirli bir mermi değil, "Bu berbat tanıdığımız için daha uzun süre desteklemeyeceğiz" yazan bir bayrak . Gelecekte daha iyi bir kod provası olması, kullanımdan kaldırılmış özelliklerden uzaklaşmak için iyi bir neden olsa da, tek (veya hatta ana kod) değil. Araçları değiştirin, çünkü zorladığınız için değil daha iyi araçlar vardır. (Ve sizden önce araçları değiştirmek, sadece kodunuzun çalışmayı bırakması ve dünün düzeltilmesi gerektiği için yeni olanları öğrenmediğiniz anlamına gelir… bu da yeni araçları öğrenmek için en kötü zamandır.
    2012-12-24 17: 43: 59Z
  4. Hazırladığım sta eksikliğinden bahsetmediğim bir şeyöğeler performans sorunu. Bir bildiri yayınladığınızda, bir şey derlemek zorundadır, böylece MySQL arka plan programı anlayabilir. Bu API ile aynı sorgunun 200.000'ini bir döngüde yayınlarsanız, sorgunun MySQL'in anlayabilmesi için 200.000 kez derlenmesi gerekir. Hazırlanan ifadelerle, bir kez derlenir ve ardından değerler derlenmiş SQL'de parametrelendirilir.
    2013-12-14 17: 58: 43Z
  5. @ symcbean, Hazırlanan açıklamaları kesinlikle desteklemez değil . Aslında, itiraz edilmesinin temel nedeni budur. (Kullanımı kolay) hazırlanmış açıklamalar olmadan, mysql uzantısı genellikle SQL enjeksiyon saldırılarına kurban kalır.
    2014-04-05 20: 30: 12Z

PHP, MySQL'e bağlanmak için üç farklı API sunar. Bunlar mysql (PHP 7'den itibaren kaldırıldı), mysqli ve PDO uzantıları.

mysql_* işlevi çok popülerdi, ancak kullanımı artık teşvik edilmiyor. Belgelendirme ekibi veritabanı güvenlik durumunu tartışıyor ve kullanıcıları yaygın olarak kullanılan ext /mysql uzantısından uzaklaşmaları konusunda eğitmek bunun bir parçası ( php.internals: ext /mysql kullanımdan kaldırılıyor ).

Daha sonra PHP geliştirici ekibi E_DEPRECATED ıcılar MySQL’e bağlanırken, mysql_connect(), mysql_pconnect() veya ext/mysql’da yerleşik örtülü bağlantı işlevselliği sayesinde güçlü> hatalar.

ext/mysql , PHP 5.5'ten itibaren resmen kullanım dışı bırakıldı ve PHP 7'den itibaren kaldırıldı .

Kırmızı Kutuya Bakın?

Herhangi bir mysql_* işlev kılavuzuna gittiğinizde, artık kullanılmaması gerektiğini açıklayan kırmızı bir kutu görürsünüz.

Neden


ext/mysql'dan uzaklaşmak yalnızca güvenlikle ilgili değil, aynı zamanda MySQL veritabanının tüm özelliklerine erişime sahip olmakla da ilgilidir.

ext/mysql, MySQL 3.23 için üretildi ve kodun korunmasını biraz zorlaştıran bu eski sürümle uyumluluğunu sürdürürken o zamandan bu yana yalnızca çok az ekleme yapıldı. ext/mysql tarafından desteklenmeyen eksik özellikler şunlardır: ( PHP kılavuzundan ).

mysql_* işlevini kullanmama nedeni :

  • Etkin geliştirilme aşamasında değil
  • PHP 7'den itibaren kaldırıldı
  • Bir OO arayüzüne sahip değil
  • Engellenmeyen, zaman uyumsuz sorguları desteklemiyor
  • Hazırlanan ifadeleri veya parametreli sorguları desteklemiyor
  • Saklı yordamları desteklemiyor
  • Birden çok ifadeyi desteklemiyor
  • işlemlerini desteklemiyor
  • MySQL 5.1'deki tüm işlevleri desteklemiyor

Quentin’in cevabından alıntı yapılan yerin üzerinde

Hazırlanan ifadeler için destek eksikliği, harici bir veriden ayrı bir işlev çağrısı ile manuel olarak kaçmaktan daha açık, daha az hataya açık bir yöntemden alıntı yapma yöntemi sunduğundan özellikle önemlidir.

SQL uzantılarının karşılaştırılması bölümüne bakın.


Kullanımdan kaldırma uyarılarını bastırma

Kod MySQLi /PDO’a dönüştürülürken, E_DEPRECATED’u error_reporting’u php.ini 'de E_DEPRECATED:’u hariç tutarak ayarlayarak

error_reporting = E_ALL ^ E_DEPRECATED
hata bastırabilir.  PDO

Bunun diğer kullanımdan çıkarma uyarıları da gizleyeceğini unutmayın , ki bu, MySQL dışındaki şeyler için olabilir. ( PHP kılavuzundan )

PDO vs. . MySQLi: Hangisini Kullanmalısınız? by Dejan Marjanovic seçmene yardımcı olacak.

Ve daha iyi bir yol PDO ve şimdi basit bir mysql_* dersi yazıyorum.


Basit ve kısa bir PDO öğreticisi


S. Aklımdaki ilk soru şuydu: “PDO” nedir?

. “ PDO - PHP Veri Nesneleri - birden çok veritabanına tek tip erişim yöntemi sağlayan bir veritabanı erişim katmanıdır.”

  

alt metin


MySQL'e Bağlanma

$link = mysql_connect('localhost', 'user', 'pass');
mysql_select_db('testdb', $link);
mysql_set_charset('UTF-8', $link);
işleviyle veya eski yoldan söyleyebiliriz (PHP 5.5 ve üzeri sürümlerde kullanım dışı)  PDO

PDO ile: Yapmanız gereken tek şey yeni bir PDO nesnesi oluşturmak. Yapıcı, DSN nolu veritabanı kaynağını belirlemek için parametreleri kabul eder, çoğunlukla username (veri kaynağı adı) ve isteğe bağlı olarak password, DSN olan dört parametre alır.

Burada PDO dışındaki herkese aşina olduğunuzu düşünüyorum; bu DSN’da yeni. PDO,

$db = new PDO('mysql:host=localhost;dbname=testdb;charset=utf8', 'username', 'password');
'a hangi sürücünün kullanılacağını ve bağlantı ayrıntılarını söyleyen bir seçenek dizisidir. Daha fazla başvuru için PDO MySQL DSN 'i kontrol edin.  charset=UTF-8

Not: utf8'u da kullanabilirsiniz, ancak bazen bir hataya neden olur, bu nedenle PDOException'u kullanmak daha iyidir.

Herhangi bir bağlantı hatası varsa, Exception'u daha fazla işlemesi için yakalanabilecek bir PDO nesnesi atar.

İyi okumalar : Bağlantılar ve Bağlantı yönetimi ¶

Ayrıca dördüncü parametreye bir dizi olarak çeşitli sürücü seçeneklerinden de geçebilirsiniz. PDO'u istisnai moda alan parametreyi geçirmenizi öneririm. Bazı PDO sürücüleri yerel hazırlanmış ifadeleri desteklemediğinden, false hazırlamanın emülasyonunu gerçekleştirir. Ayrıca bu emülasyonu el ile etkinleştirmenize de olanak sağlar. Yerel sunucu tarafı tarafından hazırlanan ifadeleri kullanmak için, açıkça MySQL olarak ayarlamanız gerekir.

Diğer, varsayılan olarak PDO sürücüsünde etkin olan hazırlama emülasyonunu kapatmaktır, ancak MySQL'u güvenle kullanmak için emülasyon hazırlama kapatılmalıdır.

Daha sonra neden emülasyon hazırlamanın kapatılması gerektiğini açıklayacağım. Sebep bulmak için lütfen bu yayını kontrol edin.

Yalnızca önerilmeyen

$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));
'un eski bir sürümünü kullanıyorsanız kullanılabilir.

Aşağıda, nasıl yapabileceğinize bir örnek verilmiştir:

 setAttribute

PDO inşaatı sonrası özellikleri ayarlayabilir miyiz?

Evet ,

$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);
yöntemiyle PDO inşaatından sonra bazı özellikler de belirleyebiliriz:  PDO

Hata İşlemesi


Hata yönetimi mysql_*'da mysql_*'dan daha kolaydır.

//Connected to MySQL
$result = mysql_query("SELECT * FROM table", $link) or die(mysql_error($link));
kullanırken yaygın bir uygulama şudur:  OR die()

die, hatayı düzeltmek için iyi bir yol değil, çünkü mysql_*'daki sorunu ele alamıyoruz. Sadece betiği aniden sonlandırır ve hatayı genellikle son kullanıcılarınıza göstermek istemediğiniz ekrana eko yapar ve kanlı bilgisayar korsanlarının şemanızı keşfetmesine izin verir. Alternatif olarak, PDO işlevlerinin dönüş değerleri genellikle hataları işlemek için mysql_error () ile birlikte kullanılabilir.

PDO daha iyi bir çözüm sunar: istisnalar. try ile yaptığımız her şey catch - PDO bloğuna sarılmalıdır. Hata modu özniteliğini ayarlayarak PDO::ERRMODE_SILENT'u üç hata modundan birine zorlayabiliriz. Üç hata işleme modu aşağıdadır.

  •  mysql_*. Sadece hata kodlarını ayarlamak ve hemen hemen her sonucu kontrol etmeniz ve ardından hata ayrıntılarını almak için $db->errorInfo();'a bakmanız gereken PDO::ERRMODE_WARNING ile aynı şekilde hareket ediyor.
  •  E_WARNING PDO::ERRMODE_EXCEPTION’u kaldırın. (Çalışma zamanı uyarıları (önemli olmayan hatalar). Komut dosyasının yürütülmesi durdurulmadı.)
  •  PDOException: İstisnaları at. PDO tarafından oluşturulan bir hatayı temsil eder. Kendi kodunuzdan bir or die(mysql_error()); atmamalısınız. PHP'deki istisnalar hakkında daha fazla bilgi için İstisnalar bölümüne bakın. Yakalanmadığında or die() gibi davranır. Ancak, PDOException'dan farklı olarak,
    $stmt->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT );
    $stmt->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING );
    $stmt->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
    
    , seçmeyi tercih ederseniz zarafetle yakalanabilir ve kullanılabilir.

İyi okunan :

gibi:

 try

Ayrıca, aşağıdaki gibi 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());
}
’a sarın:  try

Şu anda catch - try ile işlem yapmanız gerekmez. İstediğiniz zaman yakalayabilirsiniz, ancak catch - PDO kullanmanızı tavsiye ederim. Ayrıca

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.
}
öğeyi çağıran işlevin dışında yakalamak daha mantıklı olabilir:  or die()

Ayrıca, mysql_* ile baş edebilir veya display_errors off gibi diyebiliriz, ancak gerçekten değişecektir. SELECT'u çevirerek ve hata günlüğünüzü okuyarak tehlikeli hata iletilerini üretimde gizleyebilirsiniz.

Şimdi, yukarıdaki tüm şeyleri okuduktan sonra, muhtemelen düşünüyorsunuz: basit INSERT, UPDATE, DELETE veya mysql_* ifadeleri kullanmaya başlamak istediğimde ne halt ediyor? Endişelenme, işte başlıyoruz:


Veri Seçme

PDO resmi seç

Öyleyse,

<?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'];
}
’da yaptığınız şey şudur:  PDO

Şimdi

<?php
$stmt = $db->query('SELECT * FROM table');

while($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
    echo $row['field1'];
}
’da şu şekilde yapabilirsiniz:  
<?php
$stmt = $db->query('SELECT * FROM table');
$results = $stmt->fetchAll(PDO::FETCH_ASSOC);

//Use $results

Ya

 query()

Not : Aşağıdaki yöntemi kullanıyorsanız (PDOStatement), bu yöntem

<?php
foreach($db->query('SELECT * FROM table') as $row) {
    echo $row['field1'];
}
nesnesini döndürür. Bu nedenle sonucu almak istiyorsanız yukarıdaki gibi kullanın.  ->fetch()

PDO Verileri'nde, ifade işlemcinizin bir yöntemi olan PDO::FETCH_ASSOC aracılığıyla elde edilir. Getirmeyi aramadan önce, en iyi yaklaşım PDO'ya verilerin nasıl alınmasını istediğinizi söylemektir. Aşağıdaki bölümde bunu açıklıyorum.

Getirme Modları

Yukarıdaki fetch() ve fetchAll() kodunda PDO kullanımına dikkat edin. Bu,

 $stmt->fetch(PDO::FETCH_ASSOC)
'a, satırları alan adlarıyla bir anahtar dizisi olarak döndürmesini söyler. Tek tek açıklayacağım çok sayıda alma modu da var.

Her şeyden önce, getirme modunun nasıl seçileceğini açıklarım:

 fetch()

Yukarıdakilerde PDOStatement::fetchAll() kullanıyorum. Ayrıca şunları da kullanabilirsiniz:

Şimdi alım moduna geldim:

  •  PDO::FETCH_BOTH: Sonuç kümenizde döndürüldüğü gibi sütun adına göre dizine alınmış bir dizi döndürür
  •  PDOStatement (varsayılan): Sonuç kümenizde döndürüldüğü gibi hem sütun adına hem de 0 dizinli sütun numarasına göre dizine alınmış bir dizi döndürür

Daha fazla seçenek var! Hepsi hakkında mysql_num_rows Belgeleri getirme. 'da okuyun.

Satır sayısını almak :

Döndürülen satır sayısını elde etmek için PDOStatement kullanmak yerine, bir rowCount() alabilir ve

<?php
$stmt = $db->query('SELECT * FROM table');
$row_count = $stmt->rowCount();
echo $row_count.' rows selected';
gibi yapabilirsiniz:  
<?php
$result = $db->exec("INSERT INTO table(firstname, lastname) VAULES('John', 'Doe')");
$insertId = $db->lastInsertId();

Son Eklenen Kimliği Alma

 mysql_*

İfadeleri Ekleme ve Güncelleme veya Silme

PDO resmini ekleyin ve güncelleyin

<?php
$results = mysql_query("UPDATE table SET field='value'") or die(mysql_error());
echo mysql_affected_rows($result);
işlevinde yaptığımız şey:  
<?php
$affected_rows = $db->exec("UPDATE table SET field='value'");
echo $affected_rows;

Ve pdo'da da aynı şey yapılabilir:

 PDO::exec

Yukarıdaki sorguda ? bir SQL ifadesi çalıştırır ve sayısını döndürür etkilenen satırlar.

Ekleme ve silme daha sonra ele alınacak.

Yukarıdaki yöntem yalnızca sorguda değişken kullanmadığınızda yararlıdır. Ancak bir sorguda bir değişken kullanmanız gerektiğinde, hiç bir zaman yukarıdaki gibi denemeyin; hazırlanan ifade veya parametreli hale getirilmiş ifade 'dir.


Hazırlanan Bildirimler

Q. Hazırlanan bir ifade nedir ve neden onlara ihtiyacım var?
A. Hazırlanan bir ifade, çalıştırılabilen önceden derlenmiş bir SQL ifadesidir yalnızca verileri sunucuya göndererek birkaç kez.

Hazırlanan bir ifadeyi kullanmanın tipik iş akışı şu şekildedir ( Wikipedia 3'ten itibaren alıntı 3 nokta ):

  1. Hazırla : İfade şablonu, uygulama tarafından oluşturulur ve veritabanı yönetim sistemine (DBMS) gönderilir. Belirli değerler, parametreler, yer tutucular veya bağlama değişkenleri adı verilen belirtilmemiş olarak bırakılmıştır (aşağıda INSERT INTO PRODUCT (name, price) VALUES (?, ?) olarak etiketlenmiştir):

    1.00

  2. DBMS ayrıştırır, derleres, deyim şablonunda sorgu optimizasyonu gerçekleştirir ve sonucu çalıştırmadan saklar.

  3. Yürüt : Daha sonra, uygulama parametreler için değerler sağlar (veya bağlar) ve DBMS ifadeyi çalıştırır (muhtemelen bir sonuç döndürür). Uygulama, ifadeyi farklı değerlerle istediği kadar çalıştırabilir. Bu örnekte, ilk parametre için 'Ekmek' ve ikinci parametre için
     $stmt->bindParam(':bla', $bla);
    
    sağlayabilir.

Hazırlanan bir ifadeyi SQL'inizdeki yer tutucuları dahil ederek kullanabilirsiniz. Temel olarak üç tane yer tutucusu var (bunu bir üstündeki değişkenle denemeyin), biri adsız yer tutucularla, diğeri ad verilmiş yer tutucularla.

S. Şimdi, yer tutucuların adı nedir ve bunları nasıl kullanırım?

Adlandırılmış yer tutucuların adı. Soru işaretleri yerine, önce iki nokta üst üste gelen açıklayıcı isimler kullanın. İsim sahibinde pozisyon /değer sırasını umursamıyoruz:

 bindParam(parameter,variable,data_type,length,driver_options)

<?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);

Ayrıca bir execute array kullanarak da ciltleyebilirsiniz:

 OOP

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);
arkadaş için bir başka güzel özellik de, adlandırılmış yer tutucuların, özelliklerin adlandırılmış alanlarla eşleştiğini varsaymak suretiyle doğrudan veritabanınıza nesneler ekleme yeteneğine sahip olmasıdır. Örneğin:  
<?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();

Q. Öyleyse, adsız yer tutucular nedir ve bunları nasıl kullanırım?
A. Bir örnek verelim:

 
$stmt = $db->prepare("INSERT INTO folks (name, add) values (?, ?)");
$stmt->execute(array('john', '29 bla district'));

ve

 ?

Yukarıda, ad yer tutucusu gibi bir ad yerine bu $stmt->bindValue(1, $name, PDO::PARAM_STR);'u görebilirsiniz. Şimdi ilk örnekte çeşitli yer tutuculara değişkenler atadık (?). Ardından, bu yer tutuculara değer atar ve ifadeyi çalıştırırız. İkinci örnekte, ilk dizi elemanı ilk ?'a, ikincisi ikinci PDOStatement::execute()'a gider.

NOT : Adsız yer tutucular 'da, dizideki öğelerin SELECT yöntemine ilettiğimiz düzgün sıralamaya dikkat etmeliyiz.


 INSERT, UPDATE, DELETE, SELECT hazırlanan sorgular

  1. $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
  2. $stmt = $db->prepare("INSERT INTO table(field1,field2) VALUES(:field1,:field2)");
    $stmt->execute(array(':field1' => $field1, ':field2' => $field2));
    $affected_rows = $stmt->rowCount();
    
    :

     DELETE
  3. $stmt = $db->prepare("DELETE FROM table WHERE id=:id");
    $stmt->bindValue(':id', $id, PDO::PARAM_STR);
    $stmt->execute();
    $affected_rows = $stmt->rowCount();
    
    :

     UPDATE
  4. $stmt = $db->prepare("UPDATE table SET name=? WHERE id=?");
    $stmt->execute(array($name, $id));
    $affected_rows = $stmt->rowCount();
    
    :

     PDO

NOT:

Ancak MySQLi ve /veya

$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 /*"));
tamamen güvenli değildir. Cevabı kontrol edin PDO hazırlanmış ifadeler, SQL enjeksiyonunu önlemek için yeterli mi? , ircmaxell . Ayrıca, cevaplarından bir kısmını alıntı yapıyorum:  IN (...) construct     
1227
2018-11-13 01: 03: 03Z
  1. Yukarıda okuduğunuz şeylerin söyleyebileceği şeyler nelerdir: hazırlıklı açıklama function throwEx() { throw new Exception("You did selected not existng db"); } mysql_select_db("nonexistdb") or throwEx();'un anlamlı bir şekilde kullanılmasını engeller.
    2013-12-14 19: 35: 21Z
  2. Soru "Neden PHP'de mysql_ * işlevlerini kullanmamalıyım" sorusuydu. Bu cevap, etkileyici ve faydalı bilgilerle dolu olsa da, WAY'in kapsamı dışında kalıyor ve @trejder'in dediği gibi - 10 kişiden 8'i, sadece çalışmak için harcayacakları 4 saatin olmadığı için bu bilgileri kaçıracaklar. o. Bu, çok daha değerli ve daha kesin ve daha kesin sorulara cevap olarak kullanılacaktır.
    2014-11-19 22: 33: 01Z
  3. Persoanlly Ben mysqli ve PDO'yu tercih ederim. Ancak kalıp işleme için, istisna alternatifini denedim. Doesn't support non-blocking, asynchronous queries İstisnaları atmak için çalışıyor.
    2016-03-01 07: 02: 47Z
  4. mysql_ kullanmama nedeni olarak mysql_*'u listeliyorsunuz - PDO'yu desteklemediği için PDO'yu kullanmama nedeni olarak da listelemelisiniz. (ancak MySQLi destekliyor)
    2018-11-25 17: 40: 23Z

Öncelikle, herkese verdiğimiz standart yorumla başlayalım:

  

Lütfen, mysql_* işlevlerini yeni kodda kullanmayın . Artık soluk değillerained ve resmen onaylanmadı . kırmızı kutu 'ya bakın. hazırlanmış ifadeler hakkında bilgi edinin ve PDO veya MySQLi - bu makale hangisine karar vermenize yardımcı olacaktır. PDO'yu seçerseniz, burası iyi bir eğitimdir .

Bunu başaralım, cümle cümle ve açıklayalım:

  • Artık korunmuyorlar ve resmen onaylanmadılar

    Bu, PHP topluluğunun yavaş yavaş bu çok eski işlevler için desteği bıraktığı anlamına gelir. PHP'nin gelecekteki (yeni) bir sürümünde bulunmamaları muhtemeldir! Bu işlevlerin sürekli kullanımı, (çok) çok uzak bir zamanda kodunuzu bozabilir.

    YENİ! - ext /mysql şimdi PHP 5.5'ten itibaren resmi olarak kullanımdan kaldırıldı!

    Yeni! ext /mysql PHP 7’de kaldırıldı .

  • Bunun yerine hazırlanmış ifadeleri öğrenmelisiniz

    mysql uzantısı, hazırlanmış ifadeleri desteklemez; bu, (diğer şeylerin yanı sıra) SQL Injection 'a karşı çok etkili bir önlemdir. MySQL'e bağlı uygulamalarda, saldırganların betiğinize erişmesini ve veritabanında olası tüm sorguları gerçekleştirmesini sağlayan çok ciddi bir güvenlik açığı düzeltildi.

    Daha fazla bilgi için bkz. SQL’i nasıl önleyebilirim? PHP'ye enjeksiyon mu?

  • Kırmızı Kutuya Bakın?

    Herhangi bir IN (...) construct işlev manuel sayfasına gittiğinizde, artık kullanılmaması gerektiğini açıklayan kırmızı bir kutu görürsünüz.

  • PDO veya MySQLi kullanın

    Daha iyi, daha sağlam ve sağlam alternatifler var, PDO - PHP Veritabanı Nesnesi üçlü>, veritabanı etkileşimine tam bir OOP yaklaşımı sunar ve MySQLi 'dir. MySQL'e özgü bir gelişme.

291
2017-12-25 17: 58: 46Z
  1. Bir şey daha var: Sanırım bu işlev PHP'de hala tek bir nedenden ötürü var - eski, modası geçmiş ancak hala çalışan CMS, e-ticaret, ilan tahtası Sistemler vb. Sonunda kaldırılacak ve başvurunuzu yeniden yazmak zorunda kalacaksınız ...
    2012-11-13 11: 49: 48Z
  2. @ Kamil: Bu doğru, ancak kullanmamanızın nedeni bu değil. Kullanmamak için nedeni eski, güvensiz, vs. olmasıdır. :)
    2012-11-13 11: 50: 43Z
  3. @ Mario - PHP devs bir işlem var ve sadece 5.5'ten beri resmen kullanım dışı ext /mysql lehine oy kullandılar. Artık varsayımsal bir mesele değil.
    2012-12-10 15: 00: 10Z
  4. PDO veya MySQLi gibi kanıtlanmış bir teknikle birkaç ekstra satır eklemek, PHP'nin her zaman sunduğu kullanım kolaylığı sağlar. İnşallah uğruna, bu müthiş mysql_ * işlevlerini herhangi bir derste görmenin aslında dersten uzaklaştığını bildiğini ve OP'ye bu tür bir kodun 10 yıl önce soooo olduğunu söylemesi gerektiğini ve öğreticinin alaka düzeyi de!
    2012-12-31 17: 28: 34Z
  5. Cevabın ne söyleyebileceği: hazırlanan ifade pdo_'un anlamlı bir şekilde kullanılmasını engeller.
    2013-12-14 19: 36: 06Z

Kullanım kolaylığı

Analitik ve sentetik sebepler zaten belirtilmişti. Yeni gelenler için, tarihli mysql_ işlevlerini kullanmayı bırakma konusunda daha önemli bir teşvik var.

Çağdaş veritabanı API'leri yalnızca kullanımı kolaydır .

Kodu basitleştirebilen çoğunlukla sınırlanmış parametrelerdir . Ve mükemmel dersler (yukarıda görüldüğü gibi) ile PDO çok zor değil.

Bir kerede daha büyük bir kod tabanının yeniden yazılması ancak zaman alır. Bu ara alternatif için Raison d'être:

Eşdeğer pdo_ *, mysql_ * yerine çalışır

& > > Eski mysql_ işlevlerinden minimum çabayla geçebilirsiniz. mysql_ meslektaşlarının yerini alan include_once( işlev sarmalayıcıları ekler.

  1. Her bir komut dosyasında "pdo_mysql.php" ); mysql_ veritabanı ile etkileşime girme.

  2. pdo_ İşlev önekini her yerde kaldırın ve mysql_ ile değiştirin.

    • connect() pdo_, connect() mysql_ olur
    • query() pdo_, query() mysql_ olur
    • num_rows() pdo_, num_rows() mysql_ olur
    • insert_id() pdo_, insert_id() mysql_ olur
    • fetch_array() pdo_, fetch_array() mysql_ olur
    • fetch_assoc() pdo_, fetch_assoc() mysql_ olur
    • real_escape_string() pdo_, real_escape_string()
      include_once("pdo_mysql.php"); 
      
      pdo_connect("localhost", "usrABC", "pw1234567");
      pdo_select_db("test");
      
      $result = pdo_query("SELECT title, html FROM pages");  
      
      while ($row = pdo_fetch_assoc($result)) {
          print "$row[title] - $row[html]";
      }
      
      olur
    • vb. ...

  3. Kodunuz aynı şekilde çalışacak ve hala aynı görünüyor:

     pdo_query()

Et voilà.
Kodunuz kullanarak PDO.
Şimdi aslında yararlanma zamanı.

Bağlı parametrelerin kullanımı kolay olabilir

Daha az hantal bir API’ye ihtiyacınız var.

pdo_query(), ilişkili parametreler için çok kolay destek sağlar. Eski kodu dönüştürme basittir:

Değişkenlerinizi SQL dizesinin dışına taşıyın.

  • Bunları virgülle ayrılmış işlev parametreleri olarak ?'a ekleyin.
  • ' numaralı soru işaretini değişkenlerin önceden olduğu yer tutucu olarak yerleştirin.
  • Önceden dize değerleri /değişkenleri içine alan
    pdo_query("SELECT id, links, html, title, user, date FROM articles
       WHERE title='" . pdo_real_escape_string($title) . "' OR id='".
       pdo_real_escape_string($title) . "' AND user <> '" .
       pdo_real_escape_string($root) . "' ORDER BY date")
    
    tek tırnaktan kurtulun.

Uzun kod için avantaj daha belirgin hale gelir.

Genellikle dize değişkenleri yalnızca SQL'e dahil değildir, ancak aradaki kaçan çağrılarla birleştirilir.

 ?

Uygulanan

pdo_query("SELECT id, links, html, title, user, date FROM articles
   WHERE title=? OR id=? AND user<>? ORDER BY date", $title, $id, $root)
yer tutucu ile bununla uğraşmanıza gerek yok:  :named

Pdo_ * 'un veya ' e hala izin verdiğini unutmayın.
ve değişkenlerinden kaçmayın, aynı sorguda bağlayın.

  • Yer tutucu özelliği, arkasındaki gerçek PDO tarafından sağlanır.
  • Böylece daha sonra <form> yer tutucu listesine da izin verilir.

Daha da önemlisi, $_REQUEST [] değişkenlerini herhangi bir sorgunun arkasına güvenle iletebilirsiniz. Gönderilen

pdo_query("INSERT INTO pages VALUES (?,?,?,?,?)", $_POST);
alan veritabanı yapısıyla eşleştiğinde, tam olarak daha kısa:  mysql_

Çok basitlik. Ancak, neden yeniden yazma önerileri ve neden sanitize() ve kaçmak isteyebileceğinizle ilgili teknik nedenlere geri dönelim.

Eski okulları düzeltin ya da kaldırın mysql_ işlevi

Tüm pdo_query çağrıları, ilişkili params ile pdo_real_escape_string’a dönüştürdüğünüzde, gereksiz sanitize çağrıları kaldırın.

Özellikle, tarihli öğreticiler tarafından ilan edilen clean veya filterThis veya clean_data veya

function sanitize($str) {
   return trim(strip_tags(htmlentities(pdo_real_escape_string($str))));
}
işlevleri bir biçimde veya diğer hallerde düzeltmelisiniz:  stripslashes

Buradaki göze batan hata ise dokümantasyon eksikliğidir. Daha da önemlisi, filtreleme sırası tamamen yanlış sıradaydı.

  • Doğru sipariş şu şekilde olurdu: en içteki çağrı olarak trim, daha sonra strip_tags, daha sonra htmlentities, _escape_string, çıkış bağlamı için _real_escape_string ve yalnızca son olarak da sanitize(), uygulamanın doğrudan SQL ara satımını önceden alması gerekirdi.

  • Ancak ilk adım olarak yalnızca stripslashes() çağrıdan kurtulun .

  • Veritabanınız ve uygulama akışınız HTML bağlamında güvenli dizeler bekliyorsa, magic_quotes işlevinizin geri kalanını şimdilik saklamanız gerekebilir. Yalnızca bundan sonra kaçan HTML'yi uyguladığına ilişkin bir yorum ekleyin.

  • Dize /değer handling, PDO'ya ve parametreleştirilmiş ifadelerine devredilmiştir.

  • Dezenfekte etme fonksiyonunuzda stripslashes()'dan herhangi bir söz varsa, bu daha yüksek düzeyde bir gözetimi gösterebilir.

      

    Magic_quotes hakkındaki tarihi not. Bu özellik doğru olarak kullanımdan kaldırılmıştır. Bununla birlikte, genellikle yanlış bir güvenlik özelliği olarak gösteriliyor. Ancak magic_quotes, tenis topları beslenme kaynağı olarak başarısız olduğu kadar başarısız bir güvenlik özelliğidir. Bu sadece onların amacı değildi.

         

    PHP2 /FI'daki orijinal uygulama açıkça " tırnak işaretleri" ile otomatik olarak çıkarılacak ve form verilerinin doğrudan msql sorgularına aktarılmasını kolaylaştıracak. Özellikle, yalnızca ASCII destekli olduğu gibi mSQL ile kullanmak yanlışlıkla güvenliydi.
      Sonra PHP3 /Zend, MySQL için magic_quotes öğesini yeniden sunmuş ve yanlış belgelendirmiştir. Ancak başlangıçta sadece bir rahatlık özelliği oldu , güvenlik amaçlı değil.

Hazırlanan ifadelerin farkı nedir

Dize değişkenlerini SQL sorgularına karıştırdığınızda, izlemeniz sadece karmaşıklaşmaz. Ayrıca, MySQL'in kodu ve verileri tekrar ayırması çok büyük bir çaba.

SQL enjeksiyonları, verinin koda girdiği içeriktir. Bir veritabanı sunucusu, daha sonra PHP'nin, sorgu cümleleri arasındaki değişkenleri ilk önce yapıştırdığı yeri göremez.

İlişkili parametrelerle, PHP kodunuzda SQL kodu ve SQL bağlamı değerlerini ayırırsınız. Ancak sahnelerin arkasına tekrar karıştırılmıyor (PDO :: EMULATE_PREPARES hariç). Veritabanınız değişmemiş SQL komutlarını ve 1: 1 değişken değerlerini alır.

Bu yanıt, MYSQLI bırakmanın okunabilirlik avantajlarına önem vermeniz gerektiğini vurgulamakla birlikte. Bu görünür ve teknik veri /kod ayrımı nedeniyle zaman zaman bir performans avantajı da vardır (sadece farklı değerlere sahip tekrarlanan INSERT'ler).

Parametre bağlamanın hala tümü SQL enjeksiyonlarına karşı sihirli bir tek durak çözüm olmadığına dikkat edin. Veri /değerler için en yaygın kullanımı gerçekleştirir. Ancak sütun adını /tablo tanımlayıcılarını beyaz listeye alamaz, dinamik yan tümce yapımında yardımcı olabilir veya yalnızca düz dizi değer listelerini kullanamazsınız.

Hibrit PDO kullanımı

Bu

$result = pdo_query("SELECT * FROM tbl");
while ($row = pdo_fetch_assoc($result)) {
sarmalayıcı işlevi, kodlama dostu bir duruş açığı API'si oluşturur. (
foreach ($result as $row) {
'un kendine özgü işlev imzası değişimi için olmasaydı ne olabileceği hemen hemen öyleydi). Aynı zamanda gerçek PDO'yu çoğu zaman ortaya çıkarırlar.
Yeniden yazma işleminin yeni pdo_ işlev adlarını kullanmayı bırakması gerekmez. Her pdo_query () işlevini düz bir $pdo- > prepare () - > execute () çağrısına tek tek geçiş yapabilirsiniz.

Yine de basitleştirmeye başlamak en iyisidir. Örneğin, genel sonuç alma:

 
$result->fetchAll();

Yalnızca bir foreach yineleme ile değiştirilebilir:

 mysql_

Veya daha iyisi henüz doğrudan ve tam bir dizi alma:

 pdo_query()

Çoğu durumda, PDO veya mysql_'nin genellikle başarısız sorgulardan sonra sağladığından daha fazla yardımcı uyarılar elde edersiniz.

Diğer seçenekler

Bu nedenle, bazı pratik nedenleri ve pdo_query("INSERT INTO pages VALUES (?,?,?,?,?)", $_POST); 'i bırakmanın değerli bir yolunu umarım görselleştirdi.

Sadece etiketli soruları gösterme kes onu. pdo_query("INSERT INTO users VALUES (?, ?, ?), $_POST); $_POST = array( 'username' => 'lawl', 'password' => '123', 'is_admin' => 'true'); aynı zamanda sadece bir ön uç.

Parametre bağlamayı da sağlamadığınız ya da daha hoş olan API'den başka bir şey kullanamadığınız sürece, bu anlamsız bir anahtardır. İnşallah yeni gelenlere karşı cesaret kırıcılığını ilerletmeyecek kadar basit. (Eğitim genellikle yasaklamadan daha iyi çalışır.)

Çalışması mümkün olan en basit şey için uygun olsa da, yine de çok deneysel bir koddur. Sadece haftasonu yazdım. Ancak bir sürü alternatif var. PHP veritabanı soyutlaması için Google’a gidin ve biraz göz atın. Bu tür görevler için her zaman birçok mükemmel kitaplık olmuştur ve olacaktır.

Veritabanınızla etkileşimi basitleştirmek istiyorsanızDahası, Paris /Idiorm gibi haritalayıcılar denenmeye değer. Tıpkı kimse JavaScript’de mülayim DOM’u kullanmıyor gibi, bugünlerde ham bir veritabanı arayüzüne bakmanıza gerek yok.

    
210
2017-05-23 12: 03: 09Z
  1. mysql_ işlevine dikkat edin - yani: mysqli_
    2014-01-22 16: 35: 44Z
  2. @ Tom Tabii, çok fazla bakılmamasına rağmen (en son 0.9.2 idi), bir fosil hesabı , wiki’ye ekleyin veya bir hata raporu (IIRC kaydı olmadan).
    2017-03-08 14: 34: 46Z

mysql_* işlevi:

  1. güncel değil - daha fazla korunmuyorlar
  2. kolayca başka bir veritabanı arka ucuna gitmenize izin verme
  3. hazırlanmış ifadeleri desteklemiyor, dolayısıyla
  4. , programcıları sorgu oluşturmak için birleştirme kullanmaya teşvik ederek SQL enjeksiyon güvenlik açıklarına yol açtı
138
2017-12-26 16: 00: 27Z
  1. # 2 aynı şekilde mysql_query("CALL my_proc"); için de geçerlidir
    2012-10-12 13: 35: 47Z
  2. , SQL lehçesindeki farklılıklar göz önüne alındığında, adil olmak gerekirse, PDO bile hiçbir dereceye kadar kesin olarak # 2 vermez. Bunun için uygun bir ORM paketleyicisine ihtiyacınız olacak.
    2012-10-23 14: 55: 00Z
  3. @ SDC gerçekten - standartlarla ilgili sorun şu ki öyleyse çoğunda ...
    2012-10-23 15: 06: 36Z
  4. 2012-12-24 14: 30: 36Z
  5. function paraQuery()
    {
        $args  = func_get_args();
        $query = array_shift($args);
        $query = str_replace("%s","'%s'",$query); 
    
        foreach ($args as $key => $val)
        {
            $args[$key] = mysql_real_escape_string($val);
        }
    
        $query  = vsprintf($query, $args);
        $result = mysql_query($query);
        if (!$result)
        {
            throw new Exception(mysql_error()." [$query]");
        }
        return $result;
    }
    
    $query  = "SELECT * FROM table where a=%s AND b LIKE %s LIMIT %d";
    $result = paraQuery($query, $a, "%$b%", $limit);
    
    işlevi, daha yeni PHP sürümleri için mysqlnd işlevlerine bir kabuktur. Bu nedenle, eski istemci kitaplığı artık korunmasa bile, mysqlnd korunur :) :)
    2013-05-31 14: 25: 06Z

    Teknik sebeplerden bahsetmişken, sadece çok az, çok spesifik ve nadiren kullanılır. Büyük olasılıkla onları hayatında asla kullanmayacaksın.
    Belki de çok cahilimdir, ama bunları kullanma gibi hiçbir zaman bir fırsatım olmadı

    • engellenmeyen, zaman uyumsuz sorgular
    • birden fazla sonuç döndüren saklı yordamlar
    • Şifreleme (SSL)
    • Sıkıştırma

    Onlara ihtiyacınız varsa - bunlar şüphesiz, mysql uzantısından daha şık ve modern görünümlü bir şeye doğru ilerlemenin teknik nedenleridir.

    Bununla birlikte, deneyiminizi biraz daha zorlaştıracak teknik olmayan bazı sorunlar da var

    • bu işlevlerin modern PHP sürümleriyle daha fazla kullanılması, kullanımdan kaldırılmış bildirimleri artırır. Sadece kapatılabilirler.
    • uzak bir gelecekte, varsayılan PHP yapısından kaldırılabilirler. Çok fazla bir şey değil, çünkü mydsql ext, PECL'e taşınacak ve sitelerinde yıllarca çalışan müşterilerini kaybetmek istemedikleri için PHP'yi derlemekle mutlu olacaklar.
    • Stackoverflow topluluğundan güçlü bir direnç. Her zaman bu dürüst işlevlerden bahsettiniz, size sıkı bir tabu altında oldukları söylendi.
    • ortalama bir PHP kullanıcısı olmakla birlikte, büyük olasılıkla bu işlevleri kullanma fikriniz hataya açık ve yanlıştır. Sadece sana yanlış yolu öğreten tüm bu sayısız öğretici ve el kitabından dolayı. İşlevlerin kendisi değil -Vurgulamalıyım - ama kullanma biçimleri.

    Bu son sorun bir sorundur.
    Ancak bence önerilen çözüm de daha iyi değil.
    Bana göre bu, tüm PHP kullanıcılarının bir kerede SQL sorgularını doğru bir şekilde nasıl kullanacaklarını öğrenecekleri çok idealist . Büyük olasılıkla, mysql_ * 'u mysqli_ *' a mekanik olarak değiştirmeleri, yaklaşımı aynı bırakması . Özellikle, mysqli hazırlanan açıklamalar yaptığını inanılmaz acılı ve zahmetli kullanıyor. yerel hazırlanan ifadelerin SQL enjeksiyonlarından korunmaya yetmediği anlamına gelmez ve ne mysqli ne de PDO bir çözüm sunmaz.

    Dolayısıyla, bu dürüst uzantıyla mücadele etmek yerine, yanlış uygulamalarla savaşmayı ve insanları doğru şekilde eğitmeyi tercih ederim.

    Ayrıca, bazı yanlış veya önemli olmayan nedenler de var, örneğin

    • Saklı İşlemleri desteklemiyor (yaş için
      $city_ids = array(1,2,3);
      $cities   = $db->getCol("SELECT name FROM cities WHERE is IN(?a)", $city_ids);
      
      kullanıyorduk)
    • İşlemleri desteklemiyor (yukarıdakiyle aynı)
    • Çoklu İfadeleri desteklemiyor (kim onlara ihtiyaç duyuyor?)
    • Aktif geliştirilme aşamasında değil (peki bu nedir? sizi herhangi bir şekilde etkiler mi?)
    • Bir OO arayüzü yok (bir tane oluşturmak birkaç saat meselesidir)
    • Hazırlanan İfadeleri veya Parametrelenmiş Sorguları desteklemiyor

    Sonuncusu ilginç bir nokta. Mysql ext, yerel hazırlanmış açıklamaları desteklemese de, güvenlik için gerekli değildir. Elle yapılan yer tutucuları kullanarak hazırlanmış ifadeleri kolayca sahte yapabiliriz (PDO'nun yaptığı gibi):

     
    $insert = array('name' => 'John', 'surname' => "O'Hara");
    $db->query("INSERT INTO users SET ?u", $insert);
    

    voila , her şey parametreli ve güvenlidir.

    Ama tamam, kılavuzdaki kırmızı kutuyu beğenmiyorsanız, seçimde bir sorun ortaya çıkıyor: mysqli veya PDO?

    Pekala, cevap şu şekilde olurdu:

    • Bir veritabanı soyutlama katmanı kullanmanın ve bir API oluşturmak için bir API aramanın gerekliliğini anlıyorsanız, mysqli gerçekten çok mysql'i desteklediği için çok iyi bir seçimdir. özel özellikler.
    • PHP milletvekillerinin büyük çoğunluğu gibi, uygulama kodunda ham API çağrıları kullanıyorsanız (bu aslında yanlış bir uygulamadır) - Bu uzantı göründüğü gibi PDO tek seçenek sadece API değil, yarı DAL, yine de eksik ama birçok önemli özellik sunuyor, ikisi de PDO'yu mysqli'den eleştirel olarak ayırıyor:

      • mysqli'den farklı olarak, PDO yer tutucuları değerine göre bağlayabilir , bu da dinamik bir şekilde oluşturulan sorguları oldukça karışık kodlu birkaç ekran olmadan yapılabilir.
      • mysqli'den farklı olarak, PDO her zamanki basit bir dizide sorgu sonucunu her zaman döndürürken, mysqli bunu yalnızca mysqlnd kurulumlarında yapabilir.

    Yani, ortalama bir PHP kullanıcısıysanız ve yerel hazırlanmış ifadeleri kullanırken kendinize bir sürü sıkıntıdan kurtulmak istiyorsanız, PDO - tekrar - tek seçenek budur.
    Ancak, PDO da gümüş mermi değildir ve zorlukları vardır.
    Bu nedenle, PDO etiketi wiki 'de tüm yaygın tuzaklar ve karmaşık durumlar için çözümler yazdım. /p>

    Yine de, uzantılardan bahseden herkes her zaman Mysqli ve PDO ile ilgili 2 önemli gerçeği eksik:

    1. Hazırlanan açıklama gümüş bir kurşun değildir . Hazırlanan ifadeler kullanılarak bağlanamayan dinamik tanımlayıcılar vardır. Sorgu oluşturmayı zorlaştıran bir dizi parametreli dinamik sorgu var.

    2. Uygulama kodunda ne mysqli_ * ne de PDO işlevleri görünmemeliydi.
      Uygulama kodunu KURU ve temiz hale getiren tüm kirli ciltleme, döngü, hata işleme vb. İşlerini yapacak olan uygulama kodu ile aralarında bir soyutlama katmanı olması gerekir. Özellikle dinamik sorgu oluşturma gibi karmaşık durumlar için.

    Yani sadece PDO veya mysqli'ye geçmek yeterli değil. Birinin bir ORM, bir sorgu oluşturucu veya kodlarında ham API işlevlerini çağırmak yerine herhangi bir veritabanı soyutlama sınıfı kullanması gerekir.
    Ve aksine - uygulama kodunuzla mysql API'niz arasında bir soyutlama katmanınız varsa - hangi motorun kullanıldığının önemi yoktur. Mysql ext komutunu kullanana kadar kullanabilir ve ardından soyutlamanızı kolayca yeniden yazabilirsiniz. tüm uygulama kodunu eksiksiz tutan başka bir motora ders verin.

    İşte safemysql sınıfına yönelik bazı örnekler böyle bir soyutlama sınıfının nasıl olması gerektiğini gösterin:

     
    $data = $db->getAll("SELECT * FROM goods ORDER BY ?n", $_GET['order']);
    

    Bu tek satırı, PDO ile ihtiyacınız olacak kod miktarı ile karşılaştırın.
    Sonra çılgın kod miktarı , ham Mysqli'nin hazırladığı ifadelerle ihtiyaç duyacak. Hata işleme, profil oluşturma, sorgu günlüğünün zaten yerleşik ve çalışıyor olduğunu unutmayın.

     mysql_*

    Her bir alan adı altı ila on kez tekrarlandığında - bu çok sayıda adlandırılmış yer tutucu, ciltleme ve sorgu tanımlarında, normal PDO ekleriyle karşılaştırın.

    Başka bir örnek:

     mysql_*

    Böyle bir pratik olayı ele almak için PDO'ya bir örnek bulamazsınız.
    Ve çok endişeli ve büyük olasılıkla güvensiz olacak.

    Öyleyse, bir kez daha - sadece ham sürücü değil, yalnızca sizin endişeniz değil soyutlama sınıfınız olmalı, yalnızca başlangıç ​​el kitabındaki saçma örnekler için değil, gerçek hayattaki sorunları çözmek için faydalıdır.

        
    103
    2017-12-25 17: 32: 07Z
    1. everything is parameterized and safe, güvenlik açıklarını çok daha kolay hale getirmektedir. PHP bir çok acemi kullanıcı tarafından kullanıldığından, teorik olarak bir aksama olmadan da kullanılabilse bile Not under active development pratikte aktif olarak zararlıdır.
      2013-01-01 17: 48: 46Z
    2. deprecated - parametreleştirilebilir, ancak işleviniz real hazırlanmış ifadeleri kullanmaz.
      2013-01-03 06: 07: 47Z
    3. not under active development yalnızca '% 0.01' telafisi için nasıl? Bu sabit işlevle bir şey inşa ederseniz, bir yıl içinde mysql sürümünüzü güncelleyin ve çalışmayan bir sistemle başlayın, aniden bu “% 0.01” de çok fazla insan bulunduğundan eminim. no active development ve deprecated'un yakından ilişkili olduğunu söyleyebilirim. Bunun için "[makul] sebep" olmadığını söyleyebilirsiniz, ancak gerçek şu ki, seçenekler arasında bir seçim yapıldığında, mysql_* neredeyse mysql_real_escape_string() kadar söyleyeceğim kadar kötü?
      2013-02-01 10: 21: 50Z
    4. @ MadaraUchiha: Güvenlik açıklarının ne kadar kolay gelebileceğini açıklayabilir misiniz? Özellikle aynı güvenlik açıklarının PDO veya MySQLi'yi etkilemediği durumlarda ... Çünkü bahsettiğiniz birisinin farkında değilim.
      2013-02-04 12: 42: 02Z
    5. @ ShaquinTrifonoff: elbette, hazırlanan ifadeleri kullanmaz. Ancak PDO da yapmaz çoğu kişi MySQLi üzerinden tavsiye eder. Bu yüzden burada önemli bir etkisinin olduğundan emin değilim. Yukarıdaki kod (biraz daha fazla ayrıştırma ile), varsayılan olarak bir ifade hazırladığınızda PDO'nun yaptığı şeydir ...
      2013-02-04 12: 44: 37Z

    Pek çok neden var, ama belki de en önemlisi, bu işlevlerin güvenli olmayan programlama uygulamalarını teşvik etmeleridir, çünkü hazırlanan ifadeleri desteklememektedir. Hazırlanan ifadeler, SQL enjeksiyon saldırılarını önlemeye yardımcı olur.

    PDO işlevlerini kullanırken, kullanıcı tarafından sağlanan parametreleri mysqli'da çalıştırmayı hatırlamanız gerekir. Yalnızca bir yerde unutursanız veya girişin yalnızca bir bölümünden kaçarsanız, veritabanınız saldırıya uğramış olabilir.

    Hazırlanan açıklamaların "enhzflep); drop table users" veya "enhzflep); drop table users"'da kullanılması, bu tür programlama hatalarının yapılmasını zorlaştıracaktır.

        
    89
    2012-10-12 13: 41: 23Z
    1. Maalesef MySQLi_ * 'de ki değişken sayıda parametre (örneğin bir IN cümlesinde kontrol edilecek değerlerin bir listesini iletmek istediğinizde) geçirmek için zayıf destek parametrelerin kullanılmaması, MySQL_ * adında aynı bitiştirilmiş sorguların kullanılmasını teşvik etmek, savunmasız kalır.
      2013-06-27 09: 31: 27Z
    2. Ancak, bir kez daha güvensizlik, mysql_ * işlevlerinin doğal bir sorunu değil, yanlış kullanım sorunudur.
      2014-02-02 05: 29: 57Z
    3. @ Agamemnus Sorun şu ki, mysql_ *, özellikle deneyimsiz programcılar için bu "yanlış kullanımı" kolaylaştırabilir. Hazırlanan ifadeleri uygulayan kütüphaneler bu tür bir hata yapmayı zorlaştırır.
      2014-02-02 16: 33: 48Z

    Çünkü (diğer nedenlerin yanı sıra), girdi verilerinin sterilize edilmesini sağlamak çok daha zor. Parametreli sorgular kullanıyorsanız, biri PDO veya mysqli'de olduğu gibi, riskten tamamen kaçınabilirsiniz.

    Örnek olarak, birisi The old functions will allow executing of multiple statements per query'u kullanıcı adı olarak kullanabilir. Eski işlevler, sorgu başına birden fazla ifade çalıştırılmasına izin verecek, böylece kötü bir böcek gibi bir tablonun tamamını silebilir.

    Eğer biri mysqli'nin PDO'sunu kullanacak olsaydı, kullanıcı adı mysqli_multi_query() olur.

    Bkz. bobby-tables.com .

        
    72
    2017-12-25 18: 25: 56Z
    1. ' OR '1' = '1 - hayır, olmaz. Ext /mysql ile bu tür bir enjeksiyon mümkün değildir - bu tür bir enjeksiyonun PHP ve MySQL ile mümkün olmasının tek yolu MySQLi ve
      mysql> create table users(
          -> id int(2) primary key auto_increment,
          -> userid tinytext,
          -> pass tinytext);
      Query OK, 0 rows affected (0.05 sec)
      
      mysql> insert into users values(null, 'Fluffeh', 'mypass');
      Query OK, 1 row affected (0.04 sec)
      
      mysql> create user 'prepared'@'localhost' identified by 'example';
      Query OK, 0 rows affected (0.01 sec)
      
      mysql> grant all privileges on prep.* to 'prepared'@'localhost' with grant option;
      Query OK, 0 rows affected (0.00 sec)
      
      işlevini kullanırken. Ext /mysql ve çıkmamış dizelerle mümkün kılınan enjeksiyon, erişilebilir olması amaçlanmayan veritabanından veri çıkarmak için
      <?php 
      
          if(!empty($_POST['user']))
          {
              $user=$_POST['user'];
          }   
          else
          {
              $user='bob';
          }
          if(!empty($_POST['pass']))
          {
              $pass=$_POST['pass'];
          }
          else
          {
              $pass='bob';
          }
      
          $database='prep';
          $link=mysql_connect('localhost', 'prepared', 'example');
          mysql_select_db($database) or die( "Unable to select database");
      
          $sql="select id, userid, pass from users where userid='$user' and pass='$pass'";
          //echo $sql."<br><br>";
          $result=mysql_query($sql);
          $isAdmin=false;
          while ($row = mysql_fetch_assoc($result)) {
              echo "My id is ".$row['id']." and my username is ".$row['userid']." and lastly, my password is ".$row['pass']."<br>";
              $isAdmin=true;
              // We have correctly matched the Username and Password
              // Lets give this person full access
          }
          if($isAdmin)
          {
              echo "The check passed. We have a verified admin!<br>";
          }
          else
          {
              echo "You could not be verified. Please try again...<br>";
          }
          mysql_close($link);
      
      ?>
      
      <form name="exploited" method='post'>
          User: <input type='text' name='user'><br>
          Pass: <input type='text' name='pass'><br>
          <input type='submit'>
      </form>
      
      gibi şeylerdir. Bazı durumlarda alt sorguları enjekte etmek mümkündür, ancak veritabanını bu şekilde değiştirmek hala mümkün değildir.
      2012-12-30 20: 58: 49Z

    Bu cevap, zayıf yazılmış PHP kullanıcı doğrulama kodunu atlamanın ne kadar önemsiz olduğunu, bu saldırıların nasıl (ve neyin kullanıldığını) ve eski MySQL işlevlerinin güvenli hazırlanmış bir ifadeyle nasıl değiştirileceğini göstermek için yazılmıştır - ve temel olarak, Neden StackOverflow kullanıcıları (muhtemelen çok sayıda rep ile) kodlarını iyileştirmek için sorular soran yeni kullanıcılara güveniyorlar.

    Öncelikle, lütfen bu testi mysql veritabanını oluşturmaktan çekinmeyin (benimki hazırlığı denedim):

     
    user: bob
    pass: somePass
    

    Bu işlemle PHP kodumuza geçebiliriz.

    Aşağıdaki komut dosyasının bir web sitesindeki bir yönetici için doğrulama işlemi olduğunu varsayalım (basitleştirilmiş ancak test için kopyalayıp kullanırsanız çalışır):

     
    You could not be verified. Please try again...
    

    İlk bakışta yeterince okunaklı görünüyor.

    Kullanıcı bir kullanıcı adı ve şifre girmek zorunda, değil mi?

    Mükemmel, aşağıya girmeyin:

     
    user: Fluffeh
    pass: mypass
    

    ve gönderin.

    Çıktı aşağıdaki gibidir:

     
    user: bob
    pass: n' or 1=1 or 'm=m
    

    Süper! Beklendiği gibi çalışıyor, şimdi gerçek kullanıcı adını ve şifreyi deneyelim:

     
    The check passed. We have a verified admin!
    

    Şaşırtıcı! Hi-fives her yerde, kod doğru bir yönetici doğruladı. Mükemmel!

    Pek sayılmaz. Diyelim ki kullanıcı zeki küçük bir insan. Diyelim ki, kişi benim.

    Aşağıdakileri girin:

     
    select id, userid, pass from users where userid='$user' and pass='$pass'
    

    Ve çıktı:

     
    select id, userid, pass from users where userid='bob' and pass='n' or 1=1 or 'm=m'
    

    Tebrikler, süper korumalı yöneticilerinize yalnızca bölüme yanlış kullanıcı adı ve yanlış şifre girmeme izin vermeme izin verdiniz. Cidden, bana inanmıyorsanız, sağladığım kodla veritabanını oluşturun ve bu PHP kodunu çalıştırın - GERÇEKTEN bir bakışta gerçekten kullanıcı adınızı ve parolanızı doğrulamak için görünüyor.

    Öyleyse, cevap olarak, NEDEN BAĞLANTIĞINIZ NEDİR?

    Öyleyse, neyin yanlış gittiğini ve neden sadece süper-yönetici-yarasa mağarasına girdiğime bir bakalım. Bir tahminde bulundum ve girdilerinize dikkat etmediğinizi varsaydım ve doğrudan veritabanına aktardım. Girdiyi, gerçekte çalıştırmakta olduğunuz sorguyu DEĞİŞTİRECEK şekilde yapılandırdım. Öyleyse, olması gereken neydi ve sonunda ne oldu?

     mysql_*

    Sorgu budur, ancak değişkenleri kullandığımız asıl girdilerle değiştirdiğimizde aşağıdakileri alırız:

     
    <?php 
    
        if(!empty($_POST['user']))
        {
            $user=$_POST['user'];
        }   
        else
        {
            $user='bob';
        }
        if(!empty($_POST['pass']))
        {
            $pass=$_POST['pass'];
        }
        else
        {
            $pass='bob';
        }
        $isAdmin=false;
    
        $database='prep';
        $pdo=new PDO ('mysql:host=localhost;dbname=prep', 'prepared', 'example');
        $sql="select id, userid, pass from users where userid=:user and pass=:password";
        $myPDO = $pdo->prepare($sql, array(PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY));
        if($myPDO->execute(array(':user' => $user, ':password' => $pass)))
        {
            while($row=$myPDO->fetch(PDO::FETCH_ASSOC))
            {
                echo "My id is ".$row['id']." and my username is ".$row['userid']." and lastly, my password is ".$row['pass']."<br>";
                $isAdmin=true;
                // We have correctly matched the Username and Password
                // Lets give this person full access
            }
        }
    
        if($isAdmin)
        {
            echo "The check passed. We have a verified admin!<br>";
        }
        else
        {
            echo "You could not be verified. Please try again...<br>";
        }
    
    ?>
    
    <form name="exploited" method='post'>
        User: <input type='text' name='user'><br>
        Pass: <input type='text' name='pass'><br>
        <input type='submit'>
    </form>
    

    "Parolam" ı nasıl oluşturduğumu görün, böylece önce parolanın etrafındaki tek teklifi kapatıp ardından tamamen yeni bir karşılaştırma yapalım mı? Sonra sadece güvenlik için, başka bir "string" ekledim, böylece tek bir teklif orijinal olarak sahip olduğumuz kodda beklendiği gibi kapanacaktı.

    Ancak bu, size şu anda bağırdığınız milletle ilgili değil, kodunuzu nasıl daha güvenli hale getireceğinizi göstermekle ilgili.

    Tamam, peki yanlış giden ne oldu ve nasıl düzeltebiliriz?

    Bu bir sınıftıric SQL enjeksiyon saldırısı. Bu konuda en basitlerinden biri. Saldırı vektörleri ölçeğinde bu, bir tanka saldıran ve kazanan bir bebek gibidir.

    Öyleyse, kutsal yönetici bölümünüzü nasıl korur ve güzel ve güvenli hale getiririz? Yapılacak ilk şey, gerçekten eski ve kullanımdan kaldırılmış mysql_* işlevlerini kullanmayı bırakmak olacaktır. Biliyorum, çevrimiçi olarak bulduğun bir öğreticiyi takip ettin ve işe yarıyor, ama eski, modası geçmiş ve birkaç dakika uzağında, daha yeni terliyorum.

    Artık mysqli_ veya PDO . Şahsen ben büyük bir PDO hayranıyım, bu yüzden bu cevabın geri kalanında PDO kullanacağım. Profesyoneller ve aleyhte olanlar var, ama şahsen ben profesyonellerin aleyhte olanlardan daha ağır olduğunu gördüm. Birden fazla veritabanı motorunda taşınabilir - ister MySQL, ister Oracle kullanıyorsunuz, isterse kanlı bir şey olsun - yalnızca bağlantı dizesini değiştirerek, kullanmak istediğimiz tüm fantezi özelliklere sahiptir ve hoş ve temizdir. Temizliği severim.

    Şimdi, bir PDO nesnesi kullanılarak yazılan bu koda tekrar bakalım:

     
    user: bob
    pass: somePass
    

    Başlıca farklar,

    user: Fluffeh
    pass: mypass
    
    fonksiyon kalmamasıdır. Hepsi bir PDO nesnesi üzerinden yapılır, ikincisi, hazırlanmış bir ifade kullanıyor. Şimdi, sorduğun hazır bir ifade nedir? Bir sorguyu çalıştırmadan önce veritabanına, sorgunun ne olduğunu çalıştıracağımızı söylemenin bir yolu. Bu durumda, veritabanına şunu söyleriz: "Merhaba, kimliği, kullanıcı kimliğini ve kullanıcı kimliğinin değişken olduğu ve kullanıcı kimliğinin de değişken olduğu tablodaki kullanıcılardan geçen bir select ifadesi çalıştıracağım.".

    Sonra, execute ifadesinde, veritabanına şimdi beklediği tüm değişkenleri içeren bir dizi iletiriz.

    Sonuçlar harika. Bu kullanıcı adı ve şifre kombinasyonlarını daha önce tekrar deneyelim:

     
    user: bob
    pass: n' or 1=1 or 'm=m
    

    Kullanıcı doğrulanmadı. Olağanüstü.

    Peki ya:

     
    You could not be verified. Please try again...
    

    Oh, biraz heyecanlandım, işe yaradı: Kontrol geçti. Doğrulanmış bir yöneticimiz var!

    Şimdi, küçük doğrulama sistemimizi geçmeye çalışmak için akıllı bir bölümün gireceği verileri deneyelim:

     mysql_*

    Bu sefer aşağıdakileri alıyoruz:

     mysql_*

    Bu nedenle soru gönderirken bağırıyor olmanızın nedeni - insanlar, denemenize rağmen kodunuzun atlanabileceğini görmeleridir. Lütfen kodunuzu geliştirmek, daha güvenli hale getirmek ve geçerli işlevleri kullanmak için bu soruyu ve yanıtı kullanın.

    Son olarak, bu MÜKEMMEL kod olduğunu söylemek değildir. İyileştirmek için yapabileceğiniz birçok şey var, örneğin şifreli şifreler kullanın, hassas bilgileri veritabanında sakladığınızda, düz metin olarak saklamayın, birden fazla doğrulama seviyesine sahip olun. Sadece eski enjeksiyon eğilimli kodunuzu değiştirirseniz, iyi kod yazma yolunda WELL olacaksınız - ve bu ana kadar okuduğunuz ve hala okuduğunuz gerçeği bana sadece bu tipte bir uygulama yapmamaya dair bir umut duygusu veriyor. web sitelerinizi ve uygulamalarınızı yazarken kodun dışına çıkacak, ancak dışarı çıkıp biraz önce bahsettiğim diğer şeyleri araştırabilirsiniz - ve daha fazlası. Zorlukla çalışan en temel kodu değil, yazabileceğiniz en iyi kodu yazın.

        
    62
    2013-09-18 12: 50: 54Z
    1. Cevabınız için teşekkürler! + 1'imi al!
      <?php
      
      define('MYSQL_LINK', 'dbl');
      $GLOBALS[MYSQL_LINK] = null;
      
      function mysql_link($link=null) {
          return ($link === null) ? $GLOBALS[MYSQL_LINK] : $link;
      }
      
      function mysql_connect($host, $user, $pass) {
          $GLOBALS[MYSQL_LINK] = mysqli_connect($host, $user, $pass);
          return $GLOBALS[MYSQL_LINK];
      }
      
      function mysql_pconnect($host, $user, $pass) {
          return mysql_connect($host, $user, $pass);
      }
      
      function mysql_select_db($db, $link=null) {
          $link = mysql_link($link);
          return mysqli_select_db($link, $db);
      }
      
      function mysql_close($link=null) {
          $link = mysql_link($link);
          return mysqli_close($link);
      }
      
      function mysql_error($link=null) {
          $link = mysql_link($link);
          return mysqli_error($link);
      }
      
      function mysql_errno($link=null) {
          $link = mysql_link($link);
          return mysqli_errno($link);
      }
      
      function mysql_ping($link=null) {
          $link = mysql_link($link);
          return mysqli_ping($link);
      }
      
      function mysql_stat($link=null) {
          $link = mysql_link($link);
          return mysqli_stat($link);
      }
      
      function mysql_affected_rows($link=null) {
          $link = mysql_link($link);
          return mysqli_affected_rows($link);
      }
      
      function mysql_client_encoding($link=null) {
          $link = mysql_link($link);
          return mysqli_character_set_name($link);
      }
      
      function mysql_thread_id($link=null) {
          $link = mysql_link($link);
          return mysqli_thread_id($link);
      }
      
      function mysql_escape_string($string) {
          return mysql_real_escape_string($string);
      }
      
      function mysql_real_escape_string($string, $link=null) {
          $link = mysql_link($link);
          return mysqli_real_escape_string($link, $string);
      }
      
      function mysql_query($sql, $link=null) {
          $link = mysql_link($link);
          return mysqli_query($link, $sql);
      }
      
      function mysql_unbuffered_query($sql, $link=null) {
          $link = mysql_link($link);
          return mysqli_query($link, $sql, MYSQLI_USE_RESULT);
      }
      
      function mysql_set_charset($charset, $link=null){
          $link = mysql_link($link);
          return mysqli_set_charset($link, $charset);
      }
      
      function mysql_get_host_info($link=null) {
          $link = mysql_link($link);
          return mysqli_get_host_info($link);
      }
      
      function mysql_get_proto_info($link=null) {
          $link = mysql_link($link);
          return mysqli_get_proto_info($link);
      }
      function mysql_get_server_info($link=null) {
          $link = mysql_link($link);
          return mysqli_get_server_info($link);
      }
      
      function mysql_info($link=null) {
          $link = mysql_link($link);
          return mysqli_info($link);
      }
      
      function mysql_get_client_info() {
          $link = mysql_link();
          return mysqli_get_client_info($link);
      }
      
      function mysql_create_db($db, $link=null) {
          $link = mysql_link($link);
          $db = str_replace('`', '', mysqli_real_escape_string($link, $db));
          return mysqli_query($link, "CREATE DATABASE `$db`");
      }
      
      function mysql_drop_db($db, $link=null) {
          $link = mysql_link($link);
          $db = str_replace('`', '', mysqli_real_escape_string($link, $db));
          return mysqli_query($link, "DROP DATABASE `$db`");
      }
      
      function mysql_list_dbs($link=null) {
          $link = mysql_link($link);
          return mysqli_query($link, "SHOW DATABASES");
      }
      
      function mysql_list_fields($db, $table, $link=null) {
          $link = mysql_link($link);
          $db = str_replace('`', '', mysqli_real_escape_string($link, $db));
          $table = str_replace('`', '', mysqli_real_escape_string($link, $table));
          return mysqli_query($link, "SHOW COLUMNS FROM `$db`.`$table`");
      }
      
      function mysql_list_tables($db, $link=null) {
          $link = mysql_link($link);
          $db = str_replace('`', '', mysqli_real_escape_string($link, $db));
          return mysqli_query($link, "SHOW TABLES FROM `$db`");
      }
      
      function mysql_db_query($db, $sql, $link=null) {
          $link = mysql_link($link);
          mysqli_select_db($link, $db);
          return mysqli_query($link, $sql);
      }
      
      function mysql_fetch_row($qlink) {
          return mysqli_fetch_row($qlink);
      }
      
      function mysql_fetch_assoc($qlink) {
          return mysqli_fetch_assoc($qlink);
      }
      
      function mysql_fetch_array($qlink, $result=MYSQLI_BOTH) {
          return mysqli_fetch_array($qlink, $result);
      }
      
      function mysql_fetch_lengths($qlink) {
          return mysqli_fetch_lengths($qlink);
      }
      
      function mysql_insert_id($qlink) {
          return mysqli_insert_id($qlink);
      }
      
      function mysql_num_rows($qlink) {
          return mysqli_num_rows($qlink);
      }
      
      function mysql_num_fields($qlink) {
          return mysqli_num_fields($qlink);
      }
      
      function mysql_data_seek($qlink, $row) {
          return mysqli_data_seek($qlink, $row);
      }
      
      function mysql_field_seek($qlink, $offset) {
          return mysqli_field_seek($qlink, $offset);
      }
      
      function mysql_fetch_object($qlink, $class="stdClass", array $params=null) {
          return ($params === null)
              ? mysqli_fetch_object($qlink, $class)
              : mysqli_fetch_object($qlink, $class, $params);
      }
      
      function mysql_db_name($qlink, $row, $field='Database') {
          mysqli_data_seek($qlink, $row);
          $db = mysqli_fetch_assoc($qlink);
          return $db[$field];
      }
      
      function mysql_fetch_field($qlink, $offset=null) {
          if ($offset !== null)
              mysqli_field_seek($qlink, $offset);
          return mysqli_fetch_field($qlink);
      }
      
      function mysql_result($qlink, $offset, $field=0) {
          if ($offset !== null)
              mysqli_field_seek($qlink, $offset);
          $row = mysqli_fetch_array($qlink);
          return (!is_array($row) || !isset($row[$field]))
              ? false
              : $row[$field];
      }
      
      function mysql_field_len($qlink, $offset) {
          $field = mysqli_fetch_field_direct($qlink, $offset);
          return is_object($field) ? $field->length : false;
      }
      
      function mysql_field_name($qlink, $offset) {
          $field = mysqli_fetch_field_direct($qlink, $offset);
          if (!is_object($field))
              return false;
          return empty($field->orgname) ? $field->name : $field->orgname;
      }
      
      function mysql_field_table($qlink, $offset) {
          $field = mysqli_fetch_field_direct($qlink, $offset);
          if (!is_object($field))
              return false;
          return empty($field->orgtable) ? $field->table : $field->orgtable;
      }
      
      function mysql_field_type($qlink, $offset) {
          $field = mysqli_fetch_field_direct($qlink, $offset);
          return is_object($field) ? $field->type : false;
      }
      
      function mysql_free_result($qlink) {
          try {
              mysqli_free_result($qlink);
          } catch (Exception $e) {
              return false;
          }
          return true;
      }
      
      'un kendi içinde güvensiz olmadığına dikkat etmek önemlidir, ancak kötü öğreticiler aracılığıyla güvensiz kodları teşvik etmekte ve uygun bir ifade hazırlamanın eksikliği API'yi hazırlamaktadır.
      2013-09-18 12: 31: 04Z
    2. lekesiz şifreler, ah korku! = oP Ayrıntılı açıklama için Aksi halde +1.
      2013-09-19 05: 42: 38Z

    MySQL uzantısı üçünden en eskisidir ve geliştiricilerin MySQL ile iletişim kurmak için kullandıkları orijinal yoldur. Bu uzantı şimdi diğer kullanımdan kaldırıldı . net /manual /en /book.mysqli.php "> iki , iyileştirmeler nedeniyle alternatifler PHP ve MySQL'in daha yeni sürümlerinde yapılmıştır.

    • MySQLi , MySQL veritabanıyla çalışmak için 'geliştirilmiş' uzantıdırs. MySQL sunucusunun daha yeni sürümlerinde bulunan özelliklerden faydalanır, geliştiriciye hem işlev odaklı hem de nesne odaklı bir arabirim gösterir ve birkaç başka güzel şey yapar.

    • PDO , daha önce genel kullanıma yayılmış işlevselliğin çoğunu birleştiren bir API sunar. ana veritabanı erişim uzantıları, yani MySQL, PostgreSQL, SQLite, MSSQL, vb. Arayüz, programcının veritabanı bağlantıları, sorgular ve sonuç kümeleriyle çalışması için üst düzey nesneler sunar ve düşük seviye sürücüler veritabanı ile iletişim ve kaynak yönetimi gerçekleştirir. sunucusu. Çok sayıda tartışma ve çalışma PDO'ya giriyor ve modern, profesyonel kodda veritabanlarıyla çalışmanın uygun yöntemi olarak kabul ediliyor.

    30
    2015-09-02 07: 20: 14Z

    Yukarıdaki cevapları çok uzun buluyorum, bu yüzden özetlemek için:

      

    MySQL uzantısı bir dizi vardır   yararları, üzerinde anahtar geliştirmeler   mysql uzantısı şöyle:

         
    • Nesneye yönelik arayüz
    •   
    • Hazırlanan Bildirimler için Destek
    •   
    • Birden Fazla İfade Desteği
    •   
    • İşlemler için Destek
    •   
    • Gelişmiş hata ayıklama yetenekleri
    •   
    • Gömülü sunucu desteği
    •   

    Kaynak: MySQLi'ye genel bakış


    Yukarıdaki cevaplarda açıklandığı gibi, mysql alternatifleri mysqli ve PDO'dur (PHP Data Objects).

    • API, sunucu tarafında Hazırlanan İfadeleri destekler: MYSQLi ve PDO tarafından desteklenir
    • API, müşteri tarafında Hazırlanan İfadeleri destekler: Yalnızca PDO tarafından desteklenir
    • API, Kayıtlı İşlemleri destekler: Hem MySQLi hem de PDO
    • API, Birden Çok İfade ve tüm MySQL 4.1+ işlevselliğini destekler - MySQLi ve çoğunlukla PDO tarafından desteklenir

    Hem MySQLi hem de PDO, PHP 5.0'da tanıtılırken, MySQL PHP 3.0'dan önce tanıtıldı. Unutulmaması gereken bir nokta, MySQL'in PHP5.x içerisine dahil edilmiş olmasına rağmen sonraki sürümlerde kullanımdan kaldırılmış olmasıdır.

        
    19
    2017-12-25 19: 09: 28Z
    1. Yanıtınız çok uzun, gerçek özet ise "mysql ext artık yok". Hepsi bu
      2016-09-07 15: 13: 05Z
    2. @ YourCommonSense Benim cevabım, neden mysqli'nin mysql'i değiştirdiğidir. Mesele şu ki, Mysqli'nin bugün varolduğunu söylemek için kullan o zaman .. Herkes bunu biliyor!
      2016-09-07 15: 16: 59Z
    3. Eh, kimse neden mysqli'nin mysql'nin yerini aldığını sormamış olması dışında, bu soruyu da cevaplamıyor. MySQL'in neden tanıtıldığını cevaplıyor. Fakat neden mysql ve mysqli'nin paralel olarak yaşamalarına izin verilmediğini açıklamıyor
      2016-09-07 15: 19: 57Z
    4. @ YourCommonSense Ayrıca OP'nin sorusu: "Sitemde çalışsalar bile neden başka bir şey kullanmalıyım?" ve işte bu yüzden değişikliklere ve gelişmelere dikkat çektim. Diğer tüm cevaplara uzun süre bakabilirsiniz, bu yüzden özetlemem gerektiğini düşündüm.
      2016-09-07 15: 23: 48Z

    Mysqli veya PDO kullanarak neredeyse tüm mysql_connect() fonksiyonlarını tanımlamak mümkündür. Onları eski PHP uygulamanızın üstüne eklemeniz yeterlidir ve PHP7'de çalışacaktır. Benim çözümüm burayı .

     mysql_query()     
    2
    2018-08-24 07: 02: 53Z
    1. Çözümünüz için bağlantı göstermek yerine, lütfen onları cevap olarak ekleyin.
      2017-06-09 07: 07: 48Z

    Bu mysqli_connect(), mysqli_query() türüne benzer işlevler önceki sürüm PHP i.e (PHP 4) işlevlerdir ve şu anda kullanımda değildir.

    Bunlar, PHP5'teki benzer şekilde

    <div class="container">
    
    <h2>Mapping Obsolete MySQL Functions to Current PHP Extensions</h2>
    <table>
    <tr><th>MySQL Extension</th><th>MySQL<b><i>i</i></b></th><th>PDO</th></tr>
    <tr><td><a href="http://www.php.net/manual/en/function.mysql-affected-rows.php">mysql_affected_rows</a></td>
        <td><a href="http://www.php.net/manual/en/mysqli.affected-rows.php">mysqli::$affected_rows</a></td>
        <td><a href="http://www.php.net/manual/en/pdostatement.rowcount.php">PDOStatement::rowCount</a></td>
        </tr>
    <tr><td><a href="http://www.php.net/manual/en/function.mysql-client-encoding.php">mysql_client_encoding</a></td>
        <td><a href="http://www.php.net/manual/en/mysqli.character-set-name.php">mysqli::character_set_name</a></td>
        <td> </td>
        </tr>
    <tr><td><a href="http://www.php.net/manual/en/function.mysql-close.php">mysql_close</a></td>
        <td><a href="http://www.php.net/manual/en/mysqli.close.php">mysqli::close</a></td>
        <td>Assign NULL to PDO Object</td>
        </tr>
    <tr><td><a href="http://www.php.net/manual/en/function.mysql-connect.php">mysql_connect</a></td>
        <td><a href="http://www.php.net/manual/en/mysqli.construct.php">mysqli::__construct</a></td>
        <td><a href="http://www.php.net/manual/en/pdo.construct.php">PDO::__construct</a></td>
        </tr>
    <tr><td><a href="http://www.php.net/manual/en/function.mysql-create-db.php">mysql_create_db</a></td>
        <td>Query: CREATE DATABASE</a></td>
        <td> </td>
        </tr>
    <tr><td><a href="http://www.php.net/manual/en/function.mysql-data-seek.php">mysql_data_seek</a></td>
        <td><a href="http://www.php.net/manual/en/mysqli-stmt.data-seek.php">mysqli_stmt::data_seek</a></td>
        <td>PDO::FETCH_ORI_ABS (?)</td>
        </tr>
    <tr><td><a href="http://www.php.net/manual/en/function.mysql-db-name.php">mysql_db_name</a></td>
        <td>Query: SELECT DATABASE()</td>
        <td> </td>
        </tr>
    <tr><td><a href="http://www.php.net/manual/en/function.mysql-db-query.php">mysql_db_query</a></td>
        <td> </td>
        <td> </td>
        </tr>
    <tr><td><a href="http://www.php.net/manual/en/function.mysql-drop-db.php">mysql_drop_db</a></td>
        <td>Query: DROP DATABASE</td>
        <td> </td>
        </tr>
    <tr><td><a href="http://www.php.net/manual/en/function.mysql-errno.php">mysql_errno</a></td>
        <td><a href="http://www.php.net/manual/en/mysqli.errno.php">mysqli::$errno</a></td>
        <td><a href="http://www.php.net/manual/en/pdo.errorcode.php">PDO::errorCode</a></td>
        </tr>
    <tr><td><a href="http://www.php.net/manual/en/function.mysql-error.php">mysql_error</a></td>
        <td><a href="http://www.php.net/manual/en/mysqli.error-list.php">mysqli::$error_list</a></td>
        <td><a href="http://www.php.net/manual/en/pdo.errorinfo.php">PDO::errorInfo</a></td>
        </tr>
    <tr><td><a href="http://www.php.net/manual/en/function.mysql-escape-string.php">mysql_escape_string</a></td>
        <td> </td>
        <td> </td>
        </tr>
    <tr><td><a href="http://www.php.net/manual/en/function.mysql-fetch-array.php">mysql_fetch_array</a></td>
        <td><a href="http://www.php.net/manual/en/mysqli-result.fetch-array.php">mysqli_result::fetch_array</a></td>
        <td><a href="http://www.php.net/manual/en/pdostatement.fetch.php">PDOStatement::fetch</a></td>
        </tr>
    <tr><td><a href="http://www.php.net/manual/en/function.mysql-fetch-assoc.php">mysql_fetch_assoc</a></td>
        <td><a href="http://www.php.net/manual/en/mysqli-result.fetch-assoc.php">mysqli_result::fetch_assoc</a></td>
        <td><a href="http://www.php.net/manual/en/pdostatement.fetch.php">PDOStatement::fetch</a></td>
        </tr>
    <tr><td><a href="http://www.php.net/manual/en/function.mysql-fetch-field.php">mysql_fetch_field</a></td>
        <td><a href="http://www.php.net/manual/en/mysqli-result.fetch-field.php">mysqli_result::fetch_field</a></td>
        <td><a href="http://www.php.net/manual/en/pdostatement.getcolumnmeta.php">PDOStatement::getColumnMeta</a></td>
        </tr>
    <tr><td><a href="http://www.php.net/manual/en/function.mysql-fetch-lengths.php">mysql_fetch_lengths</a></td>
        <td><a href="http://www.php.net/manual/en/mysqli-result.lengths.php">mysqli_result::$lengths</a></td>
        <td><a href="http://www.php.net/manual/en/pdostatement.getcolumnmeta.php">PDOStatement::getColumnMeta</a></td>
        </tr>
    <tr><td><a href="http://www.php.net/manual/en/function.mysql-fetch-object.php">mysql_fetch_object</a></td>
        <td><a href="http://www.php.net/manual/en/mysqli-result.fetch-object.php">mysqli_result::fetch_object</a></td>
        <td><a href="http://www.php.net/manual/en/pdostatement.fetch.php">PDOStatement::fetch</a></td>
        </tr>
    <tr><td><a href="http://www.php.net/manual/en/function.mysql-fetch-row.php">mysql_fetch_row</a></td>
        <td><a href="http://www.php.net/manual/en/mysqli-result.fetch-row.php">mysqli_result::fetch_row</a></td>
        <td><a href="http://www.php.net/manual/en/pdostatement.fetch.php">PDOStatement::fetch</a></td>
        </tr>
    <tr><td><a href="http://www.php.net/manual/en/function.mysql-field-flags.php">mysql_field_flags</a></td>
        <td><a href="http://www.php.net/manual/en/mysqli-result.fetch-fields.php">mysqli_result::fetch_fields</a></td>
        <td><a href="http://www.php.net/manual/en/pdostatement.getcolumnmeta.php">PDOStatement::getColumnMeta</a></td>
        </tr>
    <tr><td><a href="http://www.php.net/manual/en/function.mysql-field-len.php">mysql_field_len</a></td>
        <td><a href="http://www.php.net/manual/en/mysqli-result.fetch-field-direct.php">mysqli_result::fetch_field_direct</a></td>
        <td><a href="http://www.php.net/manual/en/pdostatement.getcolumnmeta.php">PDOStatement::getColumnMeta</a></td>
        </tr>
    <tr><td><a href="http://www.php.net/manual/en/function.mysql-field-name.php">mysql_field_name</a></td>
        <td><a href="http://www.php.net/manual/en/mysqli-result.fetch-field-direct.php">mysqli_result::fetch_field_direct</a></td>
        <td><a href="http://www.php.net/manual/en/pdostatement.getcolumnmeta.php">PDOStatement::getColumnMeta</a></td>
        </tr>
    <tr><td><a href="http://www.php.net/manual/en/function.mysql-field-seek.php">mysql_field_seek</a></td>
        <td><a href="http://www.php.net/manual/en/mysqli-result.field-seek.php">mysqli_result::field_seek</a></td>
        <td><a href="http://www.php.net/manual/en/pdostatement.fetch.php">PDOStatement::fetch</a></td>
        </tr>
    <tr><td><a href="http://www.php.net/manual/en/function.mysql-field-table.php">mysql_field_table</a></td>
        <td><a href="http://www.php.net/manual/en/mysqli-result.fetch-field-direct.php">mysqli_result::fetch_field_direct</a></td>
        <td><a href="http://www.php.net/manual/en/pdostatement.getcolumnmeta.php">PDOStatement::getColumnMeta</a></td>
        </tr>
    <tr><td><a href="http://www.php.net/manual/en/function.mysql-field-type.php">mysql_field_type</a></td>
        <td><a href="http://www.php.net/manual/en/mysqli-result.fetch-field-direct.php">mysqli_result::fetch_field_direct</a></td>
        <td><a href="http://www.php.net/manual/en/pdostatement.getcolumnmeta.php">PDOStatement::getColumnMeta</a></td>
        </tr>
    <tr><td><a href="http://www.php.net/manual/en/function.mysql-free-result.php">mysql_free_result</a></td>
        <td><a href="http://www.php.net/manual/en/mysqli-result.free.php">mysqli_result::free</a></td>
        <td><a href="http://www.php.net/manual/en/pdostatement.closecursor.php">PDOStatement::closeCursor</a></td>
        </tr>
    <tr><td><a href="http://www.php.net/manual/en/function.mysql-get-client-info.php">mysql_get_client_info</a></td>
        <td><a href="http://www.php.net/manual/en/mysqli.get-client-info.php">mysqli::get_client_info</a></td>
        <td><a href="http://www.php.net/manual/en/pdo.getattribute.php">PDO::getAttribute</a></td>
        </tr>
    <tr><td><a href="http://www.php.net/manual/en/function.mysql-get-host-info.php">mysql_get_host_info</a></td>
        <td><a href="http://www.php.net/manual/en/mysqli.get-host-info.php">mysqli::$host_info</a></td>
        <td><a href="http://www.php.net/manual/en/pdo.getattribute.php">PDO::getAttribute</a></td>
        </tr>
    <tr><td><a href="http://www.php.net/manual/en/function.mysql-get-proto-info.php">mysql_get_proto_info</a></td>
        <td><a href="http://www.php.net/manual/en/mysqli.get-proto-info.php">mysqli::$protocol_version</a></td>
        <td> </td>
        </tr>
    <tr><td><a href="http://www.php.net/manual/en/function.mysql-get-server-info.php">mysql_get_server_info</a></td>
        <td><a href="http://www.php.net/manual/en/mysqli.get-server-info.php">mysqli::$server_info</a></td>
        <td><a href="http://www.php.net/manual/en/pdo.getattribute.php">PDO::getAttribute</a></td>
        </tr>
    <tr><td><a href="http://www.php.net/manual/en/function.mysql-info.php">mysql_info</a></td>
        <td><a href="http://www.php.net/manual/en/mysqli.info.php">mysqli::$info</a></td>
        <td> </td>
        </tr>
    <tr><td><a href="http://www.php.net/manual/en/function.mysql-insert-id.php">mysql_insert_id</a></td>
        <td><a href="http://www.php.net/manual/en/mysqli.insert-id.php">mysqli::$insert_id</a></td>
        <td><a href="http://www.php.net/manual/en/pdo.lastinsertid.php">PDO::lastInsertId</a></td>
        </tr>
    <tr><td><a href="http://www.php.net/manual/en/function.mysql-list-dbs.php">mysql_list_dbs</a></td>
        <td>Query: SHOW DATABASES</td>
        <td> </td>
        </tr>
    <tr><td><a href="http://www.php.net/manual/en/function.mysql-list-fields.php">mysql_list_fields</a></td>
        <td>Query: SHOW COLUMNS</td>
        <td> </td>
        </tr>
    <tr><td><a href="http://www.php.net/manual/en/function.mysql-list-processes.php">mysql_list_processes</a></td>
        <td><a href="http://www.php.net/manual/en/mysqli.thread-id.php">mysqli::$thread_id</a></td>
        <td> </td>
        </tr>
    <tr><td><a href="http://www.php.net/manual/en/function.mysql-list-tables.php">mysql_list_tables</a></td>
        <td>Query: SHOW TABLES</td>
        <td> </td>
        </tr>
    <tr><td><a href="http://www.php.net/manual/en/function.mysql-num-fields.php">mysql_num_fields</a></td>
        <td><a href="http://www.php.net/manual/en/mysqli.field-count.php">mysqli::$field_count</a></td>
        <td><a href="http://www.php.net/manual/en/pdostatement.columncount.php">PDOStatement::columnCount</a></td>
        </tr>
    <tr><td><a href="http://www.php.net/manual/en/function.mysql-num-rows.php">mysql_num_rows</a></td>
        <td><a href="http://www.php.net/manual/en/mysqli-stmt.num-rows.php">mysqli_stmt::$num_rows</a></td>
        <td><a href="http://www.php.net/manual/en/pdostatement.rowcount.php">PDOStatement::rowCount</a></td>
        </tr>
    <tr><td><a href="http://www.php.net/manual/en/function.mysql-pconnect.php">mysql_pconnect</a></td>
        <td><a href="http://www.php.net/manual/en/mysqli.construct.php">mysqli::__construct</a></td>
        <td><a href="http://www.php.net/manual/en/pdo.construct.php">PDO::__construct</a></td>
        </tr>
    <tr><td><a href="http://www.php.net/manual/en/function.mysql-ping.php">mysql_ping</a></td>
        <td><a href="http://www.php.net/manual/en/mysqli.ping.php">mysqli::ping</a></td>
        <td> </td>
        </tr>
    <tr><td><a href="http://www.php.net/manual/en/function.mysql-query.php">mysql_query</a></td>
        <td><a href="http://www.php.net/manual/en/mysqli.query.php">mysqli::query</a></td>
        <td><a href="http://www.php.net/manual/en/pdo.query.php">PDO::query</a></td>
        </tr>
    <tr><td><a href="http://www.php.net/manual/en/function.mysql-real-escape-string.php">mysql_real_escape_string</a></td>
        <td><a href="http://www.php.net/manual/en/mysqli.real-escape-string.php">mysqli::real_escape_string</a></td>
        <td><a href="http://www.php.net/manual/en/pdo.quote.php">PDO::quote</a></td>
        </tr>
    <tr><td><a href="http://www.php.net/manual/en/function.mysql-result.php">mysql_result</a></td>
        <td>Combination</td>
        <td><a href="http://www.php.net/manual/en/pdostatement.fetchcolumn.php">PDOStatement::fetchColumn</a></td>
        </tr>
    <tr><td><a href="http://www.php.net/manual/en/function.mysql-select-db.php">mysql_select_db</a></td>
        <td><a href="http://www.php.net/manual/en/mysqli.send-query.php">mysqli::send_query</a></td>
        <td><a href="http://www.php.net/manual/en/pdo.construct.php">PDO::__construct</a></td></td>
        </tr>
    <tr><td><a href="http://www.php.net/manual/en/function.mysql-set-charset.php">mysql_set_charset</a></td>
        <td><a href="http://www.php.net/manual/en/mysqli.character-set-name.php">mysqli::character_set_name</a></td>
        <td><a href="http://www.php.net/manual/en/pdo.construct.php">PDO::__construct</a></td></td>
        </tr>
    <tr><td><a href="http://www.php.net/manual/en/function.mysql-stat.php">mysql_stat</a></td>
        <td><a href="http://www.php.net/manual/en/mysqli.stat.php">mysqli::stat</a></td>
        <td><a href="http://www.php.net/manual/en/pdo.getattribute.php">PDO::getAttribute</a></td>
        </tr>
    <tr><td><a href="http://www.php.net/manual/en/function.mysql-tablename.php">mysql_tablename</a></td>
        <td>Query: SHOW TABLES</td>
        <td> </td>
        </tr>
    <tr><td><a href="http://www.php.net/manual/en/function.mysql-thread-id.php">mysql_thread_id</a></td>
        <td><a href="http://www.php.net/manual/en/mysqli.thread-id.php">mysqli::$thread_id</a></td>
        <td> </td>
        </tr>
    <tr><td><a href="http://www.php.net/manual/en/function.mysql-unbuffered-query.php">mysql_unbuffered_query</a></td>
        <td>See <a href="http://www.php.net/manual/en/mysqlinfo.concepts.buffering.php">Buffering Concepts</a></td>
        <td> </td>
        </tr>
    </table>
    
    </div><!-- container -->
    
    , ile değiştirilir.

    Hatanın arkasındaki sebep budur.

        
    0
    2018-03-20 19: 14: 58Z
    1. PHP 5, 2 yıldan beri son değil.
      2018-03-21 07: 30: 25Z

    Bu bugün eski bir sorudur (Ocak 2019), ancak bu yine de faydalı olabilir. Yaklaşık 7 yıl önce MySQL /MySQLi /PDO işlevselliğinin tablosal bir haritasını çıkardım. Yararlı bir referans olabilir. burada çevrimiçi ve aşağıda çoğaltılmıştır. HTML'yi kopyalayıp yapıştırmaktan çekinmeyin.

    Pratik bir mesele olarak, prosedürel MySQL işlevlerini OOP'a dönüştürmenin MySQLi'nin en düşük direnç yolu olduğunu buldum. İki DB bağlantısının aynı anda açık olması son derece iyidir ve bu bize dönüşümlerde çalıştıkça esneklik sağladı - komut dosyalarını her seferinde bir sorgu olarak bir parça parça bazında dönüştürebilirdik. Bugün bunu tavsiye etmeme rağmen, o zamanlar uygun değildi.

          
    - 2
    2019-01-18 21: 37: 47Z

    mysql_ * işlevleri, daha iyi işlevler ve kod yapıları geliştirildiği gerçeği göz önüne alındığında ( PHP 5.5 itibariyle) kullanımdan kaldırıldı. İşlevin kullanımdan kaldırılmış olması, performans ve güvenlik açısından iyileştirilmesi için daha fazla çaba gösterilmeyeceği anlamına gelir; bu, geleceğin daha az kanıtı olduğu anlamına gelir .

    Daha fazla nedene ihtiyacınız varsa:

    • mysql_ * işlevleri hazırlanmış ifadeleri desteklemez.
    • mysql_ * işlevleri, parametrelerin bağlanmasını desteklemez.
    • mysql_ * işlevlerinin Nesneye Yönelik Programlama için işlevselliği yoktur.
    • liste devam ediyor ...
    - 7
    2018-11-16 01: 51: 23Z
    1. Bu cevap eski. Ayrıca, zaten mevcut olan cevaplara faydalı bir şey eklemez.
      2016-05-24 06: 22: 33Z
kaynak yerleştirildi İşte