آموزش PDO در PHP برای اتصال ایمن به دیتابیس

روش PDO جدیدترین روش اتصال به دیتابیس در PHP است. با PDO می‌توانیم به انواع مختلف دیتابیس متصل شویم. همچنین یکسری بررسی‌های امنیتی در هنگام اجرای کوئری‌ها انجام می‌دهد. در این آموزش با نحوه استفاده از PDO در PHP آشنا می‌شویم و ۶ متد کاربردی آن را یاد می‌گیریم.

برای کار با دیتابیس در PHP آموزش جامعی داریم که روند کلی و جزئیات اتصال به پایگاه داده را با هم بررسی کردیم. در آنجا از روش mysqli استفاده کردم که مخصوص برقراری ارتباط با دیتابیس‌های mysql است.

از روش PDO علاوه بر MySQL برای اتصال به چندین نوع پایگاه داده دیگر نیز استفاده می‌شود. مثلاً می‌توانیم به دیتابیس PostgreSQL، MS SQL Server یا دیتابیس Oracle متصل شویم. البته برای اتصال به هر دیتابیس، باید درایور مخصوص به آن در سرور ما نصب شده باشد.

این روش فقط به صورت شئ گرا قابل استفاده است و با راهکارهای امنیتی که به ما می‌دهد به بهبود امنیت اسکریپت PHP کمک می‌کند.

توضیحات بیشتری در مورد PDO در PHP نمی‌دهم که سریع‌تر شروع به کار کنیم. اگر علاقمند بودید ملزومات یا اطلاعات بیشتری بدانید، به مستندات و منابعی که در انتها اشاره می‌کنم مراجعه کنید.

اتصال به دیتابیس با PDO

می‌دانیم که در برنامه‌نویسی شی گرا، باید ابتدا یک شی از کلاس‌ها بسازیم. بنابراین برای ایجاد یک شئ PDO مشابه زیر عمل می‌کنیم:

<?php
$conn = new PDO();

متد سازنده PDO چهار ورودی می‌گیرد که باید سه تای اول را مشخص کنیم. پارامتر اول، هاست (آدرس سرور دیتابیس) و در صورت نیاز نام دیتابیس را مشخص می‌کند. البته می‌توانیم اطلاعات دیگری نیز در این رشته متنی PHP تعیین کنیم.

پارامتر دوم و سوم، نام کاربری و رمز عبور اتصال به سرور دیتابیس را مشخص می‌کند. پارامتر چهارم نیز یک آرایه PHP کلید مقدار است که تنظیمات بیشتر مرتبط با درایور را تعیین می‌کند.

من در این آموزش به سرور localhost و پایگاه داده sabzdanesh متصل می‌شوم. قاعدتاً شما باید این اطلاعات و اطلاعات کاربری را با مقادیر مناسب خودتان جایگزین کنید. مثلاً اگر از زمپ استفاده می‌کنید، برای پارامتر پسورد، فقط یک رشته خالی قرار دهید. (کاربر root در زمپ پسورد ندارد.)

<?php
$conn = new PDO( "mysql:host=localhost;dbname=sabzdanesh", "username", "password" );

اگر به ساختار رشته ورودی اول دقت کنید، در ابتدا نوع دیتابیس را مشخص کرده‌ام. در اینجا از mysql استفاده می‌کنیم. اگر قرار است از نوع دیگری استفاده کنید، فرمت رشته را باید متناسب با درایور آن انتخاب کنید.

بعد از نوع دیتابیس، آدرس host و نام database را مشخص کرده‌ام. اگر هنوز دیتابیسی ایجاد نکرده‌اید، می‌توانید بخش دوم که dbname است را موقتاً در رشته قرار ندهید تا صرفاً به سرور پایگاه داده متصل شوید.

مدیریت خطای PDO

اگر به هر دلیلی امکان برقراری ارتباط با سرور دیتابیس وجود نداشته باشد، قطعه کد بالا موجب یک خطای مهلک (fatal) شده و اجرای اسکریپت متوقف می‌شود. برای مدیریت این خطا، می‌توانیم از مدیریت استثنا در PHP استفاده کنیم.

<?php
try {
    $conn = new PDO( "mysql:host=localhost;dbname=sabzdanesh", "username", "password" );
    echo "با موفقیت متصل شد.";
} catch(PDOException $e) {
    echo "خطایی به وجود آمده: " . $e->getMessage();
}
?>
مدیریت استثنا در PHP با try catch

مدیریت استثنا در PHP با try catch

اجرای دستورهای PDO در PHP

