আমি পিএইচপি-তে কেন mysql_ * ফাংশন ব্যবহার করব না?


2501

কারও কারও জন্য mysql_*ফাংশন ব্যবহার করা উচিত নয় তার প্রযুক্তিগত কারণগুলি কী ? (যেমন mysql_query(), mysql_connect()বা mysql_real_escape_string())?

তারা আমার সাইটে কাজ করলেও কেন আমি অন্য কিছু ব্যবহার করব?

যদি তারা আমার সাইটে কাজ না করে তবে আমি কেন ত্রুটি পেতে পারি

সতর্কতা: mysql_connect (): এই জাতীয় কোনও ফাইল বা ডিরেক্টরি নেই


মত হতে ত্রুটি: মারাত্মক ত্রুটি: আনকড ত্রুটি: অপরিজ্ঞাত ফাংশনটিতে কল করুন mysql_connect () ...
বিমল পাউদেল

উত্তর:


2087

মাইএসকিউএল এক্সটেনশন:

  • সক্রিয় বিকাশের অধীনে নেই
  • হয় আনুষ্ঠানিকভাবে অবচিত (জুন 2013 প্রকাশিত) পিএইচপি 5.5 হিসাবে।
  • পিএইচপি 7.0 হিসাবে সম্পূর্ণভাবে সরানো হয়েছে (ডিসেম্বর 2015 প্রকাশিত)
    • এর অর্থ এই যে 31 ডিসেম্বর 2018 পর্যন্ত এটি পিএইচপি-র কোনও সমর্থিত সংস্করণে বিদ্যমান নেই। আপনি যদি পিএইচপি এর একটি সংস্করণ ব্যবহার করে যা এটি সমর্থন করে, আপনি এমন একটি সংস্করণ ব্যবহার করছেন যা সুরক্ষার সমস্যাগুলি স্থির করে না।
  • একটি ওও ইন্টারফেসের অভাব রয়েছে
  • সমর্থন করে না:
    • অ-ব্লকিং, অ্যাসিনক্রোনাস কোয়েরি
    • বিবৃতি বা প্যারামিটারাইজড কোয়েরি প্রস্তুত
    • সঞ্চিত পদ্ধতি
    • একাধিক বিবৃতি
    • লেনদেন
    • "নতুন" পাসওয়ার্ড প্রমাণীকরণ পদ্ধতি (মাইএসকিউএল 5.6 এ ডিফল্টরূপে; 5.7 এ প্রয়োজনীয়)
    • মাইএসকিউএল 5.1 বা তার পরে এর নতুন কার্যকারিতাটির কোনও

যেহেতু এটি অবহেলা করা হয়েছে তাই এটি ব্যবহার করা আপনার কোডটিকে ভবিষ্যতের প্রমাণকে কম করে তোলে।

প্রস্তুত বিবৃতিগুলির সমর্থনের অভাব বিশেষত গুরুত্বপূর্ণ কারণ এগুলি পৃথক ফাংশন কলের সাহায্যে ম্যানুয়ালি এড়িয়ে যাওয়ার চেয়ে বাহ্যিক ডেটা বের করার এবং উদ্ধৃতি দেওয়ার একটি পরিষ্কার, কম ত্রুটি-প্রবণ পদ্ধতি সরবরাহ করে।

এসকিউএল এক্সটেনশনের তুলনা দেখুন ।


286
এগুলি এড়ানোর জন্য একা অবহেলা করা যথেষ্ট কারণ। তারা একদিন সেখানে থাকবে না এবং আপনি যদি তাদের উপর নির্ভর করেন তবে আপনি খুশি হবেন না। বাকিগুলি কেবলমাত্র সেই জিনিসগুলির তালিকা যা পুরাতন এক্সটেনশনগুলি ব্যবহার করে মানুষ শেখা থেকে বিরত রাখে।
টিম পোস্ট

111
অবমূল্যায়ন যাদুবিদ্যার বুলেট নয় যা সবাই মনে করে। পিএইচপি নিজেই একদিন সেখানে থাকবে না, তবুও আমরা আমাদের আজকের সরঞ্জামের উপর নির্ভর করি। আমাদের যখন সরঞ্জাম পরিবর্তন করতে হবে, আমরা করব।
লাইটনেস রেস

133
@ লাইটনেসেসিনঅরবিট - অবমূল্যায়ন কোনও যাদু বুলেট নয়, এটি একটি পতাকা যা বলে যে "আমরা এই স্তন্যপানগুলিকে চিনতে পারি তাই আমরা এর বেশি দিন সমর্থন করতে যাব না"। কোডের ভবিষ্যতের প্রুফিং থাকা অবনতিযুক্ত বৈশিষ্ট্যগুলি থেকে দূরে সরিয়ে নেওয়া ভাল কারণ, এটি কেবলমাত্র একটি (বা এমনকি মূলটি) নয়। সরঞ্জামগুলি পরিবর্তন করুন কারণ সেখানে আরও ভাল সরঞ্জাম রয়েছে, আপনি বাধ্য হয়েছেন বলে নয়। (এবং আপনাকে বাধ্য করার আগে সরঞ্জাম পরিবর্তন করার অর্থ হল যে আপনার কোডটি কাজ বন্ধ করে দিয়েছে এবং গতকাল ঠিক করা দরকার যার কারণে ... নতুন সরঞ্জামগুলি শেখার জন্য সবচেয়ে খারাপ সময়টি) কারণ আপনি নতুনগুলি শিখছেন না।
কোয়ান্টিন

18
প্রস্তুত বিবৃতিগুলির অভাব সম্পর্কে আমি একটি জিনিস যা উল্লেখ করি নি তা হ'ল পারফরম্যান্স ইস্যু। প্রতিবার আপনি যখন কোনও বিবৃতি জারি করেন তখন কোনও কিছু এটিকে সংকলন করতে হয় যাতে মাইএসকিউএল ডিমন এটি বুঝতে পারে। এই এপিআই দিয়ে, যদি আপনি একই কোয়েরিটির 200,000 একটি লুপে জারি করেন, তবে মাইএসকিউএল এটি বোঝার জন্য কোয়েরিটি 200,000 বার সংকলন করতে হবে। প্রস্তুত বিবৃতি দিয়ে এটি একবার সংকলিত হয় এবং তারপরে মানগুলি সংকলিত এসকিউএল-এ প্যারামিটারাইজড হয়।
গোল্ডেনটোয়া 11

20
@ সাইমসিবিয়ান, এটি অবশ্যই প্রস্তুত বিবৃতি সমর্থন করে না । প্রকৃতপক্ষে এটি হ্রাসের মূল কারণ। (ব্যবহারে সহজ) প্রস্তুত বিবৃতি ছাড়াই মাইএসকিএল এক্সটেনশন প্রায়শই এসকিউএল ইঞ্জেকশন আক্রমণের শিকার হয়।
rustyx

1287

পিএইচপি মাইএসকিউএলে কানেক্ট করার জন্য তিনটি আলাদা এপিআই সরবরাহ করে। এগুলি mysqlহ'ল (পিএইচপি 7 হিসাবে সরানো) mysqli, এবং PDOএক্সটেনশনগুলি।

mysql_*ফাংশন খুব জনপ্রিয় ব্যবহার করা হয়, কিন্তু তাদের ব্যবহার আর উৎসাহিত করা হয় না। ডকুমেন্টেশন দলটি ডাটাবেস সুরক্ষার পরিস্থিতি নিয়ে আলোচনা করছে এবং ব্যবহারকারীদের সাধারণভাবে ব্যবহৃত এক্সট্রা / মাইএসকিএল এক্সটেনশান থেকে দূরে সরে যেতে শিক্ষিত করছে এটির একটি অংশ ( php.internals দেখুন: ext / mysql হ্রাস করা )।

এবং পরবর্তী পিএইচপি বিকাশকারী দল E_DEPRECATEDব্যবহারকারীরা মাইএসকিউএলে সংযুক্ত হওয়ার পরে mysql_connect(), mysql_pconnect()বা অন্তর্নিহিত সংযোগ কার্যকারিতা কার্যকর করার সময় ত্রুটিগুলি তৈরি করার সিদ্ধান্ত নিয়েছে ext/mysql

ext/mysqlপিএইচপি 5.5 হিসাবে সরকারীভাবে অবচিত হয়েছিল এবং পিএইচপি 7 হিসাবে সরানো হয়েছে ।

রেড বক্সটি দেখুন?

আপনি যখন কোনও mysql_*ফাংশন ম্যানুয়াল পৃষ্ঠায় যান, আপনি একটি লাল বাক্স দেখতে পাবেন, এটি ব্যাখ্যা করে যে এটি আর ব্যবহার করা উচিত নয়।

কেন


এখান থেকে সরে যাওয়া ext/mysqlকেবল সুরক্ষা সম্পর্কে নয়, মাইএসকিউএল ডাটাবেসের সমস্ত বৈশিষ্ট্যে অ্যাক্সেস পাওয়ার বিষয়েও।

ext/mysqlমাইএসকিউএল ৩.২৩ এর জন্য নির্মিত হয়েছিল এবং তখন থেকে কেবলমাত্র খুব কম সংযোজন হয়েছে যখন বেশিরভাগই এই পুরানো সংস্করণটির সাথে সামঞ্জস্য রেখে যা কোড বজায় রাখা কিছুটা কঠিন করে তোলে। অনুপস্থিত বৈশিষ্ট্যগুলি যা সমর্থন করে না ext/mysqlসেগুলির মধ্যে রয়েছে: ( পিএইচপি ম্যানুয়াল থেকে )।

mysql_*ফাংশন ব্যবহার না করার কারণ :

  • সক্রিয় বিকাশের অধীনে নয়
  • পিএইচপি 7 হিসাবে সরানো হয়েছে
  • একটি ওও ইন্টারফেসের অভাব রয়েছে
  • অ-ব্লকিং, অ্যাসিনক্রোনাস অনুসন্ধানগুলিকে সমর্থন করে না
  • প্রস্তুত বিবৃতি বা প্যারামিটারাইজড কোয়েরি সমর্থন করে না
  • সঞ্চিত পদ্ধতিগুলি সমর্থন করে না
  • একাধিক বিবৃতি সমর্থন করে না
  • লেনদেন সমর্থন করে না
  • মাইএসকিউএল 5.1 এর সমস্ত কার্যকারিতা সমর্থন করে না

উপরের পয়েন্টটি কোয়ান্টিনের উত্তর থেকে উদ্ধৃত হয়েছে

প্রস্তুত বিবৃতিগুলির সমর্থনের অভাব বিশেষত গুরুত্বপূর্ণ কারণ এগুলি পৃথক ফাংশন কলের সাহায্যে ম্যানুয়ালি এড়িয়ে যাওয়ার চেয়ে বাহ্যিক ডেটা থেকে বেরিয়ে আসার এবং উদ্ধৃত করার কম ত্রুটিযুক্ত প্রবণ পদ্ধতি provide

এসকিউএল এক্সটেনশনের তুলনা দেখুন ।


অবমূল্যায়ন সতর্কতা দমন করা

কোডে রূপান্তরিত হচ্ছে যদিও MySQLi/ PDO, E_DEPRECATEDসেটিং দ্বারা ত্রুটি দমন করা যাবে error_reportingমধ্যে php.ini বাদ দেওয়ারE_DEPRECATED:

error_reporting = E_ALL ^ E_DEPRECATED

নোট করুন যে এটি অন্যান্য অবমূল্যায়ন সতর্কতাগুলিও আড়াল করবে , যা মাইএসকিউএল ব্যতীত অন্য কিছুর জন্য হতে পারে। ( পিএইচপি ম্যানুয়াল থেকে )

