هنگامی که قصد داریم در PHP به یک پایگاه داده دسترسی داشته باشیم، برای ما دو راه وجود دارد:MySQLi و PDO. بنابراین چه چیزهایی را قبل از انتخاب یکی از اینها باید دانست؟ تفاوت ها، پشتیبانی از پایگاه داده، پایداری و نگرانی هایی که در این پست ذکر می شود.

 

خلاصه

 

نوعPODMySQLi
پشتیبانی از پایگاه داده 12 درایور مختلف فقط MySQL
API شی گرا شی گرا + رویه ای
ارتباط ساده ساده
نام پارامترها بله خیر
نقشه برداری شی بله بله
اظهارات آماده بله خیر
کارایی بللل سریع
روش های ذخیره کردن بله بله

 


 

ارتباط

برای ارتباط با دیتابیس، باید روش های زیر بصورت سهولت انتخاب شود:


// PDO
$pdo=newPDO("mysql:host=localhost;dbname=database",'username','password');
 
// mysqli, procedural way
$mysqli=mysqli_connect('localhost','username','password','database');
 
// mysqli, object oriented way
$mysqli=newmysqli('localhost','username','password','database');
 
 


توجه داشته باشید که از این ارتباط ها (connection) و منابع (resources) در ادامه ی آموزش استفاده می شود.

 

پشتیبانی از API

هر دوی PDO و MySQLi در واقع API های شی گرا ارائه می دهند، اما MySQLi همچنین API های رویه ای نیز ارائه می دهد. – که باعث می شود برای تازه واردان درکش آسان باشد. اگر شما با درایور های PHP MySQL آشنا باشید، خواهید دید که مهاجرت به MySQLi رویه ای چقدر آسان است. از سوی دیگر، هنگامی که شما در PDO استاد شدید، می توانید به راحتی از آن با هر دیتابیسی که میلتان است استفاده کنید!

 

پشتیبانی از پایگاه داده

 

 

مزیت اصلی PDO نسبت به MySQLi در پشتیبانی از درایور دیتابیس است. در این لحظه که در حال نوشتن این پست هستم، PDO از 12 درایور مختلف پشتیبانی می کند، MySQLi هم تنها از MySQLپشتیبانی می کند.

برای چاپ یک لیست از تمام درایورهایی که PDO در حال حاظر از آنها پشتیبانی می کند، از کد زیر استفاده کنید:

 

نام پارامترها 

این یکی دیگر از ویژگی ها مهمی است که PDO دارد. پارامترهای اتصال بطور قابل توجهی ساده تر از استفاده از اتصال عددی:

$params=array(':username'=>'test',':email'=>$mail,':last_login'=>time()-3600);
    
