PHP MySQL से जुड़ने के लिए तीन अलग-अलग API प्रदान करता है। ये हैं mysql
(PHP 7 के रूप में हटा दिया गया) mysqli
, और PDO
एक्सटेंशन।
mysql_*
कार्यों में बहुत लोकप्रिय हुआ करते थे, लेकिन उनके उपयोग अब और प्रोत्साहित नहीं किया जाता है। प्रलेखन टीम डेटाबेस सुरक्षा स्थिति पर चर्चा कर रही है, और उपयोगकर्ताओं को आमतौर पर उपयोग किए जाने वाले ext / mysql एक्सटेंशन से दूर जाने के लिए शिक्षित कर रही है, यह इसका हिस्सा है (चेक php.internals: deprecating ext / mysql )।
और बाद में पीएचपी डेवलपर टीम उत्पन्न करने के लिए निर्णय लिया गया है E_DEPRECATED
कि क्या के माध्यम से, जब उपयोगकर्ता MySQL से कनेक्ट त्रुटियों mysql_connect()
, mysql_pconnect()
या में बनाया अंतर्निहित कनेक्शन कार्यक्षमता ext/mysql
।
ext/mysql
गया था आधिकारिक तौर पर पीएचपी 5.5 के रूप में पदावनत किया गया है पीएचपी 7 के रूप में निकाल दिया ।
रेड बॉक्स देखें?
जब आप किसी mysql_*
फंक्शन मैनुअल पेज पर जाते हैं, तो आपको एक लाल बॉक्स दिखाई देता है, यह समझाते हुए कि इसे अब इस्तेमाल नहीं किया जाना चाहिए।
क्यों
इससे दूर जाना ext/mysql
न केवल सुरक्षा के बारे में है, बल्कि MySQL डेटाबेस की सभी विशेषताओं तक पहुंच के बारे में भी है।
ext/mysql
MySQL 3.23 के लिए बनाया गया था और तब से केवल बहुत कुछ अतिरिक्त मिला है, जबकि ज्यादातर इस पुराने संस्करण के साथ संगतता रखते हुए जो कोड को बनाए रखने के लिए थोड़ा कठिन बनाता है। अनुपलब्ध सुविधाएँ जो ext/mysql
इसमें शामिल नहीं हैं: ( PHP मैनुअल से )।
mysql_*
फ़ंक्शन का उपयोग न करने का कारण :
- सक्रिय विकास के तहत नहीं
- PHP 7 के रूप में हटाया गया
- एक OO इंटरफ़ेस को कम करता है
- गैर-अवरुद्ध, अतुल्यकालिक प्रश्नों का समर्थन नहीं करता है
- तैयार कथनों या पैरामीटरयुक्त प्रश्नों का समर्थन नहीं करता है
- संग्रहीत प्रक्रियाओं का समर्थन नहीं करता है
- कई बयानों का समर्थन नहीं करता है
- लेन-देन का समर्थन नहीं करता है
- MySQL 5.1 में सभी कार्यक्षमता का समर्थन नहीं करता है
क्वेंटिन के उत्तर से उद्धृत बिंदु से ऊपर
तैयार किए गए कथनों के लिए समर्थन का अभाव विशेष रूप से महत्वपूर्ण है क्योंकि वे अलग-अलग फ़ंक्शन कॉल के साथ मैन्युअल रूप से भागने की तुलना में बाहरी डेटा से बचने और उद्धृत करने की एक स्पष्ट, कम त्रुटि प्रवण विधि प्रदान करते हैं।
SQL एक्सटेंशन की तुलना देखें ।
दबाना चेतावनियों को दबाने
कोड में बदला जा रहा है, वहीं MySQLi
/ PDO
, E_DEPRECATED
स्थापना करके त्रुटियों को दबा दिया जा सकता है error_reporting
में php.ini बाहर करने के लिएE_DEPRECATED:
error_reporting = E_ALL ^ E_DEPRECATED
ध्यान दें कि यह अन्य अपक्षय चेतावनी को भी छिपाएगा , जो कि, MySQL के अलावा अन्य चीजों के लिए हो सकता है। ( PHP मेनुअल से )
लेख PDO बनाम MySQLi: आपको किसका उपयोग करना चाहिए? द्वारा डेजन Marjanovic आप का चयन करने के लिए मदद मिलेगी।
और एक बेहतर तरीका है PDO
, और मैं अब एक सरल PDO
ट्यूटोरियल लिख रहा हूं ।
एक सरल और छोटा पीडीओ ट्यूटोरियल
Q. मेरे दिमाग में पहला सवाल था: `PDO` क्या है?
A. " पीडीओ - PHP डेटा ऑब्जेक्ट्स - एक डेटाबेस एक्सेस लेयर है जो कई डेटाबेस तक पहुँच की एक समान विधि प्रदान करता है।"
MySQL से कनेक्ट करना
mysql_*
फ़ंक्शन के साथ या हम इसे पुराने तरीके से कह सकते हैं (PHP 5.5 और इसके बाद के संस्करण में पदावनत)
$link = mysql_connect('localhost', 'user', 'pass');
mysql_select_db('testdb', $link);
mysql_set_charset('UTF-8', $link);
के साथ PDO
: आपको बस एक नई PDO
वस्तु बनाने की जरूरत है । कंस्ट्रक्टर डेटाबेस स्रोत PDO
के कंस्ट्रक्टर को निर्दिष्ट करने के लिए मापदंडों को स्वीकार करता है, ज्यादातर चार पैरामीटर लेता है जो DSN
(डेटा स्रोत का नाम) हैं और वैकल्पिक रूप से username
,password
।
यहाँ मुझे लगता है कि आप सभी को छोड़कर सभी परिचित हैं DSN
; इस में नया है PDO
। A DSN
मूल रूप से विकल्पों का एक तार है जो बताता है कि PDO
किस चालक का उपयोग करना है, और विवरण का कनेक्शन। आगे के संदर्भ के लिए, PDO MySQL DSN की जाँच करें ।
$db = new PDO('mysql:host=localhost;dbname=testdb;charset=utf8', 'username', 'password');
नोट: आप भी उपयोग कर सकते हैं charset=UTF-8
, लेकिन कभी-कभी यह एक त्रुटि का कारण बनता है, इसलिए इसका उपयोग करना बेहतर हैutf8
।
यदि कोई कनेक्शन त्रुटि है, तो यह एक PDOException
ऑब्जेक्ट को फेंक देगा जिसे Exception
आगे संभालने के लिए पकड़ा जा सकता है ।
अच्छा पढ़ा : कनेक्शन और कनेक्शन प्रबंधन and
आप चौथे पैरामीटर में सरणी के रूप में कई ड्राइवर विकल्पों में भी पास कर सकते हैं। मैं उस पैरामीटर को पारित करने की सलाह देता हूं जो PDO
अपवाद मोड में डालता है। क्योंकि कुछ PDO
ड्राइवर देशी तैयार बयानों का समर्थन नहीं करते हैं, इसलिए PDO
तैयारी का अनुकरण करता है। यह आपको मैन्युअल रूप से इस अनुकरण को सक्षम करने की सुविधा भी देता है। देशी सर्वर-साइड तैयार बयानों का उपयोग करने के लिए, आपको इसे स्पष्ट रूप से सेट करना चाहिए false
।
दूसरा है तैयार एमुलेशन को बंद करना जो MySQL
कि डिफ़ॉल्ट रूप से ड्राइवर में सक्षम है , लेकिन PDO
सुरक्षित रूप से उपयोग करने के लिए एमुलेशन तैयार करना बंद कर देना चाहिए ।
मैं बाद में बताऊंगा कि क्यों एमुलेशन तैयार करना बंद कर देना चाहिए। कारण जानने के लिए कृपया इस पोस्ट को देखें ।
यदि आप किसी पुराने संस्करण का उपयोग कर रहे हैं तो यह केवल प्रयोग करने योग्य है MySQL
जिसकी मैंने सिफारिश नहीं की है।
नीचे एक उदाहरण है कि आप इसे कैसे कर सकते हैं:
$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));
क्या हम पीडीओ निर्माण के बाद विशेषताएँ निर्धारित कर सकते हैं?
हां , हम setAttribute
विधि के साथ पीडीओ निर्माण के बाद कुछ विशेषताओं को भी सेट कर सकते हैं :
$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);
गलती संभालना
त्रुटि से निपटने में बहुत आसान PDO
है mysql_*
।
उपयोग करते समय एक सामान्य अभ्यास mysql_*
है:
//Connected to MySQL
$result = mysql_query("SELECT * FROM table", $link) or die(mysql_error($link));
OR die()
त्रुटि को संभालने का एक अच्छा तरीका नहीं है क्योंकि हम उस चीज को संभाल नहीं सकते हैं die
। यह स्क्रिप्ट को अचानक समाप्त कर देगा और फिर उस त्रुटि को स्क्रीन पर गूँज देगा जिसे आप आमतौर पर अपने अंतिम उपयोगकर्ताओं को नहीं दिखाना चाहते हैं, और खूनी हैकर्स को आपके स्कीमा की खोज करने देते हैं। वैकल्पिक रूप से, mysql_*
फ़ंक्शन के रिटर्न मान अक्सर त्रुटियों को संभालने के लिए mysql_error () के साथ संयोजन में उपयोग किए जा सकते हैं।
PDO
एक बेहतर समाधान प्रदान करता है: अपवाद। क्या हम कुछ के साथ क्या PDO
एक में लपेटा जाना चाहिए try
- catch
ब्लॉक। हम PDO
त्रुटि मोड विशेषता सेट करके तीन त्रुटि मोड में से एक में मजबूर कर सकते हैं । तीन त्रुटि हैंडलिंग मोड नीचे हैं।
PDO::ERRMODE_SILENT
। यह केवल त्रुटि कोड सेट कर रहा है और mysql_*
जहां आप प्रत्येक परिणाम की जाँच करते हैं और फिर $db->errorInfo();
त्रुटि विवरण प्राप्त करने के लिए देखना चाहिए के रूप में बहुत ज्यादा कार्य करता है ।
PDO::ERRMODE_WARNING
उठाएँ E_WARNING
। (रन-टाइम चेतावनियाँ (गैर-घातक त्रुटियाँ)। स्क्रिप्ट का निष्पादन रुका नहीं है।)
PDO::ERRMODE_EXCEPTION
: अपवादों को फेंको। यह पीडीओ द्वारा उठाए गए एक त्रुटि का प्रतिनिधित्व करता है। आपको PDOException
अपने स्वयं के कोड से नहीं फेंकना चाहिए । PHP में अपवादों के बारे में अधिक जानकारी के लिए अपवाद देखें । यह बहुत पसंद है or die(mysql_error());
, जब यह पकड़ा नहीं जाता है। लेकिन इसके विपरीत or die()
, PDOException
अगर आप ऐसा करने के लिए चुनते हैं , तो इसे पकड़ा जा सकता है और इनायत से नियंत्रित किया जा सकता है।
अच्छा पढ़ें :
पसंद:
$stmt->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT );
$stmt->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING );
$stmt->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
और तुम में लपेट कर सकते हैं try
- 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());
}
आपको अभी try
- catch
अभी नहीं संभालना है । आप इसे किसी भी समय उचित रूप से पकड़ सकते हैं, लेकिन मैं दृढ़ता से आपको उपयोग करने की सलाह देता हूं try
- catch
। PDO
सामान को कॉल करने वाले फ़ंक्शन के बाहर इसे पकड़ने के लिए भी अधिक समझदारी हो सकती है :
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.
}
इसके अलावा, आप इसे संभाल or die()
सकते हैं या हम जैसे कह सकते हैं mysql_*
, लेकिन यह वास्तव में विविध होगा। आप उत्पादन में खतरनाक त्रुटि संदेशों को बदल सकते हैं display_errors off
और अपनी त्रुटि लॉग को पढ़ सकते हैं।
अब, ऊपर सब बातों को पढ़ने के बाद, तो आप शायद सोच रहे हैं: क्या बिल्ली है कि जब मैं सिर्फ सरल झुकाव शुरू करना चाहते हैं SELECT
, INSERT
, UPDATE
, या DELETE
बयान? चिंता मत करो, यहाँ हम चलते हैं:
डेटा का चयन करना
तो आप क्या कर रहे हैं mysql_*
:
<?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'];
}
अब PDO
आप इस तरह कर सकते हैं:
<?php
$stmt = $db->query('SELECT * FROM table');
while($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
echo $row['field1'];
}
या
<?php
$stmt = $db->query('SELECT * FROM table');
$results = $stmt->fetchAll(PDO::FETCH_ASSOC);
//Use $results
नोट : यदि आप नीचे दी गई विधि ( query()
) का उपयोग कर रहे हैं , तो यह विधि एक PDOStatement
वस्तु लौटाती है । इसलिए यदि आप परिणाम प्राप्त करना चाहते हैं, तो इसे ऊपर की तरह उपयोग करें।
<?php
foreach($db->query('SELECT * FROM table') as $row) {
echo $row['field1'];
}
पीडीओ डेटा में, यह ->fetch()
आपके स्टेटमेंट हैंडल की एक विधि के माध्यम से प्राप्त किया जाता है । लाने के लिए कॉल करने से पहले, सबसे अच्छा तरीका पीडीओ को बता रहा है कि आप डेटा कैसे प्राप्त करना चाहते हैं। नीचे के भाग में मैं इसे समझा रहा हूँ।
फ़ोड़ने का काम
नोट के उपयोग PDO::FETCH_ASSOC
में fetch()
और fetchAll()
इसके बाद के संस्करण कोड। यह PDO
पंक्तियों को कुंजी के रूप में फ़ील्ड नामों के साथ एक सहयोगी सरणी के रूप में वापस करने के लिए कहता है। कई अन्य फ़िच मोड भी हैं जिन्हें मैं एक-एक करके समझाता हूँ।
सबसे पहले, मैं समझाता हूं कि कैसे प्राप्त करना है:
$stmt->fetch(PDO::FETCH_ASSOC)
उपरोक्त में, मैं उपयोग कर रहा हूं fetch()
। आप भी उपयोग कर सकते हैं:
अब मैं लाने के लिए मोड:
PDO::FETCH_ASSOC
: आपके परिणाम सेट में दिए गए कॉलम नाम से अनुक्रमित एक सरणी देता है
PDO::FETCH_BOTH
(डिफ़ॉल्ट): आपके परिणाम सेट में दिए गए दोनों कॉलम नाम और 0-अनुक्रमित कॉलम नंबर द्वारा अनुक्रमित एक सरणी देता है
और भी विकल्प हैं! PDOStatement
Fetch प्रलेखन में उन सभी के बारे में पढ़ें । ।
पंक्ति गणना प्राप्त करना :
mysql_num_rows
लौटी हुई पंक्तियों की संख्या प्राप्त करने के लिए उपयोग करने के बजाय , आप एक PDOStatement
ऐसा कर सकते हैं rowCount()
, जैसे:
<?php
$stmt = $db->query('SELECT * FROM table');
$row_count = $stmt->rowCount();
echo $row_count.' rows selected';
अंतिम सम्मिलित आईडी प्राप्त करना
<?php
$result = $db->exec("INSERT INTO table(firstname, lastname) VAULES('John', 'Doe')");
$insertId = $db->lastInsertId();
सम्मिलित करें और अद्यतन या हटाएँ बयान
हम जो mysql_*
कार्य कर रहे हैं वह है:
<?php
$results = mysql_query("UPDATE table SET field='value'") or die(mysql_error());
echo mysql_affected_rows($result);
और pdo में, यह वही काम कर सकता है:
<?php
$affected_rows = $db->exec("UPDATE table SET field='value'");
echo $affected_rows;
उपरोक्त क्वेरी में PDO::exec
SQL कथन निष्पादित करें और प्रभावित पंक्तियों की संख्या लौटाता है।
सम्मिलित करें और हटाएं बाद में कवर किया जाएगा।
उपरोक्त विधि केवल तभी उपयोगी है जब आप क्वेरी में परिवर्तनशील का उपयोग नहीं कर रहे हैं। लेकिन जब आपको किसी प्रश्न में एक चर का उपयोग करने की आवश्यकता होती है, तो कभी भी उपरोक्त की तरह प्रयास न करें और तैयार कथन या पैरामीटर किए गए कथन के लिए वहाँ है।
तैयार विवरण
प्रश्न: एक तैयार कथन क्या है और मुझे उनकी आवश्यकता क्यों है?
A. एक तैयार बयान एक पूर्व संकलित SQL स्टेटमेंट है जिसे केवल सर्वर पर डेटा भेजकर कई बार निष्पादित किया जा सकता है।
एक तैयार कथन का उपयोग करने का विशिष्ट कार्य इस प्रकार है ( विकिपीडिया तीन 3 बिंदु से उद्धृत ):
तैयार करें : स्टेटमेंट टेम्प्लेट एप्लिकेशन द्वारा बनाया गया है और डेटाबेस प्रबंधन प्रणाली (DBMS) को भेजा गया है। कुछ मानों को अनिर्दिष्ट छोड़ दिया जाता है, जिन्हें पैरामीटर, प्लेसहोल्डर या बाइंड चर ( ?
नीचे लेबल ) कहा जाता है:
INSERT INTO PRODUCT (name, price) VALUES (?, ?)
DBMS पर्सेंट करता है, कंपाइल करता है, और स्टेटमेंट टेम्प्लेट पर क्वेरी ऑप्टिमाइज़ेशन करता है, और रिजल्ट को बिना एक्सेप्ट किए स्टोर करता है।
- निष्पादन : बाद के समय में, मापदंडों के लिए एप्लिकेशन आपूर्ति (या बाइंड) मूल्यों, और DBMS कथन को निष्पादित करता है (संभवतः परिणाम लौटाता है)। एप्लिकेशन विवरण को कई बार निष्पादित कर सकता है क्योंकि यह विभिन्न मूल्यों के साथ चाहता है। इस उदाहरण में, यह पहले पैरामीटर के
1.00
लिए और दूसरे पैरामीटर के लिए 'ब्रेड' की आपूर्ति कर सकता है ।
आप अपने SQL में प्लेसहोल्डर्स को शामिल करके एक तैयार स्टेटमेंट का उपयोग कर सकते हैं। प्लेसहोल्डर के बिना मूल रूप से तीन व्यक्ति हैं (इसके ऊपर एक के साथ चर की कोशिश न करें), एक अनाम प्लेसहोल्डर के साथ, और एक नामित प्लेसहोल्डर्स के साथ।
प्र। अब, प्लेसहोल्डर्स का नाम क्या है और मैं उनका उपयोग कैसे करूं?
ए नामांकित प्लेसहोल्डर। प्रश्नवाचक चिन्ह के स्थान पर एक बृहदान्त्र से पहले वर्णनात्मक नामों का उपयोग करें। हम नाम स्थान धारक की स्थिति / मूल्य के बारे में परवाह नहीं करते हैं:
$stmt->bindParam(':bla', $bla);
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);
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);
प्र। अब, अनाम प्लेसहोल्डर क्या हैं और मैं उनका उपयोग कैसे करूं?
ए चलो एक उदाहरण है:
<?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();
तथा
$stmt = $db->prepare("INSERT INTO folks (name, add) values (?, ?)");
$stmt->execute(array('john', '29 bla district'));
उपरोक्त में, आप ?
एक नाम स्थान धारक की तरह नाम के बजाय उन देख सकते हैं । अब पहले उदाहरण में, हम विभिन्न प्लेसहोल्डर्स ( $stmt->bindValue(1, $name, PDO::PARAM_STR);
) को वेरिएबल प्रदान करते हैं । फिर, हम उन प्लेसहोल्डर्स को मान असाइन करते हैं और स्टेटमेंट निष्पादित करते हैं। दूसरे उदाहरण में, पहला ऐरे तत्व पहले ?
और दूसरे से दूसरे तक जाता है ?
।
ध्यान दें : अनाम प्लेसहोल्डर में हमें उस सरणी में तत्वों के उचित क्रम का ध्यान रखना चाहिए जिसे हम PDOStatement::execute()
विधि में पास कर रहे हैं ।
SELECT
, INSERT
, UPDATE
, DELETE
तैयार प्रश्नों
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();
ध्यान दें:
हालाँकि PDO
और / या MySQLi
पूरी तरह से सुरक्षित नहीं हैं। उत्तर की जाँच करें क्या SQL इंजेक्शन को रोकने के लिए PDO पर्याप्त विवरण तैयार करते हैं? ircmaxell द्वारा । इसके अलावा, मैं उनके उत्तर से कुछ अंश उद्धृत कर रहा हूं:
$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 /*"));