পিডিও বনাম মাইএসকিউএল নিবন্ধ : আপনার কোনটি ব্যবহার করা উচিত? দ্বারা Dejan Marjanovic আপনি নির্বাচন করতে সাহায্য করবে।

এবং আরও ভাল উপায় PDO, এবং আমি এখন একটি সহজ PDOটিউটোরিয়াল লিখছি ।


একটি সাধারণ এবং সংক্ষিপ্ত পিডিও টিউটোরিয়াল


প্র: আমার মনে প্রথম প্রশ্ন ছিল: `পিডিও` কী?

উ: " পিডিও - পিএইচপি ডেটা অবজেক্টস - একাধিক ডাটাবেসে অ্যাক্সেসের একটি অভিন্ন পদ্ধতি সরবরাহ করে এমন একটি ডাটাবেস অ্যাক্সেস স্তর।"

বিকল্প পাঠ


মাইএসকিউএলে সংযুক্ত হচ্ছে

সঙ্গে mysql_*ফাংশন অথবা আমরা এটা বলতে পারি পুরাতন পথ (থামানো হয়েছে পিএইচপি 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। এ DSNমূলত বিকল্পগুলির একটি স্ট্রিং PDOযা কোন ড্রাইভারটি ব্যবহার করতে হবে এবং সংযোগের বিশদটি জানায়। আরও রেফারেন্সের জন্য, PDO মাইএসকিউএল ডিএসএন পরীক্ষা করুন ।

$db = new PDO('mysql:host=localhost;dbname=testdb;charset=utf8', 'username', 'password');

দ্রষ্টব্য: আপনি এটিও ব্যবহার করতে পারেন charset=UTF-8তবে কখনও কখনও এটি ত্রুটির কারণ হয়ে থাকে তাই এটি ব্যবহার করা আরও ভাল utf8

যদি কোনও সংযোগ ত্রুটি থাকে তবে এটি এমন একটি PDOExceptionবস্তু ছুঁড়ে দেবে যা Exceptionআরও হ্যান্ডেল করার জন্য ধরা পড়ে ।

ভাল পড়ুন : সংযোগ এবং সংযোগ ব্যবস্থাপনা ¶

আপনি চতুর্থ প্যারামিটারের অ্যারে হিসাবে কয়েকটি ড্রাইভার বিকল্পেও যেতে পারেন। আমি পরামিতিটি পাস করার পরামর্শ দিচ্ছি যা 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));

আমরা PDO নির্মাণের পরে বৈশিষ্ট্যগুলি সেট করতে পারি?

হ্যাঁ , আমরা setAttributeপদ্ধতিটি সহ PDO নির্মাণের পরে কিছু বৈশিষ্ট্যও সেট করতে পারি :

$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। (রান-টাইম সতর্কতা (অ-মারাত্মক ত্রুটি) the স্ক্রিপ্ট কার্যকর করা থামেনি))
  • PDO::ERRMODE_EXCEPTION: ব্যতিক্রম নিক্ষেপ। এটি PDO দ্বারা উত্থাপিত একটি ত্রুটি উপস্থাপন করে। PDOExceptionআপনার নিজের কোড থেকে একটি নিক্ষেপ করা উচিত নয় । পিএইচপি-তে ব্যতিক্রম সম্পর্কে আরও তথ্যের জন্য ব্যতিক্রমগুলি দেখুন । এটি খুব বেশি কাজ করে 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এখনি। আপনি যে কোনও সময় এটি উপযুক্ত ধরতে পারেন তবে আমি আপনাকে দৃ strongly়ভাবে ব্যবহার করার পরামর্শ দিচ্ছি 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বিবৃতি? চিন্তা করবেন না, আমরা এখানে যাচ্ছি:


ডেটা নির্বাচন করা হচ্ছে

PDO নির্বাচন করুন চিত্র

সুতরাং আপনি যা করছেন তা 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 কে বলবে যে আপনি কীভাবে ডেটা আনতে চান। নীচের বিভাগে আমি এটি ব্যাখ্যা করছি।

মোডগুলি আনুন

উল্লেখ্য ব্যবহার PDO::FETCH_ASSOCমধ্যে fetch()এবং fetchAll()উপরে কোড। এটি PDOকি হিসাবে ক্ষেত্রের নামগুলি সহ একসেসিয়েটিভ অ্যারে হিসাবে সারিগুলি ফিরিয়ে আনতে বলে । আরও অনেক আনতে মোড রয়েছে যা আমি একে একে ব্যাখ্যা করব।

প্রথমত, আমি কীভাবে আনতে হবে মোডটি নির্বাচন করবেন তা ব্যাখ্যা করছি:

 $stmt->fetch(PDO::FETCH_ASSOC)

উপরের দিকে, আমি ব্যবহার করা হয়েছে fetch()। আপনি এটি ব্যবহার করতে পারেন:

  • PDOStatement::fetchAll() - ফলাফল সেট সারিগুলির মধ্যে একটি অ্যারে ফিরিয়ে দেয়
  • PDOStatement::fetchColumn() - ফলাফল সেটটির পরবর্তী সারি থেকে একটি একক কলাম দেয়
  • PDOStatement::fetchObject() - পরবর্তী সারিতে আনতে এবং এটি একটি বস্তু হিসাবে ফিরিয়ে দেয়।
  • PDOStatement::setFetchMode() - এই বিবৃতিটির জন্য ডিফল্ট আনয়ন মোড সেট করুন

এখন আমি আনতে মোডে:

  • PDO::FETCH_ASSOC: আপনার ফলাফলের সেটটিতে ফিরে আসার সাথে কলামের নাম অনুসারে একটি অ্যারে সূচিত করে
  • PDO::FETCH_BOTH (ডিফল্ট): আপনার ফলাফলের সেটে প্রত্যাবর্তিত কলামের নাম এবং 0-সূচী কলাম নম্বর উভয় দ্বারা সূচকযুক্ত একটি অ্যারে প্রদান করে

আরও পছন্দ আছে! এগুলি সম্পর্কে PDOStatementড্যাচুয়েশন আনুন।

সারি গণনা পাওয়া :

mysql_num_rowsপ্রত্যাবর্তিত সারিগুলির সংখ্যা পেতে ব্যবহার করার পরিবর্তে , আপনি একটি PDOStatementএবং করতে rowCount()পারেন যেমন:

<?php
$stmt = $db->query('SELECT * FROM table');
$row_count = $stmt->rowCount();
echo $row_count.' rows selected';

সর্বশেষ sertedোকানো আইডি পাচ্ছি

<?php
$result = $db->exec("INSERT INTO table(firstname, lastname) VAULES('John', 'Doe')");
$insertId = $db->lastInsertId();

Sertোকান এবং আপডেট করুন বা বিবৃতি মুছুন

PDO চিত্র sertোকান এবং আপডেট করুন

আমরা mysql_*ফাংশনে যা করছি তা হ'ল:

<?php
$results = mysql_query("UPDATE table SET field='value'") or die(mysql_error());
echo mysql_affected_rows($result);

এবং পিডোতে, এই একই জিনিসটি দ্বারা করা যেতে পারে:

<?php
$affected_rows = $db->exec("UPDATE table SET field='value'");
echo $affected_rows;

উপরের ক্যোয়ারিতে PDO::execএকটি এসকিউএল বিবৃতি কার্যকর করুন এবং প্রভাবিত সারিগুলির সংখ্যা প্রদান করে।

সন্নিবেশ এবং মুছুন পরে আচ্ছাদিত করা হবে।

উপরের পদ্ধতিটি কেবল তখনই কার্যকর যখন আপনি কোয়েরিতে ভেরিয়েবল ব্যবহার করছেন না। তবে যখন আপনাকে কোনও ক্যোয়ারিতে একটি ভেরিয়েবল ব্যবহার করার দরকার হয়, কখনও কখনও উপরের মতো চেষ্টা করে নেবেন না এবং প্রস্তুত বিবৃতি বা প্যারামিটারাইজড স্টেটমেন্টটি রয়েছে।


বিবৃতি প্রস্তুত

প্র: প্রস্তুত বিবৃতি কী এবং আমার এগুলি কেন দরকার?
উ: প্রস্তুত বিবৃতিটি একটি পূর্ব-সংকলিত এসকিউএল বিবৃতি যা কেবলমাত্র সার্ভারে ডেটা প্রেরণ করে একাধিকবার কার্যকর করা যায়।

একটি প্রস্তুত বিবৃতি ব্যবহারের সাধারণ কর্মপ্রবাহটি নিম্নরূপ ( উইকিপিডিয়া থেকে তিনটি 3 দফায় উদ্ধৃত ):

  1. প্রস্তুত করুন : বিবৃতি টেম্পলেটটি অ্যাপ্লিকেশন দ্বারা তৈরি করা হয়েছে এবং ডাটাবেস ম্যানেজমেন্ট সিস্টেমে (ডিবিএমএস) প্রেরণ করা হয়। নির্দিষ্ট মানগুলিকে অনির্ধারিত রেখে দেওয়া হয়, যাকে বলা হয় প্যারামিটার, স্থানধারক বা বাইন্ড ভেরিয়েবল ( ?নীচে লেবেলযুক্ত ):

    INSERT INTO PRODUCT (name, price) VALUES (?, ?)

  2. ডিবিএমএস বিবৃতি টেমপ্লেটে কোয়েরি অপ্টিমাইজেশনকে বিশ্লেষণ, সংকলন এবং সম্পাদন করে এবং ফলাফলটি কার্যকর না করেই সঞ্চয় করে।

  3. সম্পাদন করুন : পরবর্তী সময়ে, অ্যাপ্লিকেশন প্যারামিটারগুলির জন্য মান সরবরাহ করে (বা বাঁধাই করে), এবং ডিবিএমএস বিবৃতি কার্যকর করে (সম্ভবত কোনও ফল প্রত্যাবর্তন করে)। অ্যাপ্লিকেশনটি বিভিন্ন মানের সাথে যতবার চায় বিবৃতি কার্যকর করতে পারে। এই উদাহরণস্বরূপ, এটি প্রথম প্যারামিটার এবং 1.00দ্বিতীয় প্যারামিটারের জন্য 'ব্রেড' সরবরাহ করতে পারে ।

আপনি আপনার এসকিউএলে স্থানধারীদের অন্তর্ভুক্ত করে একটি প্রস্তুত বিবৃতি ব্যবহার করতে পারেন। স্থানধারক ব্যতীত মূলত তিনটি রয়েছে (এর উপরের একের সাথে ভেরিয়েবল দিয়ে এটি ব্যবহার করে দেখুন না) একটি, নামবিহীন স্থানধারক এবং অন্য একটি নামধারক স্থানধারক।

প্র। সুতরাং এখন, স্থানধারীদের নাম কী এবং আমি কীভাবে সেগুলি ব্যবহার করব?
উ: নামধারক স্থানধারক। প্রশ্ন চিহ্নের পরিবর্তে কোলন দ্বারা বর্ণিত বর্ণনামূলক নামগুলি ব্যবহার করুন। আমরা নাম স্থান ধারক স্থানে / মান ক্রম সম্পর্কে যত্ন নেই:

 $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প্রস্তুত প্রশ্নের

  1. 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);
  2. INSERT:

    $stmt = $db->prepare("INSERT INTO table(field1,field2) VALUES(:field1,:field2)");
    $stmt->execute(array(':field1' => $field1, ':field2' => $field2));
    $affected_rows = $stmt->rowCount();
  3. DELETE:

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

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

বিঃদ্রঃ:

