مروری بر PDO (بخش دوم)

Overview of PDO - Part II: Executing SQL Codes

25 بهمن 1399
پروژه ساخت شبکه ی اجتماعی: مروری بر PDO (بخش دوم)

همانطور که در قسمت قبلی گفتیم در این جلسه کدنویسی پروژه ی اصلی را کنار گذاشته ایم تا مروری بر رابط PDO و آموزش PDO در PHP داشته باشیم. این رابط یک رابط اتصال به پایگاه داده به صورت شیء گرا در PHP است که با نسخه ی 5.1 از زبان PHP ارائه شد.

در قسمت قبلی با استفاده از کد زیر به پایگاه داده ی خود وصل شدیم:

<?php
	$host = 'localhost';
	$user = 'root';
	$password = '123456';
	$dbname = 'pdotest';
// Set DSN
	$dsn = 'mysql:host=' . $host . ';dbname=' . $dbname;
	$pdo = new PDO($dsn, $user, $password);

سپس سه کاربر در جدول کاربرها ایجاد کردیم و فایل sql آن را برای دانلود به شما دادیم.

حالا می خواهیم با دستورات SQL این کاربران را دریافت کنیم بنابراین با دستوری ساده شروع می کنیم. اگر از prepared statement ها استفاده نکنیم دستور ما به شکل زیر خواهد بود:

ابتدا یک متغیر تعریف می کنیم به نام Status تا وضعیت کاربر را مشخص کند (آیا کاربر ادمین است یا یک کاربر عادی؟) سپس آن را مستقیما وارد دستور SQL زیر می کنیم:

$status = 'admin';
$sql = 'SELECT * FROM users WHERE status = $status';

حالا فرض کنید متغیر status از سمت کاربر بیاید (فرض می کنیم)؛ کاربر می تواند به جای اضافه کردن وضعیت کاربر، کدهای sql بیشتری را اضافه کند و با این کدها در سیستم پایگاه داده ی ما اخلال ایجاد کند یا حتی تمام پایگاه داده را حذف کند.

اما به جای این کار می توانیم از یک placeholder استفاده کنیم یعنی:

$sql = 'SELECT * FROM users WHERE status = :status';

به این حالت (استفاده از علامت دو نقطه) named parameter می گوییم. حالت دیگری وجود دارد به نام positional parameters که در آن از علامت سوال استفاده می کنیم:

$sql = 'SELECT * FROM users WHERE status = ?';

اگر با این دو مفهوم آشنا نیستید به صورت ساده چند نکته را خدمتتان عرض می کنم. برای مثال به کد زیر توجه کنید:

$sql = 'SELECT * FROM users WHERE email = :email AND status=:status';

اگر به مثال توجه کرده باشید، فهمیده اید که PDO از placeholder های موقعیتی یا positional (در مثال -> ?) و اسمی یا named (در مثال -> email:) پشتیبانی می کند. برای استفاده از placeholder های اسمی از دو نقطه استفاده می کنید (مانند مثال). نامی که برای آن انتخاب می کنید باید از بین حروف، اعداد و آندرلاین انتخاب شده باشد. همچنین توجه داشته باشد که هیچ نوع quotation ای این نوع از placeholder ها را احاطه نکرده است.

نکته ی اول: شما نمی توانید از placeholder های موقعیتی و اسمی به طور همزمان در یک کوئری استفاده کنید.

نکته ی دوم: توجه داشته باشید که placeholder های موقعیتی به شما کمک می کنند کدهای کوتاه تری بنویسید اما نسبت به ترتیب آرگومان های پاس داده شده به ()execute حساس هستند؛ یعنی دقیقا به ترتیب placeholder ها در کوئری اصلی هستند (به طور مثال علامت سوال اول، اولین آرگومان را می گیرد، دومی نیز آرگومان دومی را می گیرد و الی آخر).

از طرف دیگر placeholder های اسمی کد را طولانی تر می کنند اما نسبت به موقعیت حساس نیستند (چرا که در آرایه ی متناظر با جفت های key و value تنظیم می شوند – ر.ک مثال بالا).