برای اجرای دستورها در روش PDO متدهای مختلفی در اختیار داریم که بنا به نیازمان از آن‌ها استفاده می‌کنیم. در این آموزش با سه متد اصلی و پرکاربرد آشنا می‌شویم.

اولین متد، متد exec() است. این متد یک پارامتر ورودی به صورت string گرفته و آن را در دیتابیس اجرا می‌کند. به عنوان خروجی، تعداد سطرها (رکوردهای) تحت تأثیر قرار گرفته در دیتابیس را به ما می‌دهد. پس از این متد نمی‌توان برای واکشی (خواندن اطلاعات از دیتابیس با PDO) استفاده کرد.

مثلاً با دستور زیر، charset کانکشن را روی utf8 تنظیم می‌کنم:

<?php
$conn->exec( "set names utf8" );

البته می‌توان دستورهایی مثل حذف از دیتابیس را نیز اجرا کرد؛ برای مثال:

$row_affected = $conn->exec("DELETE from logs");

اجرای کوئری با PDO

یکی از دستورهای پرکاربر در کار با دیتابیس به روش PDO در PHP متد query() است. این متد یک ورودی گرفته و آن را مستقیماً در دیتابیس اجرا می‌کند.

در خط زیر، یک رکورد جدید با داده‌های ثابت به جدول users اضافه کرده‌ام: (با دستور INSERT در SQL)

$result = $conn->query( "INSERT INTO users VALUES('امید', 'omid@sample.com', '123456')" );

مشابه قطعه کد زیر نیز همه داده‌های جدول users را با روش PDO در PHP فراخوانی می‌کنیم:

<?php
$result = $conn->query( "SELECT * FROM users" );

اگر قرار است داده‌ای از کاربران دریافت کرده و از آن در دستور SQL استفاده کنید، برای استفاده از متد query() باید عملیات حذف کاراکترهای خطرناک و ایمن‌سازی را خودتان انجام دهید یا از روش بعدی استفاده کنید.

ذخیره رکورد با PDO در PHP

در مثال بالا دیدیم که می‌توان یک کوئری را به راحتی در دیتابیس اجرا کرد. اما اگر بخواهیم یک یا چند مقدار را از کاربر گرفته و از آن‌ها در دستور SQL استفاده کنیم، می‌توان از راهکار بهتری استفاده کرد.

بهتر است ابتدا کوئری مورد نظرمان ر بنویسیم اما به جای تعریف مقادیر دریافتی از کاربر در کوئری، از علامت سوال (?) استفاده کنیم. اینطوری به PDO می‌فهمانیم که قرار است به جای این علامت سؤال، یک مقدار جایگزین شود.

حالا کوئری را به متد prepare() در PDO می‌دهیم تا آن را آماده مقداردهی کند.

$statement = $conn->prepare("INSERT INTO users VALUES(?, ?, ?)");

برای اینکه مقادیر را در کوئری قرار دهیم، دو روش داریم:

روش اول تعریف یک آرایه php به ترتیب علامت‌های سوال است. مثلاً در کوئری بالا، ۳ جای خالی داریم که به ترتیب نام، ایمیل و رمز عبور است. پس آرایه‌ای به همین ترتیب ایجاد کرده و آن را به عنوان ورودی به متد execute() می‌دهیم:

<?php
$statement = $conn->prepare("INSERT INTO users VALUES(?, ?, ?)");

$data = ["امید", "omid@sample.com", "123456"];
$result = $statement->execute( $data );

توجه کنید که execute() را روی متغیر $statement که خروجی prepare() بود صدا زده‌ام.

در روش دوم تعیین پارامترهای ورودی کوئری PDO در PHP، به کمک متد bindParam() مقادیر را یکی یکی تعریف می‌کنیم.

  1. پارامتر اول جایگاه متغیر (ترتیب علامت سؤال) را مشخص می‌کند.
  2. در پارامتر مقدار مورد نظر را قرار می‌دهیم؛ که می‌تواند مقدار ثابت، متغیر یا مقادیر get و post در php باشد.
  3. بقیه پارامترها اختیاری است. مثلاً آرگومان سوم نوع داده‌ای که قرار است جایگزین شود را تعیین می‌کند.
<?php
$statement = $conn->prepare("INSERT INTO users VALUES(?, ?, ?)");

$password = "123456";

$statement->bindParam(1, $_POST['name']);
$statement->bindParam(2, $_POST['email']);
$statement->bindParam(3, $password);

$result = $statement->execute();
?>

مشابه این روند را در آموزش کار با فرم در PHP بررسی کرده‌ام. برای تثبیت یادگیری و کار با فرم‌ها می‌توانید آموزشش را ببینید.

