انواع دریافت داده ها در PDO - قسمت دوم

13 بهمن 1397
درسنامه درس 7 از سری آموزش PDO
PDO-Fetch-Data

با سلام، در این قسمت به بررسی بیشتر راه های دریافت داده ها در PDO خواهیم پرداخت و برخی مسائل حاشیه ای را هم ذکر می کنیم.

نوع داده ی برگشتی

اگر PDO روی حالت mysqlnd1 بوده و emulation mode نیز خاموش باشد، داده های برگشتی می توانند از نوع int (عدد صحیح) و float (عدد اعشاری) باشند.

به طور مثال اگر یک جدول بسازیم:

create table typetest (string varchar(255), `int` int, `float` float, `null` int);
insert into typetest values('foo',1,1.1,NULL);

و سپس آن را با PDO بر پایه ی mysqlnd (و emulation mode خاموش) کوئری بزنیم، خروجی به شکل زیر خواهد بود:

array(4) {
  ["string"] => string(3) "foo"
  ["int"]    => int(1)
  ["float"]  => float(1.1)
  ["null"]   => NULL
}

در غیر این صورت همان رفتار قدیمی در تابع ()mysql_fetch_array را خواهیم دید؛ تمام مقادیر به صورت رشته ای برمیگردند به غیر از null که به صورت null برمیگردد.

1- mysqlnd چیست؟ برای برقراری ارتباط با پایگاه داده دو driver داریم: libmysqlclient و mysqlnd که تفاوت هایشان به شرح زیر است:

  • libmysqlclient توسط MySQL اما mysqlnd توسط PHP ارائه شده است.
  • libmysqlclient بخشی از MySQL است، بنابراین برای استفاده از آن باید کتابخانه ی MySQL را نصب کنید.
  • مباحث license آن ها متفاوت است.
  • mysqlnd از پلاگین های بسیاری پشتیبانی می کند (مانند mysqlnd_ms و mysqlnd_qc و ...).
  • از آن جایی که mysqlnd جزئی از PHP است، ممکن است حافظه ی آن بر اساس تنظیمات PHP محدود شود.
  • بعد از PHP 5.4 درایورِ mysqlnd به صورت پیش فرض انتخاب و فعال شده است.

برای اطلاعات بیشتر به http://php.net/manual/en/mysqlinfo.library.choosing.php مراجعه نمایید.

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

$pdo->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, true);

دریافت داده ها از طریق ()fetchColumn

این تابع هنگامی که برای انتخاب یک فیلد از پایگاه داده بسیار موثر است!

// id دریافت نام بر اساس 
$stmt = $pdo->prepare("SELECT name FROM table WHERE id=?");
$stmt->execute([$id]);
$name = $stmt->fetchColumn();

// دریافت تعداد ردیف ها در جدول
$count = $pdo->query("SELECT count(*) FROM table")->fetchColumn();

دریافت داده ها با فرمت های مختلف ()fetchAll

یکی از بهترین و کاربردی ترین توابع در PDO است که بسیاری از کار هایی که باید دستی انجام می شد را به صورت خودکار برای ما انجام می دهد!

در واقع ()PDOStatement::fetchAll یک آرایه برمی گرداند که شامل تمامی ردیف هایی (row) است که توسط کوئری ما برگشت داده شده اند. بر این اساس می توانیم بگوییم:

  1. اگر تعداد ردیف های انتخاب شده زیاد است، نباید از این تابع استفاده کرد. در چنین حالتی بهتر است از همان روش قدیمی حلقه ی while استفاده کرد تا ردیف ها را تک تک بگیرد نه اینکه همه را یکجا داخل یک آرایه بگذارد. منظور ما از "تعداد بالا" تعدادی است که نشان دادنش در حالت معمولی روی یک وب سایت معمولی درست نباشد و عقل سلیم آن را مشکل دار ببیند.
  2. این تابع در اپلیکیشن های مدرن وب امروزی بیشترین کاربرد را دارد؛ در این اپلیکیشن ها داده مستقیما هنگام دریافت (fetching) نمایش داده نمی شود بلکه به قالب (template) پاس داده می شود.

شما حتی باورتان نمی شود که این تابع به چند حالت می تواند داده ها را برگرداند! تمام این حالات با دستور *_PDO::FETCH کنترل می شود.