نکته ی سوم: در placeholder های اسمی، زمانی که بخواهید آرایه را به ()execute تحویل دهید نیازی به گذاشتن علامت دو نقطه نیست (ر.ک مثال بالا).


حالا ادامه ی بحث خودمان؛ کدها را prepare (آماده) می کنیم:

$stmt = $pdo->prepare($sql);

این کد دستور ما را برای اجرا آماده می کند. سپس می توانیم دستور را برای اجرا به پایگاه داده بفرستیم اما باید status: را نیز مشخص کنیم چون در حال حاضر مقداری برایش تعیین نکردیم. بنابراین آن را به شکل یک آرایه ی متناظر تعیین می کنیم:

$stmt->execute(['status' => $status]);

حالا که دستور در پایگاه داده اجرا شد باید نتایج را برگردانیم بنابراین می گوییم:

$users = $stmt->fetchAll();

اکنون متغیر users تبدیل به یک آرایه شده است و کاربران را در خود نگه داشته است. برای نمایش کاربران می توانیم از یک حلقه ی ساده ی foreach استفاده کنیم:

foreach($users as $user) {
 	echo $user[‘name’].’<br>’;
	 }

همانطور که دیدیم دستور fetchAll یک آرایه به ما برمی گرداند اما اگر نتایج را به صورت شیء بخواهیم می توانیم آن را به صورت زیر بنویسیم:

$users = $stmt->fetchAll(PDO::FETCH_OBJ);
foreach($users as $user) {
 	echo $user->name.’<br>’;
	 }

بنده از استایل شیء گرایانه بیشتر خوشم می آید بنابراین طرح را به همین شکل جلو می بریم اما از آنجایی که هر بار نوشتن PDO::FETCH_OBJ وقت گیر است آن را به عنوان پیش فرض تعیین می کنیم. برای این کار هنگام ساختن اتصال به پایگاه داده می توانیم به این شکل عمل کنیم:

$pdo = new PDO($dsn, $user, $password);
$pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_OBJ);

از این به بعد نیازی به نوشتن PDO::FETCH_OBJ نیست بلکه به راحتی می نویسیم:

$users = $stmt->fetchAll();

حالا برای قسمت دوم کار می خواهیم یک دستور INSERT را پیاده سازی کنیم. بهتر است قبل از شروع کار دستورات قبل را کامنت کنید تا به خاطر شباهت نام ها به مشکل نخورید.

 فرض کنید می خواهیم فردی با اطلاعات زیر را در جدول پایگاه داده ی خود وارد کنیم:

$name = 'Karen Williams';
$email = 'kwills@gmail.com';
$status = 'guest';

باید دستور SQL خود را به این شکل بنویسیم:

$sql = 'INSERT INTO users(name, email, status) VALUES(:name, :email, :status)';

توجه کنید که مقادیر نام، ایمیل و وضعیت را به شکل placeholder (با علامت :) قرار داده ایم.

من راجع به دستورات SQL صحبتی نمی کنم چرا که از پیش نیاز های این دوره است. اگر با زبان SQL آشنایی ندارید و نمی دانید چطور اطلاعات را وارد جدول می کنند باید به دوره ی آموزشی SQL در روکسو مراجعه کنید.

حالا باید دستور SQL را آماده سازی (prepare) کنیم:

$stmt = $pdo->prepare($sql);

اکنون باید دستور را در پایگاه داده اجرا کنیم:

$stmt->execute(['name'=> $name, 'email' => $email, 'status' => $status]);

در آخر برای اطمینان از ورود کاربر یک پیام ساده چاپ می کنیم:

echo 'Added User';

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

دانلود فایل های این دو جلسه (مروری بر PDO)

از قسمت بعدی شروع به نوشتن کلاس پایگاه داده ی خود در فریم ورک traversy خواهیم کرد. امیدوارم این قسمت از آموزش PDO در PHP برایتان مفید بوده باشد.

تمام فصل‌های سری ترتیبی که روکسو برای مطالعه‌ی دروس سری آموزش ساخت شبکه اجتماعی توصیه می‌کند:
نویسنده شوید
دیدگاه‌های شما

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.