তবে PDOএবং / অথবা MySQLiসম্পূর্ণ নিরাপদ নয়। উত্তরটি দেখুন কি পিডিও এসকিউএল ইঞ্জেকশন প্রতিরোধের জন্য বিবৃতি প্রস্তুত রয়েছে? 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 /*"));

15
উপরের ভাল পড়াটি কী উল্লেখ করতে হবে: প্রস্তুত বিবৃতিটি এর কোনও অর্থবহ ব্যবহারকে সরিয়ে দেয় IN (...) construct
ইউজেন রিয়েক

24
প্রশ্নটি ছিল "পিএইচপি-তে আমি mysql_ * ফাংশনগুলি কেন ব্যবহার করব না"। এই উত্তরটি চিত্তাকর্ষক এবং সহায়ক তথ্যে ভরপুর হলেও সুযোগের বাইরে চলে গেছে এবং @ ট্রেজার্ডার বলেছেন - 10 জনের মধ্যে 8 জন কেবল এই তথ্যটি মিস করতে চলেছে কারণ তাদের 4 ঘন্টা সময় না কাটানোর জন্য কাজ করার চেষ্টা করা হচ্ছে এটা। এটি অনেক বেশি মূল্যবান ভাঙ্গা এবং বিভিন্ন, আরও সুনির্দিষ্ট, প্রশ্নের উত্তর হিসাবে ব্যবহৃত হবে।
অ্যালেক্স ম্যাকমিলান

ব্যক্তিগতভাবে আমি মাইএসকিলি এবং পিডিও পছন্দ করি। তবে ডাই হ্যান্ডলিংয়ের জন্য, আমি ব্যতিক্রমের বিকল্প চেষ্টা করেছিলাম function throwEx() { throw new Exception("You did selected not existng db"); } mysql_select_db("nonexistdb") or throwEx();এটি ব্যতিক্রম ছোঁড়ার পক্ষে কাজ করে।
কুলদীপ.কম্বুজ

আপনি Doesn't support non-blocking, asynchronous queriesমাইএসকিএল_ ব্যবহার না করার কারণ হিসাবে তালিকাবদ্ধ করেছেন - আপনার পিডিও ব্যবহার না করার কারণ হিসাবে এটিও তালিকাভুক্ত করা উচিত, কারণ পিডিও এটি সমর্থন করে না। (তবে মাইএসকিউএলআই এটি সমর্থন করে)
হ্যানশেরিক

আমার কীভাবে এটি ব্যবহার করছে এমন একটি ডাটাবেস আছে তাই চরসেট utf8mb4_unicode_ci ব্যবহার করা সম্ভব?
রায়ান স্টোন

301

প্রথমে আসুন আমরা প্রত্যেককে যে স্ট্যান্ডার্ড মন্তব্য দিয়েছি তা দিয়ে শুরু করুন:

দয়া করে mysql_*নতুন কোডে ফাংশন ব্যবহার করবেন না । এগুলি আর রক্ষণাবেক্ষণ করা হয় না এবং সরকারীভাবে হ্রাস করা হয় । দেখুন লাল বক্স ? পরিবর্তে প্রস্তুত বিবৃতি সম্পর্কে জানুন, এবং PDO বা মাইএসকিউএলি ব্যবহার করুন- এই নিবন্ধটি আপনাকে সিদ্ধান্ত নিতে সহায়তা করবে। আপনি যদি PDO চয়ন করেন তবে এখানে একটি ভাল টিউটোরিয়াল রয়েছে

আসুন এর মাধ্যমে, বাক্য দ্বারা বাক্যটি ব্যাখ্যা করুন এবং ব্যাখ্যা করুন:

  • এগুলি আর রক্ষণাবেক্ষণ করা হয় না, এবং সরকারীভাবে হ্রাস করা হয়

    এর অর্থ এই যে পিএইচপি সম্প্রদায় ধীরে ধীরে এই খুব পুরানো ফাংশনগুলির জন্য সমর্থন বাদ দিচ্ছে। তারা পিএইচপি-র ভবিষ্যতের (সাম্প্রতিক) সংস্করণে উপস্থিত না থাকার সম্ভবত! এই ক্রিয়াকলাপগুলির অবিচ্ছিন্ন ব্যবহার ভবিষ্যতে আপনার কোডটি ভেঙে দিতে পারে (অতটা না) ভবিষ্যতে।

    নতুন! - এক্সট্রা / মাইএসকিএল এখন পিএইচপি 5.5 হিসাবে সরকারীভাবে অবচয় করা হয়েছে!

    নবীনতর! ext / mysql পিএইচপি 7 এ সরিয়ে ফেলা হয়েছে

  • পরিবর্তে, আপনি প্রস্তুত বিবৃতি শিখতে হবে

    mysql_*এক্সটেনশন প্রস্তুত বিবৃতি সমর্থন করে না , যা এসকিউএল ইঞ্জেকশনের বিরুদ্ধে খুব কার্যকর প্রতিরোধের (অন্যান্য বিষয়গুলির মধ্যে) । এটি মাইএসকিউএল নির্ভরশীল অ্যাপ্লিকেশনগুলির মধ্যে একটি মারাত্মক দুর্বলতা ঠিক করেছে যা আক্রমণকারীদের আপনার স্ক্রিপ্টে অ্যাক্সেস পেতে এবং আপনার ডাটাবেসে কোনও সম্ভাব্য ক্যোয়ারী সম্পাদন করতে দেয় ।

    আরও তথ্যের জন্য দেখুন কীভাবে আমি পিএইচপি-তে এসকিউএল ইঞ্জেকশনটি আটকাতে পারি?

  • রেড বক্সটি দেখুন?

    আপনি যখন কোনও mysqlফাংশন ম্যানুয়াল পৃষ্ঠায় যান, আপনি একটি লাল বাক্স দেখতে পাবেন, এটি ব্যাখ্যা করে যে এটি আর ব্যবহার করা উচিত নয়।

  • PDO বা MySQLi হয় ব্যবহার করুন either

    পিডিও - পিএইচপি ডেটাবেস অবজেক্টটি আরও ভাল, আরও দৃust় এবং সুগঠিত বিকল্প রয়েছে , যা ডাটাবেস ইন্টারঅ্যাকশনের জন্য একটি সম্পূর্ণ ওওপি পদ্ধতির প্রস্তাব দেয় এবং মাইএসকিউএলই , যা মাইএসকিউএল নির্দিষ্ট উন্নতি।


6
আরও একটি জিনিস রয়েছে: আমি মনে করি যে পিএইচপি-তে এখনও একটি কারণেই ফাংশন বিদ্যমান রয়েছে - পুরানো, পুরানো তবে এখনও চলমান সিএমএস, ই-বাণিজ্য, বুলেটিন বোর্ড সিস্টেমগুলির সাথে সামঞ্জস্যতা অবশেষে এটি সরিয়ে ফেলা হবে এবং আপনাকে আপনার পুনর্লিখন করতে হবে অ্যাপ্লিকেশন ...
কামিল

4
@ কামিল: এটি সত্য, তবে এটি ব্যবহার না করার কারণ এটি আসলে কোনও কারণ নয়। এটি ব্যবহার না করার কারণ হ'ল এটি প্রাচীন, অনিরাপদ ইত্যাদি :) :)
মাদারার ঘোস্ট

4
@ মারিও - পিএইচপি দেবগণের একটি প্রক্রিয়া রয়েছে এবং তারা মাত্র 5.5 হিসাবে আনুষ্ঠানিকভাবে এক্সট্রা / মাইএসকিএলকে অবমূল্যায়নের পক্ষে ভোট দিয়েছেন। এটি আর কোনও অনুমানের বিষয় নয়।
এসডিসি

2
প্রমাণিত প্রযুক্তি যেমন পিডিও বা মাইএসকিউএলির সাথে একাধিক অতিরিক্ত লাইন যুক্ত করা এখনও পিএইচপি সর্বদা অফার করে এমন স্বাচ্ছন্দ্য দেয়। আমি বিকাশকারীর পক্ষে আশা করি তিনি জানেন যে কোনও টিউটোরিয়ালে এই godশ্বর-ভয়ঙ্কর মাইএসকিএল_ * ফাংশনগুলি দেখে পাঠ থেকে বিরত থাকে, এবং ওপিকে জানানো উচিত যে এই ধরণের কোডটি 10 ​​বছর আগে খুব সুন্দর ছিল - এবং প্রশ্নটি করা উচিত টিউটোরিয়ালের প্রাসঙ্গিকতাও!
ফ্রেড দ্য ওয়েইগগুই

1
উত্তরে উত্তরটি কী উল্লেখ করতে হবে: প্রস্তুত বিবৃতি এর কোনও অর্থবহ ব্যবহারকে সরিয়ে দেয় IN (...) construct
ইউজেন রিয়েক

217

ব্যবহারে সহজ

বিশ্লেষণমূলক এবং সিন্থেটিক কারণগুলি ইতিমধ্যে উল্লেখ করা হয়েছিল। নতুনদের জন্য তারিখের মাইএসকিএল_ ফাংশন ব্যবহার বন্ধ করার জন্য আরও একটি গুরুত্বপূর্ণ উত্সাহ রয়েছে।

সমসাময়িক ডাটাবেস এপিআইগুলি ব্যবহার করা কেবল সহজ

এটি বেশিরভাগ সীমাবদ্ধ পরামিতি যা কোড সরল করতে পারে। এবং দুর্দান্ত টিউটোরিয়াল সহ (উপরে দেখানো হয়েছে) পিডিওতে রূপান্তর অত্যধিক কঠিন নয়।

একবারে একটি বৃহত্তর কোড বেস পুনর্লিখন করতে সময় লাগে। এই মধ্যবর্তী বিকল্পের জন্য রাইসন ডি'ত্রে:

সমতুল্য pdo_ * স্থানে ফাংশন mysql_ *

< Pdo_mysql.php > ব্যবহার করে আপনি নূন্যতম প্রচেষ্টা সহ পুরানো mysql_ ফাংশন থেকে স্যুইচ করতে পারেন । এটি pdo_ফাংশন র‌্যাপারগুলি যুক্ত করে যা তাদের অংশগুলি প্রতিস্থাপন করে mysql_

  1. কেবলমাত্র প্রতিটি অনুরোধ স্ক্রিপ্টে যা ডাটাবেসের সাথে ইন্টারঅ্যাক্ট করতে হয়। include_once("pdo_mysql.php");

  2. mysql_ফাংশন উপসর্গটি সর্বত্র সরিয়ে ফেলুন এবং এর সাথে প্রতিস্থাপন করুন pdo_

    • mysql_connect() হয়ে pdo_connect()
    • mysql_query() হয়ে pdo_query()
    • mysql_num_rows() হয়ে pdo_num_rows()
    • mysql_insert_id() হয়ে pdo_insert_id()
    • mysql_fetch_array() হয়ে pdo_fetch_array()
    • mysql_fetch_assoc() হয়ে pdo_fetch_assoc()
    • mysql_real_escape_string() হয়ে pdo_real_escape_string()
    • এবং তাই ...

  3. আপনার কোডটি একইভাবে কাজ করবে এবং এখনও বেশিরভাগ ক্ষেত্রে একই দেখাচ্ছে:

    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]";
    }

এবং voilà।
আপনার কোডটি PDO ব্যবহার করছে
এখন সময় এসেছে এটি সত্যই কাজে লাগানোর

বাউন্ড প্যারামিটারগুলি ব্যবহার করা সহজ

আপনার কেবলমাত্র অল্পস্বল্প এপিআই দরকার।

pdo_query()সীমাবদ্ধ পরামিতিগুলির জন্য খুব সহজ সমর্থন যোগ করে। পুরানো কোড রূপান্তর করা সোজা:

আপনার ভেরিয়েবলগুলি এসকিউএল স্ট্রিংয়ের বাইরে নিয়ে যান।

  • এগুলিতে কমা সীমিত ফাংশন পরামিতি হিসাবে যুক্ত করুন pdo_query()
  • ?ভেরিয়েবল আগে যেখানে স্থানধারক হিসাবে প্রশ্ন চিহ্ন রাখুন ।
  • 'পূর্বে বন্ধ স্ট্রিংয়ের মান / ভেরিয়েবলগুলি একক উদ্ধৃতি থেকে মুক্তি পান ।

দীর্ঘতর কোডের জন্য সুবিধাটি আরও সুস্পষ্ট হয়ে ওঠে।

প্রায়শই স্ট্রিং ভেরিয়েবলগুলি এসকিউএল-তে কেবল ইন্টারপোল্ট করা হয় না, তবে এর মধ্যে পালানো কলগুলির সাথে সংযুক্ত থাকে।

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")

সঙ্গে ?প্লেসহোল্ডার প্রয়োগ আপনি যে সঙ্গে বিরক্ত করার জন্য নেই:

pdo_query("SELECT id, links, html, title, user, date FROM articles
   WHERE title=? OR id=? AND user<>? ORDER BY date", $title, $id, $root)

মনে রাখবেন যে pdo_ * এখনও অনুমতি দেয় বা হয়
শুধু একটি পরিবর্তনশীল অব্যাহতি না এবং একই ক্যোয়ারীতে করে বাঁধে।

  • স্থানধারক বৈশিষ্ট্যটি এর পিছনে আসল পিডিও সরবরাহ করে by
  • সুতরাং :namedপরে স্থানধারক তালিকাগুলি অনুমোদিত ।

আরও গুরুত্বপূর্ণ আপনি যে কোনও প্রশ্নের পিছনে নিরাপদে $ _REQUEST [] ভেরিয়েবলগুলি পাস করতে পারেন। যখন জমা দেওয়া <form>ক্ষেত্রগুলি ডাটাবেস কাঠামোর সাথে মেলে ঠিক তখন এটি আরও ছোট হয়:

pdo_query("INSERT INTO pages VALUES (?,?,?,?,?)", $_POST);

এত সরলতা। তবে আপনি কেন পরিত্রাণ পেতে mysql_এবং পালাতে চাইতে পারেন তার আরও কয়েকটি পুনর্লিখনের পরামর্শ এবং প্রযুক্তিগত কারণগুলিতে ফিরে আসি ।

কোনও পুরানো স্কুল sanitize()ফাংশন ঠিক করুন বা অপসারণ করুন

একবার আপনি সমস্ত mysql_কলকে pdo_queryবাউন্ড প্যারামের সাথে রূপান্তরিত করার পরে সমস্ত রিডানড্যান্ট pdo_real_escape_stringকলগুলি সরিয়ে ফেলুন ।

বিশেষত আপনার কোনও sanitizeবা cleanবা filterThisবা clean_dataফাংশন স্থিত টিউটোরিয়ালগুলির দ্বারা একটি ফর্ম বা অন্যটিতে বিজ্ঞাপনিত হিসাবে ঠিক করা উচিত :

function sanitize($str) {
   return trim(strip_tags(htmlentities(pdo_real_escape_string($str))));
}

এখানে বেশিরভাগ সুস্পষ্ট বাগ হ'ল নথিপত্রের অভাব। আরও উল্লেখযোগ্যভাবে ফিল্টারিংয়ের ক্রমটি ছিল সঠিক ক্রম order

  • সঠিক অনুক্রমে হতো: deprecatedly stripslashesঅন্তরতম কল করে দাঁড়াও, অতঃপর trim, পরে strip_tags, htmlentitiesআউটপুট প্রসঙ্গ, এবং শুধুমাত্র সর্বশেষে জন্য _escape_stringতার প্রয়োগ যেমন সরাসরি SQL এর intersparsing preceed করা উচিত নয়।

  • তবে প্রথম পদক্ষেপ হিসাবে কেবল কল থেকে মুক্তি পান_real_escape_string

  • sanitize()আপনার ডাটাবেস এবং অ্যাপ্লিকেশন প্রবাহ যদি এইচটিএমএল-প্রসঙ্গ-সুরক্ষিত স্ট্রিংগুলি প্রত্যাশা করে তবে আপাতত আপনার বাকী কাজটি রাখতে হবে । একটি মন্তব্য যুক্ত করুন যে এটি কেবলমাত্র এইচটিএমএল থেকে অব্যাহতি প্রয়োগ করে।

  • স্ট্রিং / মান হ্যান্ডলিং পিডিও এবং এর প্যারামিটারাইজড স্টেটমেন্টগুলিতে অর্পণ করা হয়।

  • যদি stripslashes()আপনার স্যানিটাইজ ফাংশনে কোনও উল্লেখ থাকে তবে এটি উচ্চ স্তরের তদারকি নির্দেশ করতে পারে।

    ম্যাজিক_কোটেসে noteতিহাসিক নোট। এই বৈশিষ্ট্যটি যথাযথভাবে হ্রাস করা হয়েছে। এটি প্রায়শই ভুলভাবে সুরক্ষা বৈশিষ্ট্য হিসাবে ব্যর্থ হিসাবে চিত্রিত হয়েছে । টেনিস বল পুষ্টির উত্স হিসাবে ব্যর্থ হয়েছে হিসাবে ম্যাজিক_কোটিস যেমন একটি ব্যর্থ সুরক্ষা বৈশিষ্ট্য। এটি কেবল তাদের উদ্দেশ্য ছিল না।

    পিএইচপি 2 / এফআই-এর আসল বাস্তবায়নটি কেবল " কোটেশন " সহ স্পষ্টভাবে এটির সাথে পরিচয় করিয়ে দিয়েছিল সরাসরি এমএসকিএল কোয়েরিতে ফর্ম ডেটা প্রেরণ করা সহজ করে "" স্বয়ংক্রিয়ভাবে পালিয়ে যাবে "। উল্লেখযোগ্যভাবে এটি এমএসকিউএল সহ সনাক্ত করা নিরাপদ ছিল , কারণ এটি কেবলমাত্র ASCII সমর্থন করে।
    তারপরে পিএইচপি 3 / জেনড মাইএসকিউএল এর জন্য ম্যাজিক_কোটগুলি পুনরায় প্রবর্তন করেছিল এবং এটিকে ভুল দস্তাবেজ করেছে। তবে মূলত এটি ছিল একটি সুবিধার বৈশিষ্ট্য , সুরক্ষার উদ্দেশ্যে নয়।

কীভাবে প্রস্তুত বিবৃতি আলাদা হয়

আপনি যখন এসকিউএল কোয়েরিতে স্ট্রিং ভেরিয়েবলগুলি স্ক্যাম্বল করেন, তখন আপনাকে অনুসরণ করার পক্ষে এটি আরও জটিল হয় না। মাইএসকিউএল এর আবার কোড এবং ডেটা আলাদা করার চেষ্টা করাও বহিরাগত প্রচেষ্টা।

এসকিউএল ইনজেকশনগুলি কেবল তখনই হয় যখন ডেটা কোডের প্রসঙ্গে প্রবাহিত হয় । কোনও ডাটাবেস সার্ভার পরে স্পট করতে পারে না যেখানে পিএইচপি মূলত কোয়েরি ক্লজগুলির অভ্যন্তরে চলকগুলিকে আটকানো হয়েছে।

আবদ্ধ প্যারামিটারের সাহায্যে আপনি আপনার পিএইচপি কোডে এসকিউএল কোড এবং এসকিউএল-প্রসঙ্গ মানগুলি পৃথক করেন। তবে এটি আবার পর্দার আড়ালে ফিরে আসে না (PDO :: EMULATE_PREPARES ব্যতীত)। আপনার ডাটাবেসটি অবিচ্ছিন্ন এসকিউএল কমান্ড এবং 1: 1 ভেরিয়েবল মান গ্রহণ করে।

যদিও এই উত্তরে জোর দেওয়া হয়েছে যে আপনার ঝরে পড়ার পাঠযোগ্যতা সুবিধাগুলি সম্পর্কে যত্ন নেওয়া উচিত mysql_। এই দৃশ্যমান এবং প্রযুক্তিগত ডেটা / কোড পৃথকীকরণের কারণে মাঝে মাঝে একটি পারফরম্যান্স সুবিধা (কেবলমাত্র পৃথক মানগুলির সাথে পুনরাবৃত্তি INSERTs) রয়েছে।

সাবধান যে প্যারামিটার বাঁধাই এখনও সমস্ত এসকিউএল ইঞ্জেকশনগুলির বিরুদ্ধে ম্যাজিক ওয়ান স্টপ সমাধান নয় । এটি ডেটা / মানগুলির জন্য সর্বাধিক সাধারণ ব্যবহার পরিচালনা করে। তবে কলামের নাম / সারণী শনাক্তকারীদের শ্বেত তালিকাভুক্ত করতে পারে না, গতিশীল ক্লজ নির্মাণে সহায়তা করতে পারে, বা কেবল সরল অ্যারে মান তালিকাগুলি।

হাইব্রিড পিডিও ব্যবহার করুন

এই pdo_*মোড়ক ফাংশন একটি কোডিং-বান্ধব স্টপ-গ্যাপ API তৈরি করে make (এটি MYSQLIআইডিসিক্র্যাটিক ফাংশন স্বাক্ষর শিফ্টের জন্য না হলে কী হতে পারত)) তারা বেশিরভাগ সময়ে আসল পিডিওও প্রকাশ করে।
নতুন pdo_ ফাংশন নাম ব্যবহার করে পুনরায় লেখালেখি থামাতে হবে না। আপনি এক এক করে প্রতিটি পিডো_কোয়ারী () কে একটি সরল $ pdo-> প্রস্তুত () -> চালানো () কলটিতে রূপান্তর করতে পারেন।

তবে আবার সরলকরণ শুরু করা ভাল। উদাহরণস্বরূপ সাধারণ ফলাফল আনয়ন:

$result = pdo_query("SELECT * FROM tbl");
while ($row = pdo_fetch_assoc($result)) {

কেবল একটি পূর্বাঞ্চ পুনরাবৃত্তি দিয়ে প্রতিস্থাপন করা যেতে পারে:

foreach ($result as $row) {

বা আরও ভাল একটি সরাসরি এবং সম্পূর্ণ অ্যারে পুনরুদ্ধার:

$result->fetchAll();

আপনি ব্যর্থ প্রশ্নের পরে সাধারণত PDO বা mysql_ সরবরাহের চেয়ে বেশিরভাগ ক্ষেত্রে আরও সহায়ক সতর্কতা পাবেন।

অন্যান্য অপশন

তাই এই আশা কিছু ভিজ্যুয়ালাইজ ব্যবহারিক কারণে এবং ড্রপ করার জন্য একটি worthwile পথ mysql_

শুধু স্যুইচ করা একেবারেই কাটেনি। pdo_query()এটি শুধুমাত্র একটি সম্মুখভাগ।

আপনি যদি না প্যারামিটার বাইন্ডিং প্রবর্তন করেন বা ভাল API থেকে অন্য কিছু ব্যবহার করতে না পারেন তবে এটি অর্থহীন সুইচ। আমি আশা করি এটি একেবারে সহজ চিত্রিত হয়েছে যাতে নতুনদের মধ্যে নিরুৎসাহ না বাড়িয়ে দেওয়া যায়। (শিক্ষা সাধারণত নিষেধের চেয়ে ভাল কাজ করে।)

যদিও এটি সম্ভবত সবচেয়ে সহজ-কাজটি-সম্ভবত-কাজ-বিভাগের জন্য যোগ্যতা অর্জন করে, এটি এখনও খুব পরীক্ষামূলক কোড। আমি সপ্তাহান্তে এটি লিখেছি। তবে বিকল্পগুলির আধিক্য রয়েছে। পিএইচপি ডাটাবেস বিমূর্তনের জন্য কেবল গুগল করুন এবং কিছুটা ব্রাউজ করুন। এই জাতীয় কাজের জন্য সর্বদা দুর্দান্ত গ্রন্থাগার রয়েছে এবং থাকবে।

আপনি যদি আপনার ডেটাবেস ইন্টারঅ্যাকশন আরও সরল করতে চান তবে প্যারিস / আইডিয়র্মের মতো ম্যাপাররা চেষ্টা করার মতো। ঠিক তেমন কেউ জাভাস্ক্রিপ্টে দুষ্কর DOM ব্যবহার করে না, আজকাল আপনাকে কোনও কাঁচা ডাটাবেস ইন্টারফেসটি ববাই করতে হবে না।


8
pdo_query("INSERT INTO pages VALUES (?,?,?,?,?)", $_POST);ফাংশনটি সম্পর্কে সতর্কতা অবলম্বন করুন - যেমন:pdo_query("INSERT INTO users VALUES (?, ?, ?), $_POST); $_POST = array( 'username' => 'lawl', 'password' => '123', 'is_admin' => 'true');
রিক্যডাক্ক

@ টম অবশ্যই, এটি খুব বেশি রক্ষণাবেক্ষণ না করা সত্ত্বেও (0.9.2 শেষ ছিল), আপনি একটি জীবাশ্ম অ্যাকাউন্ট তৈরি করতে পারেন , উইকিতে যুক্ত করতে পারেন বা একটি বাগ রিপোর্ট ফাইল করতে পারেন (আইআইআরসি রেজিস্ট্রেশন ছাড়াই)।
মারিও

pdo_real_escape_string() <- এটি কি একটি আসল কাজ, আমি এর জন্য কোনও ডকুমেন্টেশন খুঁজে পাচ্ছি না? এই জন্য একটি উত্স পোস্ট করুন।
রায়ান স্টোন

144

mysql_ফাংশন:

  1. পুরানো - তারা আর বজায় রাখা হয় না
  2. আপনাকে অন্য ডেটাবেস ব্যাকএন্ডে সহজেই স্থানান্তর করতে দেবেন না
  3. অতএব, প্রস্তুত বিবৃতি সমর্থন করবেন না
  4. এসকিউএল ইঞ্জেকশন দুর্বলতার দিকে নিয়ে প্রোগ্রামারদের কোয়েরি তৈরির জন্য কনটেনটেশন ব্যবহার করতে উত্সাহিত করুন

18
# 2 সমানভাবে সত্যmysqli_
উদাহরণস্বরূপ

16
সুষ্ঠু হতে, এসকিউএল ডায়ালিকের পরিবর্তনের পরিপ্রেক্ষিতে, এমনকি পিডিও কোনও ডিগ্রি সহ আপনাকে # 2 দেয় না। তার জন্য আপনার একটি উপযুক্ত ওআরএম র‌্যাপার দরকার need
এসডিসি

mysql_*ফাংশন নতুন পিএইচপি সংস্করণের জন্য mysqlnd ফাংশন মধ্যে একটি শেল হয়। এমনকি পুরাতন ক্লায়েন্ট লাইব্রেরিটি আর রক্ষণাবেক্ষণ না করা সত্ত্বেও, মাইকিউএলএন্ড রক্ষণাবেক্ষণ করা হয় :)
হ্যাক্রে

সমস্যাটি অনেকগুলি ওয়েব হোস্টিং সরবরাহকারী পুরানো পিএইচপি সংস্করণের কারণে এই জাতীয় অবজেক্ট-ভিত্তিক স্টাইলের নকশাকে সমর্থন করতে পারে না
রাজু আপনার পিপি

@ রাজুগুরাজি তাই এমন একটি ওয়েব হোস্ট সন্ধান করুন। যদি আপনার ওয়েব হোস্ট না করে তবে সম্ভাবনা খুব বেশি যে তারা তাদের সার্ভারগুলিতে আক্রমণে ঝুঁকির মধ্যে রয়েছে।
Alnitak

106

প্রযুক্তিগত কারণে কথা বলতে গেলে, এখানে কয়েকটি মাত্র, অত্যন্ত নির্দিষ্ট এবং খুব কম ব্যবহৃত হয়। সম্ভবত আপনি তাদের জীবনে কখনও ব্যবহার করবেন না।
হতে পারে আমি খুব অজ্ঞ, তবে তাদের মতো জিনিস ব্যবহার করার সুযোগ আমার কখনই আসেনি

  • অ-ব্লকিং, অ্যাসিনক্রোনাস কোয়েরি
  • একাধিক ফলাফলের ফলাফলগুলি সঞ্চিত পদ্ধতি
  • এনক্রিপশন (এসএসএল)
  • সঙ্কোচন

আপনার যদি তাদের প্রয়োজন হয় - এগুলি মাইএসকিএল এক্সটেনশন থেকে আরও আড়ম্বরপূর্ণ এবং আধুনিক চেহারার দিকে সরে যাওয়ার কোনও প্রযুক্তিগত কারণ নয়।

তবুও, কিছু অ-প্রযুক্তিগত সমস্যাও রয়েছে, যা আপনার অভিজ্ঞতাটিকে কিছুটা শক্ত করে তুলতে পারে

  • আধুনিক পিএইচপি সংস্করণগুলির সাথে এই ক্রিয়াকলাপগুলির আরও ব্যবহার অবচিত-স্তরের বিজ্ঞপ্তিগুলি বাড়িয়ে তুলবে। এগুলি কেবল বন্ধ করা যায়।
  • সুদূর ভবিষ্যতে, তাদের সম্ভবত ডিফল্ট পিএইচপি বিল্ড থেকে সরানো যেতে পারে। খুব বড় বিষয়ও নয়, যেহেতু মাইডএসকিএল এক্সটাকে পিইসিএলে স্থানান্তরিত করা হবে এবং প্রতিটি হোস্টার এটির সাথে পিএইচপি সংকলন করতে খুশি হবে, কারণ তারা যে ক্লায়েন্টদের দশক ধরে কাজ করছিল তাদের ক্লায়েন্টকে হারাতে চায় না।
  • স্ট্যাকওভারফ্লো সম্প্রদায়ের তীব্র প্রতিরোধ। প্রতিবার আপনি এই সৎ কাজগুলি উল্লেখ করার সময়, আপনাকে বলা হচ্ছে যে সেগুলি কঠোরভাবে নিষিদ্ধ।
  • একজন গড় পিএইচপি ব্যবহারকারী হওয়ায় সম্ভবত এই ফাংশনগুলি ব্যবহার করার আপনার ধারণাটি ত্রুটি-প্রবণ এবং ভুল। এই সমস্ত অসংখ্য টিউটোরিয়াল এবং ম্যানুয়ালগুলির কারণে যা আপনাকে ভুল উপায়ে পাঠায়। সেগুলি নিজেরাই নয় - আমাকে এটির উপর জোর দিতে হবে - তবে তারা যেভাবে ব্যবহৃত হয়।

এই পরবর্তী সমস্যাটি একটি সমস্যা।
তবে, আমার মতে, প্রস্তাবিত সমাধানটি এর চেয়ে ভাল আর নয়।
আমার কাছে এটি খুব আদর্শিক একটি স্বপ্ন বলে মনে হচ্ছে যে এই সমস্ত পিএইচপি ব্যবহারকারীরা এসকিউএল কোয়েরিগুলি একবারে কীভাবে সঠিকভাবে পরিচালনা করতে শিখবেন। সম্ভবত সম্ভবত তারা যান্ত্রিকভাবে mysql_ * কে mysqli_ * এ পরিবর্তন করবে, পদ্ধতির দিকটি একই রেখে । বিশেষত কারণ মাইএসকিলি প্রস্তুত বিবৃতি ব্যবহারকে অবিশ্বাস্য বেদনাদায়ক এবং ঝামেলা করে। এসকিউএল ইনজেকশনগুলি থেকে রক্ষা করার জন্য নেটিভ প্রস্তুত বিবৃতিগুলি যথেষ্ট নয় এবং মাইসকিলি বা পিডিও উভয়ই এর সমাধান দেয় না বলে
উল্লেখ করার দরকার নেই।

সুতরাং, এই সৎ সম্প্রসারনের বিরুদ্ধে লড়াই করার পরিবর্তে, আমি ভুল অভ্যাসের বিরুদ্ধে লড়াই করা এবং মানুষকে সঠিক উপায়ে শিক্ষিত করতে পছন্দ করব।

এছাড়াও, কিছু ভুল বা অ-উল্লেখযোগ্য কারণ রয়েছে, যেমন

  • সঞ্চিত পদ্ধতিগুলি সমর্থন করে না (আমরা mysql_query("CALL my_proc");যুগে যুগে ব্যবহার করছিলাম )
  • লেনদেনগুলি সমর্থন করে না (উপরের মতো)
  • একাধিক বিবৃতি সমর্থন করে না (তাদের প্রয়োজন কে?)
  • সক্রিয় বিকাশের অধীনে নেই (তাহলে কী? এটি কোনও ব্যবহারিক উপায়ে আপনাকে প্রভাবিত করে ?)
  • একটি ওও ইন্টারফেসের অভাব রয়েছে (এটি তৈরি করতে কয়েক ঘন্টা ব্যয় হয়)
  • প্রস্তুত বিবৃতি বা প্যারাম্যাট্রাইজড ক্যোয়ারী সমর্থন করে না

শেষটি একটি আকর্ষণীয় বিষয়। যদিও মাইএসকিএল এক্সট নেটিভ প্রস্তুত বিবৃতি সমর্থন করে না , সেগুলি সুরক্ষার জন্য প্রয়োজন হয় না। আমরা ম্যানুয়ালি হ্যান্ডেল করা স্থানধারকগুলি (পিডিওর মতো) ব্যবহার করে সহজেই জাল প্রস্তুত বিবৃতিগুলি করতে পারি:

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

ভয়েলা , সবকিছু প্যারামিটারাইজড এবং নিরাপদ।

তবে ঠিক আছে, আপনি যদি ম্যানুয়ালটিতে লাল বাক্সটি পছন্দ না করেন তবে পছন্দের সমস্যা দেখা দেয়: মাইএসকিলি বা পিডিও?

ঠিক আছে, উত্তরটি নিম্নরূপ হবে:

  • আপনি যদি ডেটাবেস বিমূর্তকরণ স্তর ব্যবহার করার প্রয়োজনীয়তা বুঝতে এবং একটি তৈরি করার জন্য একটি API অনুসন্ধান করে থাকেন তবে মাইএসকিলি একটি খুব ভাল পছন্দ, কারণ এটি সত্যিকার অর্থে অনেকগুলি মাইএসকিএল-নির্দিষ্ট বৈশিষ্ট্য সমর্থন করে।
  • যদি, পিএইচপি জনগণের সিংহভাগের মতো, আপনি অ্যাপ্লিকেশন কোডের ঠিক কাঁচা এপিআই কলগুলি ব্যবহার করছেন (যা মূলত ভুল অনুশীলন) - পিডিও হ'ল একমাত্র পছন্দ , কারণ এই এক্সটেনশনটি কেবল এপিআই নয়, বরং একটি আধা-ডাল হওয়ার ভান করে, এখনও অসম্পূর্ণ তবে অনেকগুলি গুরুত্বপূর্ণ বৈশিষ্ট্য সরবরাহ করে, এর মধ্যে দুটি পিডিওকে মাইসকিলি থেকে সমালোচিতভাবে আলাদা করে তুলেছে:

    • mysqli এর বিপরীতে, PDO স্থানধারককে মান দ্বারা আবদ্ধ করতে পারে , যা বেশ গণ্ডগোলের কোডের বেশ কয়েকটি স্ক্রিন ছাড়াই গতিশীলভাবে নির্মিত ক্যোয়ারিকে সম্ভাব্য করে তোলে।
    • mysqli এর বিপরীতে, PDO সর্বদা একটি সাধারণ সাধারণ অ্যারেতে ক্যোয়ারির ফলাফলটি সর্বদা ফিরিয়ে দিতে পারে, যখন mysqli কেবল mysqlnd ইনস্টলেশনগুলিতে করতে পারে।

সুতরাং, আপনি যদি গড় পিএইচপি ব্যবহারকারী হন এবং দেশীয় প্রস্তুত বিবৃতিগুলি ব্যবহার করার সময় নিজেকে এক টন মাথা ব্যথা বাঁচাতে চান, পিডিও - আবার - একমাত্র পছন্দ।
তবে পিডিও খুব বেশি রূপালী বুলেট নয় এবং এর অসুবিধাও রয়েছে।
সুতরাং, আমি PDO ট্যাগ উইকিতে সমস্ত সাধারণ সমস্যা এবং জটিল মামলার সমাধান লিখেছি

তবুও, এক্সটেনশনের বিষয়ে কথা বলার প্রত্যেকে Mysqli এবং PDO সম্পর্কে 2 টি গুরুত্বপূর্ণ তথ্য সর্বদা অনুপস্থিত :

  1. প্রস্তুত বিবৃতি কোনও রূপোর বুলেট নয় । গতিশীল শনাক্তকারী রয়েছে যা প্রস্তুত বিবৃতি ব্যবহার করে আবদ্ধ হতে পারে না। অজানা সংখ্যক পরামিতিগুলির সাথে ডায়নামিকাল ক্যোয়ারী রয়েছে যা কোয়েরি বিল্ডিংকে একটি কঠিন কাজ করে তোলে।

  2. মাইএসকিলি_ * বা পিডিও ফাংশন উভয়ই অ্যাপ্লিকেশন কোডটিতে উপস্থিত হওয়া উচিত ছিল না। তাদের এবং অ্যাপ্লিকেশন কোডের মধ্যে
    একটি বিমূর্ত স্তর থাকা উচিত, যা বাইন্ডিং, লুপিং, ত্রুটি পরিচালনা করা ইত্যাদির অভ্যন্তরীণ সমস্ত অ্যাপ্লিকেশন কোড ডিআরওয়াই এবং পরিষ্কার করে দেবে। বিশেষত ডায়নামিকাল ক্যোয়ারী বিল্ডিংয়ের মতো জটিল ক্ষেত্রে।

সুতরাং, কেবল পিডিও বা মাইসকিলে স্যুইচ করা যথেষ্ট নয়। তাদের কোডে কাঁচা এআইপি ফাংশন কল করার পরিবর্তে একজনকে একটি ওআরএম, বা কোয়েরি বিল্ডার, বা যে কোনও ডাটাবেস বিমূর্ত শ্রেণি ব্যবহার করতে হবে।
এবং বিপরীতে - আপনার যদি আপনার অ্যাপ্লিকেশন কোড এবং মাইএসকিএল এপিআইয়ের মধ্যে বিমূর্ত স্তর থাকে - কোন ইঞ্জিনটি ব্যবহৃত হয় তা আসলে কোনও ব্যাপার নয়। আপনি মাইএসকিএল এক্স ব্যবহার করতে পারবেন যতক্ষণ না এটি অবনমিত হয় এবং তারপরে সহজেই আপনার বিমূর্ততা ক্লাসটি অন্য কোনও ইঞ্জিনে পুনরায় লেখা যায়, সমস্ত অ্যাপ্লিকেশন কোড অক্ষত থাকে।

এই জাতীয় বিমূর্ত শ্রেণিটি কীভাবে হওয়া উচিত তা দেখানোর জন্য এখানে আমার সেফএমএসকিএল ক্লাসের উপর ভিত্তি করে কয়েকটি উদাহরণ রয়েছে :

$city_ids = array(1,2,3);
$cities   = $db->getCol("SELECT name FROM cities WHERE is IN(?a)", $city_ids);

আপনার PDO এর সাথে প্রয়োজনীয় পরিমাণের কোডের সাথে এটি একটি একক লাইনের সাথে তুলনা করুন ।
তারপরে আপনার কাঁচা মাইস্ক্লি প্রস্তুত বিবৃতিগুলির সাথে পাগল পরিমাণ কোডের সাথে তুলনা করুন । নোট করুন যে ত্রুটিটি পরিচালনা, প্রোফাইলিং, ক্যোয়ারী লগিং ইতিমধ্যে অন্তর্নির্মিত এবং চলছে।

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

এটিকে সাধারণ পিডিও সন্নিবেশগুলির সাথে তুলনা করুন, যখন প্রতিটি একক ক্ষেত্রের নামটি ছয় থেকে দশ বার পুনরাবৃত্তি করা হয় - এই সমস্ত নামকরা স্থানধারক, বাইন্ডিংস এবং কোয়েরি সংজ্ঞাতে।

আরেকটি উদাহরণ:

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

এই জাতীয় ব্যবহারিক কেস পরিচালনা করতে আপনি PDO এর পক্ষে খুব কমই উদাহরণ খুঁজে পেতে পারেন।
এবং এটি খুব শব্দযুক্ত এবং সম্ভবত অনিরাপদ হবে।

সুতরাং, আরও একবার - এটি কেবল কাঁচা ড্রাইভারই আপনার উদ্বেগ নয়, তবে অ্যাবস্ট্রাকশন ক্লাস হওয়া উচিত, এটি কেবল শিক্ষানবিসের ম্যানুয়াল থেকে নিরীহ উদাহরণগুলির জন্যই নয়, বাস্তব জীবনের সমস্যাগুলির সমাধানের জন্যও কার্যকর।


20
mysql_*দুর্বলতাগুলি খুব সহজেই আসে। যেহেতু পিএইচপি সম্পূর্ণ নবজাতক ব্যবহারকারীদের দ্বারা ব্যবহৃত হয়, mysql_*এটি অনুশীলনে সক্রিয়ভাবে ক্ষতিকারক, এমনকি যদি তাত্ত্বিকভাবে এটি কোনও বাধা ছাড়াই ব্যবহার করা যায়।
মাদারার ঘোস্ট

4
everything is parameterized and safe- এটি প্যারামিটারাইজড হতে পারে তবে আপনার ফাংশনটি আসল প্রস্তুত বিবৃতি ব্যবহার করে না ।
uınbɐɥs

6
Not under active developmentকেবলমাত্র সেই 'মেক-আপ' 0.01% এর জন্য কীভাবে ? আপনি যদি এই স্ট্যান্ড-স্টিল ফাংশন দিয়ে কিছু তৈরি করেন, আপনার মাইএসকিএল-সংস্করণটি এক বছরে আপডেট করুন এবং একটি অ-কার্যক্ষম সিস্টেমের সাথে আপ করুন, আমি নিশ্চিত যে '0.01%' তে হঠাৎ করেই প্রচুর লোক রয়েছে। আমি এটা বলতে চাই deprecatedএবং not under active developmentঘনিষ্ঠভাবে সম্পর্কিত। আপনি বলতে পারেন যে এর জন্য "কোনও [যোগ্য] কারণ নেই" তবে সত্যটি হ'ল বিকল্পগুলির মধ্যে কোনও পছন্দ দেওয়ার সময় আমি no active developmentযতটা খারাপ deprecatedবলি ঠিক ততটা খারাপ ?
Nanne

1
@ মাডারাউচিহ: দুর্বলতাগুলি কীভাবে সহজেই আসে তা আপনি ব্যাখ্যা করতে পারেন? বিশেষত সেই একই ক্ষেত্রে দুর্বলতাগুলি PDO বা MySQLi কে প্রভাবিত করে না ... কারণ আপনি যে কোনও একটির কথা বলছেন তা সম্পর্কে আমি অবগত নই।
একারমেক্সেল

4
@ শ্যাকুইন ট্রিফোনফ: নিশ্চিত, এটি প্রস্তুত বিবৃতি ব্যবহার করে না। তবে দু'টিই পিডিও করে না , যা বেশিরভাগ লোকেরা মাইএসকিউএলআইয়ের উপরে সুপারিশ করে। সুতরাং আমি নিশ্চিত না যে এখানে একটি উল্লেখযোগ্য প্রভাব আছে। উপরের কোডটি (আরও কিছু বিশ্লেষণ সহ) পিডিও হ'ল আপনি যখন ডিফল্টরূপে একটি বিবৃতি প্রস্তুত করেন ...
ircmaxell

97

অনেকগুলি কারণ রয়েছে, তবে সম্ভবত সবচেয়ে গুরুত্বপূর্ণটি হ'ল এই ফাংশনগুলি অনিরাপদ প্রোগ্রামিং অনুশীলনগুলিকে উত্সাহ দেয় কারণ তারা প্রস্তুত বিবৃতি সমর্থন করে না। প্রস্তুত বিবৃতি এসকিউএল ইঞ্জেকশন আক্রমণ রোধ করতে সহায়তা করে।

mysql_*ফাংশনগুলি ব্যবহার করার সময় , আপনাকে ব্যবহারকারী দ্বারা সরবরাহিত পরামিতিগুলি চালাতে হবে mysql_real_escape_string()। আপনি যদি কেবল একটি জায়গায় ভুলে যান বা যদি আপনি কেবল ইনপুটটির কিছু অংশ থেকে পালাতে পারেন তবে আপনার ডাটাবেস আক্রমণে পড়তে পারে।

এগুলিতে তৈরি বিবৃতি ব্যবহার করা PDOবা mysqliএটি তৈরি করা হবে যাতে এই ধরণের প্রোগ্রামিং ত্রুটিগুলি করা আরও কঠিন।


3
দুর্ভাগ্যক্রমে, MySQLi_ * এর পরিবর্তনশীল সংখ্যক প্যারামিটারগুলি পাস করার জন্য দুর্বল সমর্থন (যেমন আপনি যখন কোনও আইএন ধারাতে পরীক্ষা করার জন্য মানগুলির একটি তালিকা পাস করতে চান) প্যারামিটারের অপব্যবহারকে উত্সাহিত করে, ঠিক একই কনটেস্টেড কোয়েরিগুলির ব্যবহারকে উত্সাহিত করে যা মাইএসকিউএল_ * কলগুলি দুর্বল রাখুন।
কিকস্টার্ট

5
তবে, আবারও, নিরাপত্তাহীনতা মাইএসকিএল_ * ফাংশনগুলির অন্তর্নিহিত সমস্যা নয়, তবে ভুল ব্যবহারের সমস্যা।
আগামেমনাস

2
@ অ্যাগামেমনাস সমস্যাটি হ'ল মাইএসকিএল_ * বিশেষত অনভিজ্ঞ প্রোগ্রামারদের ক্ষেত্রে "ভুল ব্যবহার" প্রয়োগ করা সহজ করে তোলে। প্রস্তুত বিবৃতি কার্যকর করে এমন গ্রন্থাগারগুলি এ ধরণের ত্রুটি করা আরও কঠিন করে তোলে।
ট্রট

75

কারণ (অন্যান্য কারণে) ইনপুট ডেটা স্যানিটাইজ করা হয়েছে তা নিশ্চিত করা আরও শক্ত। আপনি যদি প্যারামিট্রাইজড ক্যোয়ারী ব্যবহার করেন, যেমন কেউ পিডিও বা মাইএসকিলি দিয়ে থাকে আপনি পুরোপুরি ঝুঁকি এড়াতে পারবেন।

উদাহরণ হিসাবে, কেউ "enhzflep); drop table users"ব্যবহারকারীর নাম হিসাবে ব্যবহার করতে পারে । পুরানো ফাংশনগুলি ক্যোয়ারী অনুসারে একাধিক বিবৃতি কার্যকর করতে মঞ্জুরি দেয়, সুতরাং সেই দুষ্টু বাগের মতো কিছু পুরো টেবিলটি মুছতে পারে।

যদি কেউ মাইএসকিলির পিডিও ব্যবহার করে তবে ব্যবহারকারীর নামটি শেষ হয়ে যাবে "enhzflep); drop table users"

ববি টেবিল ডট কম দেখুন ।


10
The old functions will allow executing of multiple statements per query- না, তারা করবে না। এই জাতীয় ইনজেকশন এক্সট্রা / মাইএসকিএল দিয়ে সম্ভব নয় - মাইএসকিউএল এবং mysqli_multi_query()ফাংশনটি ব্যবহার করার সময় পিএইচপি এবং মাইএসকিউএল দিয়ে এই ধরণের ইনজেকশন সম্ভব the Ext / mysql এবং unescaped স্ট্রিংয়ের সাহায্যে যে ধরনের ইনজেকশন সম্ভব তা হ'ল এমন ' OR '1' = '1তথ্য যা ডাটাবেস থেকে ডেটা বের করার মতো যা অ্যাক্সেসযোগ্য নয়। নির্দিষ্ট পরিস্থিতিতে সাব-কোয়েরি ইনজেকশন করা সম্ভব, তবে এখনও এইভাবে ডাটাবেসটি সংশোধন করা সম্ভব নয়।
ডেভর্যান্ডম

64

এই উত্তরটি দুর্বল লিখিত পিএইচপি ব্যবহারকারী-যাচাইকরণ কোডটি বাইপাস করা, এই আক্রমণগুলি কীভাবে (এবং কী ব্যবহার করছে) এবং কীভাবে একটি নিরাপদ প্রস্তুত বিবৃতি দিয়ে পুরানো মাইএসকিউএল ফাংশনগুলি প্রতিস্থাপন করতে পারে - এবং মূলত, কেন স্ট্যাকওভারফ্লো ব্যবহারকারীরা তা দেখানোর জন্যই এই উত্তরটি লেখা হয়েছে (সম্ভবত প্রচুর প্রতিনিধি সহ) নতুন ব্যবহারকারীদের কোড উন্নত করার জন্য প্রশ্ন জিজ্ঞাসা করছে bar

প্রথমে, দয়া করে এই পরীক্ষাটি মাইএসকিএল ডাটাবেস তৈরি করতে নির্দ্বিধায় (আমি খনি প্রস্তুতি বলেছি):

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)

এটি হয়ে গেলে, আমরা আমাদের পিএইচপি কোডে যেতে পারি।

নীচের স্ক্রিপ্টটি কোনও ওয়েবসাইটের প্রশাসকের যাচাইকরণ প্রক্রিয়াটি ধরে নেওয়া যাক (সরলীকৃত তবে যদি আপনি এটি অনুলিপি করে পরীক্ষার জন্য ব্যবহার করেন):

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

প্রথম নজরে বৈধতা যথেষ্ট বলে মনে হচ্ছে।

ব্যবহারকারীর একটি লগইন এবং পাসওয়ার্ড লিখতে হবে, তাই না?

উজ্জ্বল, নিম্নলিখিতটিতে প্রবেশ করবেন না:

user: bob
pass: somePass

এবং এটি জমা দিন।

আউটপুট নিম্নরূপ:

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

সুপার! প্রত্যাশিত হিসাবে কাজ করা, এখন আসল ব্যবহারকারীর নাম এবং পাসওয়ার্ড চেষ্টা করে দেখুন:

user: Fluffeh
pass: mypass

অ্যামেজিং! চারদিকে হাই-ফাইভস, কোডটি একটি প্রশাসককে সঠিকভাবে যাচাই করেছে। এইটা ঠিক আছে!

সত্যিই ভাল না. আসুন বলুন যে ব্যবহারকারী একজন চালাক ছোট ব্যক্তি। বলুন ব্যক্তিটি আমি।

নিম্নলিখিত প্রবেশ করান:

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

এবং আউটপুটটি হ'ল:

The check passed. We have a verified admin!

অভিনন্দন, আপনি আমাকে কেবলমাত্র নিজের সুপার-সুরক্ষিত প্রশাসকদের প্রবেশের অনুমতি দিয়েছিলেন কেবলমাত্র আমার সাথে একটি মিথ্যা ব্যবহারকারী নাম এবং একটি ভুয়া পাসওয়ার্ড প্রবেশ করানো। সিরিয়াসলি, যদি আপনি আমাকে বিশ্বাস না করেন তবে আমার দেওয়া কোডটি দিয়ে ডেটাবেস তৈরি করুন এবং এই পিএইচপি কোডটি চালান - যা এক নজরে ব্যবহারকারীর নাম এবং পাসওয়ার্ডটি খুব সুন্দরভাবে যাচাই করে বলে মনে হচ্ছে।

সুতরাং, উত্তরে, এটি আপনি কেন বিক্রি হচ্ছে।

সুতরাং, কী কী ভুল হয়েছে এবং কীভাবে আমি কেবলমাত্র আপনার সুপার-অ্যাডমিন-কেবল-ব্যাট-গুহায় প্রবেশ করেছি তা একবার দেখে নেওয়া যাক। আমি একটি অনুমান নিয়েছিলাম এবং ধরে নিয়েছি যে আপনি আপনার ইনপুটগুলির প্রতি যত্নবান হন নি এবং সরাসরি এগুলি সরাসরি ডাটাবেসে পৌঁছে দিয়েছিলেন। আমি ইনপুটটি এমনভাবে তৈরি করেছি যাতে আপনি যে ক্যোয়ারীটি চালিয়ে যাচ্ছেন তা বদলাবে। সুতরাং, এটি কী হওয়ার কথা ছিল এবং এটি কী ছিল?

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

এটাই ক্যোয়ারী, তবে আমরা যখন ব্যবহার করি আসল ইনপুটগুলির সাথে ভেরিয়েবলগুলি প্রতিস্থাপন করি, তখন আমরা নিম্নলিখিতটি পাই:

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

দেখুন কীভাবে আমি আমার "পাসওয়ার্ড" তৈরি করেছি যাতে এটি পাসওয়ার্ডের চারপাশে একক উদ্ধৃতিটি বন্ধ করে দেয়, তারপরে সম্পূর্ণ নতুন তুলনাটি উপস্থাপন করবে? তারপরে কেবল সুরক্ষার জন্য, আমি আরও একটি "স্ট্রিং" যুক্ত করেছি যাতে একক উদ্ধৃতিটি আমাদের মূল কোডটিতে প্রত্যাশা অনুযায়ী বন্ধ হয়ে যায়।

যাইহোক, এটি এখন লোকেরা আপনাকে চিত্কার করার বিষয়ে নয়, এটি আপনাকে কীভাবে আপনার কোডটিকে আরও সুরক্ষিত করা যায় তা দেখানোর বিষয়ে।

ঠিক আছে, তাহলে কী ভুল হয়েছে, এবং আমরা কীভাবে এটি ঠিক করতে পারি?

এটি একটি ক্লাসিক এসকিউএল ইঞ্জেকশন আক্রমণ। এই বিষয়টির জন্য সহজতম একটি। আক্রমণকারী ভেক্টরগুলির স্কেলে, এটি একটি টডল যা একটি ট্যাঙ্কে আক্রমণ করে - এবং জয়লাভ করে।

সুতরাং, কীভাবে আমরা আপনার পবিত্র প্রশাসক বিভাগটি সুরক্ষা করব এবং এটিকে সুন্দর এবং সুরক্ষিত করব? প্রথম কাজটি হ'ল সত্যিকারের পুরানো এবং অবহেলা করা mysql_*ফাংশনগুলি ব্যবহার বন্ধ করা । আমি জানি, আপনি যে টিউটোরিয়ালটি অনলাইনে খুঁজে পেয়েছিলেন তা অনুসরণ করেছিলেন এবং এটি কার্যকর হয়, তবে এটি পুরানো, এটি পুরানো এবং কয়েক মিনিটের ব্যবধানে, আমি কোনও ঘাম না ভেঙে কেবল এটিকে ভেঙে ফেলেছি।

এখন, আপনার কাছে mysqli_ বা PDO ব্যবহারের আরও ভাল বিকল্প রয়েছে । আমি ব্যক্তিগতভাবে PDO- র একটি বড় অনুরাগী, তাই এই উত্তরটির বাকি অংশগুলিতে আমি PDO ব্যবহার করব। প্রো এবং কন এর আছে, কিন্তু ব্যক্তিগতভাবে আমি দেখতে পেলাম যে প্রো এর কনসের তুলনায় অনেক বেশি। এটি একাধিক ডাটাবেস ইঞ্জিন জুড়ে পোর্টেবল - আপনি মাইএসকিউএল বা ওরাকল ব্যবহার করছেন বা রক্তাক্ত যে কোনও বিষয়েই ব্যবহার করছেন - কেবল সংযোগের স্ট্রিং পরিবর্তন করে, এতে আমরা ব্যবহার করতে চাই এমন সমস্ত অভিনব বৈশিষ্ট্য রয়েছে এবং এটি সুন্দর এবং পরিষ্কার clean আমি পরিষ্কার পছন্দ করি।

এখন, আবার সেই কোডটি একবার দেখে নেওয়া যাক, এবার PDO অবজেক্ট ব্যবহার করে লেখা হয়েছে:

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

প্রধান পার্থক্য হ'ল আর কোনও mysql_*কার্যকারিতা নেই। এটি একটি PDO অবজেক্টের মাধ্যমে সম্পন্ন হয়েছে, দ্বিতীয়ত, এটি প্রস্তুত বিবৃতি ব্যবহার করছে। এখন, আপনি জিজ্ঞাসা একটি প্রস্তুত বিবৃতি কি? কোয়েরি চালানোর আগে এটি ডাটাবেসকে বলার একটি উপায়, ক্যোয়ারীটি কী যে আমরা চালাতে যাচ্ছি। এই ক্ষেত্রে, আমরা ডাটাবেসকে বলি: "হাই, আমি টেবিল ব্যবহারকারীদের আইডি, ইউজারিড এবং পাসের জন্য একটি নির্বাচনী স্টেটমেন্ট চালাচ্ছি যেখানে ইউজারিড একটি পরিবর্তনশীল এবং পাসটিও একটি চলক" "

তারপরে এক্সিকিউট স্টেটমেন্টে আমরা ডাটাবেসটিকে সমস্ত ভেরিয়েবলের সাথে অ্যারে পাস করি যা এটি এখন প্রত্যাশা করে।

ফলাফল চমত্কার। আবার সেই ব্যবহারকারী নাম এবং পাসওয়ার্ড সংমিশ্রণগুলি আবার চেষ্টা করে দেখুন:

user: bob
pass: somePass

ব্যবহারকারী যাচাই করা হয়নি। অসাধারণ.

কেমন:

user: Fluffeh
pass: mypass

ওহ, আমি কিছুটা উত্তেজিত হয়েছি, এটি কাজ করেছে: চেকটি পাস হয়েছে। আমাদের একটি যাচাইকৃত অ্যাডমিন রয়েছে!

এখন, একটি চতুর চ্যাপটি আমাদের সামান্য যাচাইকরণ সিস্টেমটি পাস করার চেষ্টা করার জন্য প্রবেশ করতে পারে এমন ডেটা চেষ্টা করতে দিন:

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

এবার, আমরা নিম্নলিখিত পেতে:

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

এই কারণেই প্রশ্ন পোস্ট করার সময় আপনাকে চিৎকার করা হচ্ছে - এটি কারণ লোকেরা দেখতে পাচ্ছে যে এমনকি আপনার কোডকেও চেষ্টা করে বাইপাস করা যায়। দয়া করে, আপনার কোডটি উন্নত করতে, এটি আরও সুরক্ষিত করতে এবং বর্তমানের ফাংশনগুলি ব্যবহার করতে এই প্রশ্নটি এবং উত্তরটি ব্যবহার করুন।

শেষ অবধি, এটি এটি নিখুঁত কোড বলে তা নয়। এটি আরও উন্নত করতে আপনি আরও অনেকগুলি কাজ করতে পারেন, উদাহরণস্বরূপ হ্যাশ পাসওয়ার্ড ব্যবহার করুন, নিশ্চিত করুন যে আপনি যখন ডেটাবেসে সংবেদনশীল তথ্য সংরক্ষণ করবেন, আপনি এটি সরল পাঠ্যে সংরক্ষণ করবেন না, যাচাইয়ের একাধিক স্তর রেখেছেন - তবে সত্যই, যদি আপনি কেবল আপনার পুরানো ইনজেকশন প্রোন কোডটিকে এটিতে পরিবর্তন করেছেন, ভাল কোড লেখার পথে আপনি ভাল থাকবেন - এবং আপনি যে এখনও পর্যন্ত অর্জন করেছেন এবং এখনও পড়ছেন তা আমাকে এই আশ্বাস দেয় যে আপনি কেবল এই ধরণের প্রয়োগ করবেন না আপনার ওয়েবসাইট এবং অ্যাপ্লিকেশনগুলি লেখার সময় কোডের কোড, তবে আপনি বাইরে গিয়ে আমার সবেমাত্র উল্লিখিত অন্যান্য জিনিসগুলি নিয়ে গবেষণা করতে পারেন - এবং আরও অনেক কিছু। সর্বাধিক কার্যকর কোডগুলি যা আপনি করতে পারেন সর্বাধিক কোড লিখুন ly


2
আপনার উত্তর করার জন্য আপনাকে ধন্যবাদ! আমার +1 আছে! এটি লক্ষণীয় যে mysql_*এটি নিজেই অনিরাপদ নয়, তবে এটি খারাপ টিউটোরিয়ালের মাধ্যমে এবং সুরক্ষিত এপিআই-র সঠিক বিবরণীর অভাবে অনিরাপদ কোডের প্রচার করে।
মাদারার ঘোস্ট

2
অপরিবর্তিত পাসওয়ার্ড, ওরে হরর! = oP অন্যথায় +1 বিস্তারিত ব্যাখ্যার জন্য
ক্রিপ্টিক ツ

33

মাইএসকিউএল এক্সটেনশানটি এই তিনটির মধ্যে প্রাচীনতম এবং এটি মূল উপায়টি ছিল যে বিকাশকারীরা মাইএসকিউএল এর সাথে যোগাযোগের জন্য ব্যবহৃত হত। এই এক্সটেনশনটি এখন পিএইচপি এবং মাইএসকিউএল উভয়েরই নতুন রিলিজে উন্নতির কারণে অন্য দুটি বিকল্পের পক্ষে অবহেলা করা হচ্ছে ।

  • MySQLi মাইএসকিউএল ডাটাবেস সঙ্গে কাজ করার জন্য 'উন্নত' এক্সটেনশান। এটি মাইএসকিউএল সার্ভারের নতুন সংস্করণগুলিতে উপলভ্য এমন বৈশিষ্ট্যগুলির সুবিধা গ্রহণ করে, বিকাশকারীকে একটি ফাংশন-ওরিয়েন্টেড এবং অবজেক্ট-ওরিয়েন্টেড ইন্টারফেস উভয়ই প্রকাশ করে এবং কিছু অন্যান্য নিফটি জিনিস করে।

  • পিডিও এমন একটি এপিআই সরবরাহ করে যা বেশিরভাগ কার্যকারিতা সংহত করে যা পূর্বে প্রধান ডাটাবেস অ্যাক্সেস এক্সটেনশানগুলির মধ্যে ছড়িয়ে পড়েছিল, যেমন মাইএসকিউএল, পোস্টগ্র্রেএসকিউএল, এসকিউলাইট, এমএসএসকিউএল ইত্যাদি। ইন্টারফেস প্রোগ্রামারটির জন্য ডেটাবেস সংযোগ, কোয়েরি এবং কাজ করার জন্য উচ্চ-স্তরের অবজেক্টগুলিকে প্রকাশ করে ফলাফল সেট, এবং নিম্ন-স্তরের ড্রাইভারগুলি ডাটাবেস সার্ভারের সাথে যোগাযোগ এবং সংস্থান হ্যান্ডলিং সম্পাদন করে। প্রচুর আলোচনা এবং কাজ পিডিওতে চলেছে এবং এটি আধুনিক, পেশাদার কোডে ডাটাবেসের সাথে কাজ করার উপযুক্ত পদ্ধতি হিসাবে বিবেচিত হয়।


21

আমি উপরের উত্তরগুলি সত্যই দীর্ঘায়িত দেখতে পাই, তাই সংক্ষেপে:

মাইসকিলি এক্সটেনশনের বেশ কয়েকটি সুবিধা রয়েছে, যা মাইএসকিএল এক্সটেনশনের মূল বর্ধনসমূহ:

  • অবজেক্ট-ওরিয়েন্টেড ইন্টারফেস
  • প্রস্তুত বিবৃতি জন্য সমর্থন
  • একাধিক বিবৃতি জন্য সমর্থন
  • লেনদেনের জন্য সমর্থন
  • বর্ধিত ডিবাগিং ক্ষমতা
  • এম্বেড করা সার্ভার সমর্থন

উত্স: মাইএসকিউএলআই ওভারভিউ


উপরের উত্তরে বর্ণিত হিসাবে, মাইএসকিএল-এর বিকল্পগুলি হ'ল মাইএসকিলি এবং পিডিও (পিএইচপি ডেটা অবজেক্টস)।

  • এপিআই সার্ভার-সাইড প্রস্তুত বিবৃতিগুলি সমর্থন করে: এমওয়াইএসকিউএলআই এবং পিডিও দ্বারা সমর্থিত
  • এপিআই ক্লায়েন্টের পক্ষের প্রস্তুত বিবৃতিগুলি সমর্থন করে: কেবল পিডিও দ্বারা সমর্থিত
  • এপিআই স্টোরড পদ্ধতিগুলিকে সমর্থন করে: মাইএসকিউএল এবং পিডিও উভয়ই
  • এপিআই একাধিক বিবৃতি এবং সমস্ত মাইএসকিউএল 4.1+ কার্যকারিতা সমর্থন করে - মাইএসকিউএলি দ্বারা সমর্থিত এবং বেশিরভাগ পিডিও দ্বারা সমর্থিত

মাইএসকিউএল এবং পিডিও উভয়ই পিএইচপি 5.0 তে চালু হয়েছিল, যেখানে মাইএসকিউএল পিএইচপি 3.0 এর আগে চালু হয়েছিল। লক্ষ্য করার মতো বিষয় হ'ল মাইএসকিউএল পিএইচপি 5.x এর অন্তর্ভুক্ত রয়েছে যদিও পরবর্তী সংস্করণগুলিতে হ্রাস পেয়েছে।


2
আপনার উত্তরটি খুব দীর্ঘ, যদিও আসল সংক্ষিপ্তসারটি "mysql ext আর হয় না" more সব কিছুই
আপনার সাধারণ অনুভূতি

1
@YourCommonSense আমার উত্তর হ'ল মাইএসকিলি কেন মাইএসকিএল প্রতিস্থাপন করেছে। বলার অপেক্ষা রাখে না যে আজ মাইস্কুলির অস্তিত্ব আছে তাই এটি ব্যবহার করুন .. এটা সবাই জানেন!
আনি মেনন

1
ঠিক আছে, এ ছাড়াও যে কেউ জিজ্ঞাসা করেনি কেন মাইএসকিলি মাইএসকিএল প্রতিস্থাপন করেছে, এটিও এই প্রশ্নের উত্তর দেয় না। এটি মাইএসকিলি কেন চালু হয়েছিল তার উত্তর দেয়। তবে এটি ব্যাখ্যা করে না যে কেন মাইএসকিএল এবং মাইএসকিলিকে সমান্তরালভাবে বসবাস করতে দেওয়া হয়নি
আপনার সাধারণ অনুভূতি

@ ইওরকমমনসেন্স এছাড়াও ওপি-র প্রশ্ন "আমার সাইটে কাজ করা সত্ত্বেও কেন আমি অন্য কিছু ব্যবহার করব?" এবং সেই কারণেই আমি পরিবর্তনগুলি এবং উন্নতিগুলিকে নির্দেশ করেছি। আপনি দীর্ঘ অন্য সমস্ত উত্তরগুলি দেখতে পারেন তাই আমি ভেবেছিলাম এটির সংক্ষিপ্ত বিবরণ দেওয়া উচিত।
আনি মেনন

6

mysql_*মাইএসকিলি বা পিডিও ব্যবহার করে প্রায় সমস্ত ফাংশন সংজ্ঞায়িত করা সম্ভব । এগুলি কেবল আপনার পুরানো পিএইচপি অ্যাপ্লিকেশনের শীর্ষে অন্তর্ভুক্ত করুন এবং এটি পিএইচপি 7 এ কাজ করবে। আমার সমাধান এখানে

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

আপনার সমাধানের জন্য লিঙ্ক দেখানোর পরিবর্তে, দয়া করে তাদের উত্তর হিসাবে এখানে যুক্ত করুন।
অমরনাথ

1

ফাংশন যা এই অনুরূপ হিসাবে mysql_connect(), mysql_query()টাইপ পূর্ববর্তী সংস্করণ পিএইচপি অর্থাত (পিএইচপি 4) ফাংশন এবং এখন ব্যবহার না হয়।

এই দ্বারা প্রতিস্থাপিত হয় mysqli_connect(), mysqli_query()একইভাবে সর্বশেষ PHP5 হবে।

এই ত্রুটির পিছনে কারণ।


2
পিএইচপি 5 এখন 2 বছরেরও বেশি সময় সর্বশেষ হয়নি।
মাদারার ঘোস্ট

1

মাইএসকিউএল পিএইচপি 5.5.0 এ হ্রাস পেয়েছে এবং পিএইচপি 7.0.0 এ সরানো হয়েছে। একটি বড় এবং পুরানো অ্যাপ্লিকেশনটির জন্য, প্রতিটি ফাংশন অনুসন্ধান এবং প্রতিস্থাপন করা কঠিন।

আমরা নীচে প্রতিটি চলমান কোড চলমান জন্য একটি মোড়ক ফাংশন তৈরি করে মাইএসকিউএল ফাংশন ব্যবহার করতে পারি। এখানে ক্লিক করুন


-9

mysql_ * ফাংশনগুলি আরও ভাল ফাংশন এবং কোড স্ট্রাকচার ডেভলপ করা হয়েছে এই সত্যের ভিত্তিতে ( পিএইচপি 5.5 হিসাবে ) অবচিত করা হয়েছিল। ফাংশনটি অবহেলা করা হয়েছে এর অর্থ এই যে পারফরম্যান্স এবং সুরক্ষার দিক থেকে এটির উন্নতি করার জন্য আর কোনও প্রচেষ্টা করা হবে না, যার অর্থ এটি ভবিষ্যতের কম প্রমাণ

আপনার আরও কারণের প্রয়োজন হলে:

  • mysql_ * ফাংশন প্রস্তুত বিবৃতি সমর্থন করে না।
  • mysql_ * ফাংশনগুলি পরামিতিগুলির বাঁধাই সমর্থন করে না।
  • mysql_ * ফাংশনগুলির অবজেক্ট ওরিয়েন্টেড প্রোগ্রামিংয়ের কার্যকারিতার অভাব রয়েছে।
  • তালিকাটি চলছে ...

18
এই উত্তরটি পুরানো। তদ্ব্যতীত, এটি ইতিমধ্যে বিদ্যমান উত্তরগুলিতে দরকারী কিছু যুক্ত করে না।
আপনার সাধারণ অনুভূতি
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.