$pdo->prepare('
    SELECT * FROM users
    WHERE username = :username
    AND email = :email
    AND last_login > :last_login');
    
$pdo->execute($params);
 


… نسبت به روش MySQLi است:


$query=$mysqli->prepare('
    SELECT * FROM users
    WHERE username = ?
    AND email = ?
    AND last_login > ?');
    
$query->bind_param('sss','test',$mail,time()-3600);
$query->execute();

 

شاید با دیدن پارامتر علامت سوال فکر کنید این راه کوتاه تری است، اما نسبت به نام پارامترها انعطاف پذیری ندارد. با توجه به این واقعیت که توسعه دهنده ها همیشه باید ترتیب پارامترها را نگه دارند، در برخی از شرایط قابل هک می باشد.

متاسفانه، MySQLi از نام پارمترها پشتیبانی نمی کند.

 

نقشه برداری شی

هر دوی PDO و MySQLi می توانند نتایج را به شی تبدیل کنند. این وقتی می آید که شما نمی خواهید از یک لایه ی انتزاعی پایگاه داده سفارشی استفاده کنید، در حالی که می خواهید رفتارش شبیه به ORMباشد. فرض کنید که ما یک کلاس User داریم که تعدای خواص (properties) دارد، که نام فیلد ها از یک دیتابیس انتخاب شده است:


  
  classUser{
      public $id;
      public $first_name;
      public $last_name;
      
      publicfunctioninfo()
      {
          return '#'.$this->id.': '.$this->first_name.' '.$this->last_name;
      }
  }

بدون نقشه برداری شی، ما نیاز داریم که مقدار هر فیلد را قبل از اینکه بتوانیم از متد ()info به درستی استفاده کنیم پر کنیم (یا به صورت دستی و یا از طریق سازنده).

این به ما اجاره می دهد که این خواص را قبل از اینکه شی از روی آنها ساخته شود از قبل تعریف کنیم، به عنوان مثال:

 


  
  $query = "SELECT id, first_name, last_name FROM users";
      
  // PDO
  $result =$pdo->query($query);
  $result->setFetchMode(PDO::FETCH_CLASS,'User');
   
  while($user=$result->fetch()){
      echo$user->info()."\n";
  }
  // MySQLI, procedural way
  if ($result=mysqli_query($mysqli,$query)){
      while ($user=mysqli_fetch_object($result,'User')){
          echo $user->info()."\n";
      }
  }
  // MySQLi, object oriented way
  if($result=$mysqli->query($query)){
      while($user=$result->fetch_object('User')){
          echo$user->info()."\n";
      }
  }

 

امنیت

 

بیایید فرض کنیم که یک هکر می خواهد تعدادی SQL مخرب از طریق پارامتر username وارد تزریق کند:


$_GET['username']="'; DELETE FROM users; /*"

اگر ما در این بخش شکست بخورم، هکر می تواند query هایی مخرب مثل پاک کردن تمام رکورد های جدول users وارد کند (هر دوی PDO و MySQLi از query های چندگانه پشتیبانی می کنند).


  // PDO, "manual" escaping
  $username=PDO::quote($_GET['username']);
   
  $pdo->query("SELECT * FROM users WHERE username = $username");
          
  // mysqli, "manual" escaping
  $username=mysqli_real_escape_string($_GET['username']);
   
  $mysqli->query("SELECT * FROM users WHERE username = '$username'");

همانطور که می بینید، ()PDO::quote نه تنها از رشته ها فرار (escape) می کند، بلکه آنها را نقل قول هم می کند. از طرف دیگر، ()mysqli_real_escape_string تنها از رشته ها فرار می کند; شما نیاز دارید که بطور دستی روش نقل قول را اعمال کنید.


  // PDO, prepared statement
  $pdo->prepare('SELECT * FROM users WHERE username = :username');
  $pdo->execute(array(':username'=>$_GET['username']));
   
  // mysqli, prepared statements
  $query=$mysqli->prepare('SELECT * FROM users WHERE username = ?');
  $query->bind_param('s',$_GET['username']);
  $query->execute();

من پیشنهاد می کنم که همیشه از دستورات آماده با پرس و جوی محدود بجای ()PDO::quote و()mysqli_real_escape_string استفاده کنید.

 

کارایی

در حالی که هر دوی PDO و MySQLi سریع هستند، MySQLi به طور قابل توجهی در معیار سریع تر است – %2.5~ برای دستورات غیر آماده، و %6.5~ برای آنهایی که آماده است. با این حال، MySQLخالص حتی از این دو هم سریع تر است. بنابراین اگر شما واقعا زیر فشار هر زمان از عملکر هستید، پس این چیزی است که باید در نظر داشته باشید.

 

خلاصه

در نهایت، PDO برنده ی این مسابقه می شود. با پشتیبانی از 12 درایور مختلف دیتابیس، (18 درایور مختلف دیتابیس!)، نام پارامترها، می توانیم عملکرد های کوچک را نادیده بگیریم و API ها. از نقطه نظر امنیتی، هر دوی آنها امن هستند تا زمانی که یک توسعه دهنده قرار است از آنها در راهی استفاده کند. بنابراین اگر هنوز از MySQLi استفاده می کنید، شاید زمان تغییر است.

آیا این پاسخ به شما کمک کرد؟ 41 کاربر این را مفید یافتند (84 نظرات)