فراخوانی از دیتابیس با PDO

برای فراخوانی داده از دیتابیس هم می‌توانیم مشابه روش‌های بالا عمل کنیم. فقط باید کدهای SQL مورد نظر را بنویسیم. کوئری نمایش همه سطرهای جدول users را اجرا می‌کنیم تا با متدهای نمایش نتایج آشنا شویم. در بخش انتهایی، مثال مشابهی با روش prepare می‌زنم.

فرض کنید می‌خواهم تمام کاربران سایت را در یک جدول نمایش دهم. در این جدول قرار است نام، ایمیل و سن کاربر را نمایش دهیم.

برای این کار، کافی است از دستور SELECT در SQL استفاده کنیم. خروجی query() و execute() یک شئ است که نتیجه اجرای کوئری (در اینجا نتیجه فراخوانی) را در خود نگه می‌دارد.

دو متد پرکاربرد در نمایش داده‌های واکشی‌شده داریم:

  • fetch() : در هر بار صدا زدن این متد، یکی از سطرهای نتیجه به ما بازگردانده می‌شود. بنابراین باید به تعداد سطرهای نتیجه، آن را صدا بزنیم. اگر به انتها برسیم، false برمی‌گرداند.
  • fetchAll() : آرایه‌ای از آرایه‌ها به ما برمی‌گرداند که هر عضو آن، مشخص کننده یک سطر از نتایج است.

در قطعه کد زیر از fetch() استفاده می‌کنم و در بخش بعدی کاربرد دومی را خواهید دید.

<?php
$result = $conn->query( "SELECT * FROM users" );

echo '<ul>';
while( $user = $result->fetch() ) {
    echo '<li>' . $user['name'] . ': ' . $user['age'] . '</li>';
}
echo '</ul>';
?>

مثال کار با PDO در PHP

به عنوان جمع‌بندی، فرض کنید می‌خواهیم نام افرادی که بیشتر از پارامتر $_GET['age'] سن دارند را در صفحه نمایش دهیم. برای این کار از prepare() و fetchAll() استفاده می‌کنم.

<?php
require_once 'configs.php';

try {
    $conn = new PDO( "mysql:host=$db_host;dbname=$db_name", $db_user, $db_pass );    
} catch(PDOException $e) {
    echo "خطایی به وجود آمده: " . $e->getMessage();
	die();
}

$statement = $conn->prepare( "SELECT * FROM users WHERE age > ?" );

$data = [$_GET['age']];

if( $statement->execute($data) ) {

    echo '<ul>';
    foreach( $statement->fetchAll() as $user ){
        echo '<li>' . $user['name'] . ': ' . $user['age'] . '</li>';
    }
    echo '</ul>';

}
?>

در این کد، اطلاعات دیتابیس را به صورت متغیر در فایل جانبی به نام configs.php قرار داده و با require (فراخوانی فایل در PHP) از آن‌ها استفاده کرده‌ام.

نتیجه کد مثال اتصال PDO به دیتابیس PHP
نتیجه کد مثال اتصال PDO به دیتابیس PHP

پیشنهاد: اگر لازم است دستور SQL مشابهی را با مقادیر داده‌ای مختلف اجرا کنید یا داده‌های دریافتی کاربران را در کوئری قرار دهید، از prepare() و سپس execute() استفاده کنید تا از مشکلات امنیتی در امان باشید.

در این آموزش یاد گرفتیم چگونه با روش PDO در PHP به دیتابیس متصل شده و با آن کار کنیم. برای اینکه در ابتدای یادگیری PHP از mysql استفاده می‌کنیم، از این دیتابیس استفاده کردم. اما یادتان باشد که علاوه بر راهکارهای امنیتی که PDO در اختیارمان می‌گذارد، به کمکش می‌توانیم به انواع دیتابیس متصل شویم.

برای جمع‌بندی، متدهای پرکاربرد PDO را در جدول زیر مشاهده می‌کنید:

exec()اجرای کوئری و برگرداندن تعداد سطر
query()اجرای مستقیم کوئری
prepare()ایجاد statement
execute()اجرای کوئری آماده شده
fetch()نمایش یکی یکی نتایج
fetchAll()برگرداندن همه نتایج

امیدوارم پس از این آموزش بتوانید به راحتی با PDO در PHP کار کنید. مستندات این کتابخانه در این صفحه در دسترس است. همچنین اگر سؤال یا تجربه‌ای در کار با pdo دارید، از بخش دیدگاه‌ها ثبت کنید.