دریافت به صورت آرایه ای ساده

در حالت پیش فرض، این تابع یک آرایه عددی ساده را بر میگرداند که حاوی تمام ردیف های برگردانده شده است اما شما می توانید با ثابت های مختلف مربوط به این تابع (مانند PDO::FETCH_NUM یا PDO::FETCH_ASSOC یا PDO::FETCH_OBJ یا ...)، قالب داده های برگشتی را تعیین کنید:

$data = $pdo->query('SELECT name FROM users')->fetchAll(PDO::FETCH_ASSOC);
var_export($data);
/*
array (
  0 => array('John'),
  1 => array('Mike'),
  2 => array('Mary'),
  3 => array('Kathy'),
)*/

دریافت یک ستون (column)

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

$data = $pdo->query('SELECT name FROM users')->fetchAll(PDO::FETCH_COLUMN);
/* array (
  0 => 'John',
  1 => 'Mike',
  2 => 'Mary',
  3 => 'Kathy',
)*/

دریافت داده به صورت جفت های key-value

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

$data = $pdo->query('SELECT id, name FROM users')->fetchAll(PDO::FETCH_KEY_PAIR);
/* array (
  104 => 'John',
  110 => 'Mike',
  120 => 'Mary',
  121 => 'Kathy',
)*/

توجه: برای این قالب حتما باید دو ستون (و تنها دو ستون) انتخاب کنید که مورد اولشان unique (منحصر به فرد - به طور که در جدول مشترک نبوده و تکرار نشود) باشد.

دریافت ردیف ها با ایندکس های خاص

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

$data = $pdo->query('SELECT * FROM users')->fetchAll(PDO::FETCH_UNIQUE);
/* array (
  104 => array (
    'name' => 'John',
    'car' => 'Toyota',
  ),
  110 => array (
    'name' => 'Mike',
    'car' => 'Ford',
  ),
  120 => array (
    'name' => 'Mary',
    'car' => 'Mazda',
  ),
  121 => array (
    'name' => 'Kathy',
    'car' => 'Mazda',
  ),
)*/

نکته: اولین ستون انتخاب شده در این قالب باید unique (منحصر به فرد) باشد. در این مثال، فرض ما این بوده است که ستون اول، id افراد است و بنابراین منحصر به فرد تلقی می شود اما شما باید حواستان به جدول هایتان باشد.

دریافت ردیف ها به صورت دسته بندی شده بر اساس یک فیلد

دستور PDO::FETCH_GROUP ردیف ها را به صورت یک آرایه ی تو در تو در می آورد که ایندکس ها، مقادیر منحصر به فرد از ستون های اول هستند و مقادیر (value) آرایه هایی شبیه به آرایه هایی بوده که دستور ()fetchAll بر میگرداند.

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

$data = $pdo->query('SELECT sex, name, car FROM users')->fetchAll(PDO::FETCH_GROUP);
array (
  'male' => array (
    0 => array (
      'name' => 'John',
      'car' => 'Toyota',
    ),
    1 => array (
      'name' => 'Mike',
      'car' => 'Ford',
    ),
  ),
  'female' => array (
    0 => array (
      'name' => 'Mary',
      'car' => 'Mazda',
    ),
    1 => array (
      'name' => 'Kathy',
      'car' => 'Mazda',
    ),
  ),
)

این قالب، راه حل ایده آلی برای مواردی مانند "مرتب سازی بر اساس تاریخ" و "مرتب سازی بر اساس دسته بندی" و ... است.

حالت های دیگر

برای طرفداران برنامه نویسی functional نیز حالت  PDO::FETCH_FUNC موجود است.

حالت های دیگری نیز در دست ساخت است.

خلاصه ی مقاله

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

تمام فصل‌های سری ترتیبی که روکسو برای مطالعه‌ی دروس سری آموزش PDO توصیه می‌کند:
نویسنده شوید
دیدگاه‌های شما (1 دیدگاه)

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

اریا
20 اسفند 1399
دمت گرم کسی که با این مباحث نا اشنا نیست حتی مرورش هم شیرینه چه به اینکه بخواد از صفر یاد بگیره

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