خانه - پنجره ها
چگونه با PDO کار کنیم؟ راهنمای کامل نصب پسوندهای OCI8 و PDO_OCI برای PHP5 نصب pdo

من در حال حاضر برای شرکتی کار می کنم که واقعاً دوست دارد از Oracle DBMS در پروژه های PHP استفاده کند، گاهی اوقات نسخه 11g.

اکثر توسعه دهندگان این شرکت تحت سیستم عامل ویندوز کار می کنند. در ماه گذشته، چند نفر از آنها تصمیم گرفتند به لینوکس بپیوندند و اوبونتو را نصب کردند. چند روز پس از نصب خود سیستم عامل، بچه ها با وظیفه نصب درایورهای PHP برای کار با Oracle DBMS - OCI8 و PDO_OCI بر اساس Oracle instant client 11.2 مواجه شدند که به تنهایی نتوانستند آن را حل کنند.

من یک کتابچه راهنمای دقیق و کامل به زبان روسی پیدا نکردم که طبق آن یک تازه وارد به لینوکس بتواند تمام دستکاری ها را خودش انجام دهد. در نتیجه مجبور شدم چندین بار یک سری از کارهای مشابه را روی دستگاه های آنها انجام دهم و یک دفترچه راهنما بنویسم که به شما ارائه می دهم.

این راهنما برای کاربران لینوکس اوبونتو نوشته شده است، اما با برخی تغییرات برای کاربران اکثر سیستم های لینوکس مناسب خواهد بود.

آماده سازی برای نصب

  1. شما باید بتوانید دستورات را به عنوان یک مدیر اجرا کنید.
  2. شما باید php5 را با بسته های زیر نصب کنید (دستور نصب با لیست):
    sudo apt-get نصب php5 php5-dev php-pear php5-cli
    sudo pecl نصب pdo
  3. شما باید کتابخانه libaio1 را نصب کرده باشید:
    sudo apt-get install libaio1

نصب کلاینت فوری Oracle

مشتری فوری Oracle را از وب سایت رسمی http://oracle.com برای معماری پردازنده و سیستم عامل خود دانلود کنید.
کلاینت فوری لینوکس در دو نسخه ارائه می شود:
  • بسته RPM - Linux، CentOS، Fedora، Red Hat Enterprise Linux، Mandriva Linux، SUSE Linux و غیره. چه کسی پشتیبانی از RPM دارد.
  • بایگانی ZIP - برای دیگران.
شما باید 2 فایل دانلود کنید:
  • instantclient-basic - خود مشتری فوری Oracle
  • instantclient-sdk - مجموعه ای از کتابخانه ها برای توسعه برنامه های کاربردی برای سرویس گیرنده فوری Oracle
همچنین می توانید دانلود کنید:
  • instantclient-sqlplus - SQL*Plus
دایرکتوری ای ایجاد کنید که فایل های سرویس گیرنده فوری Oracle در آن قرار گیرند (دایرکتوری opt/ که برای بسته های نرم افزاری اضافی رزرو شده است، برای این کار خوب است):
sudo mkdir -p /opt/oracle/

فایل‌های دانلود شده را به /opt/oracle منتقل کنید و به پوشه مقصد بروید (فرض می‌کنیم که «زیپ آرشیو» را در پوشه «دانلود» کاربر خود دانلود کرده‌اید):
sudo mv ~/downloads/instantclient-*.zip /opt/oracle/
سی دی /opt/oracle/

تمام آرشیوهای دانلود شده را از حالت فشرده خارج کنید:
sudo unzip instantclient-basic-*-*.zip
sudo unzip instantclient-sdk-*-*.zip
اگر SQL*Plus را دانلود کردید:
sudo unzip instantclient-sqlplus-*-*.zip

در نتیجه، در پوشه /opt/oracle، دایرکتوری instantclient_11_2 برای Oracle instant client 11.2.0.2.0 ایجاد شد. بیایید نام این دایرکتوری را به instantclient تغییر دهیم (اگر نسخه/دایرکتوری دیگری دارید، دستور را تغییر دهید) و به آن بروید:
sudo mv instantclient_11_2 instantclient
cd instantclient

در مرحله بعد، باید چندین دایرکتوری اضافی و پیوند نمادین ایجاد کنید تا مشتری به طور معمول کار کند (به نسخه توجه کنید و اگر نسخه دیگری دارید، دستورات را تغییر دهید):
sudo ln -s /opt/oracle/instantclient/libclntsh.so.* /opt/oracle/instantclient/libclntsh.so
sudo ln -s /opt/oracle/instantclient/libocci.so.* /opt/oracle/instantclient/libocci.so
sudo ln -s /opt/oracle/instantclient/ /opt/oracle/instantclient/lib

Sudo mkdir -p include/oracle/11.2/
سی دی شامل/oracle/11.2/
sudo ln -s ../../../sdk/include client
سی دی-

Sudo mkdir -p lib/oracle/11.2/client
سی دی lib/oracle/11.2/client
sudo ln -s ../../../ lib
سی دی-

ما یک فایل پیکربندی ایجاد می کنیم که فهرست راهنمای جستجوی کتابخانه های سرویس گیرنده فوری Oracle را نشان می دهد و آن را متصل می کنیم:
echo /opt/oracle/instantclient/ | sudo tee -a /etc/ld.so.conf.d/oracle.conf
sudo ldconfig

از آنجایی که هیچ دایرکتوری /usr/include/php در اوبونتو وجود ندارد، و مشتری همچنان به دنبال آن است، بیایید یک پیوند نمادین به معادل php5 آن ایجاد کنیم:
sudo ln -s /usr/include/php5 /usr/include/php

OCI8 را نصب کنید

پس از تمام دستکاری های ما، پسوند oci8 با استفاده از دستور pecl به طرز شگفت انگیزی نصب می شود:
sudo pecl نصب oci8
از ما خواسته می شود که مسیر مشتری فوری Oracle را وارد کنیم که باید به آن پاسخ دهیم:
instantclient،/opt/oracle/instantclient

یک فایل اتصال پسوند ایجاد کنید:
echo "؛ پیکربندی برای ماژول php oci8" | sudo tee /etc/php5/conf.d/oci8.ini
echo extension=oci8.so | sudo tee -a /etc/php5/conf.d/oci8.ini

PDO_OCI را نصب کنید

برای نصب PDO_OCI ابتدا باید آن را از مخزن گلابی دانلود کنیم.
بیایید لیست بسته های گلابی را به روز کنیم:
کانال sudo pecl-به روز رسانی pear.php.net

آرشیو را دانلود و در یک فهرست موقت قرار دهید:
sudo mkdir -p /tmp/pear/download/
سی دی /tmp/pear/دانلود/
sudo pecl دانلود pdo_oci

بیایید محتویات آرشیو را استخراج کنیم و به آن برویم:
sudo tar xvf PDO_OCI*.tgz
سی دی PDO_OCI*

در اینجا ما باید فایل config.m4 را تنظیم کنیم، زیرا حاوی اطلاعاتی در مورد نسخه سرویس گیرنده فوری Oracle ما نیست، آخرین تغییرات به سال 2005 بازمی‌گردد. ویرایشگر مورد علاقه خود را راه اندازی کنید و تغییرات را با علامت "+" انجام دهید (به نسخه توجه کنید و اگر نسخه دیگری دارید، خطوط را تغییر دهید):
sudo vim config.m4

موارد زیر تفاوت دو فایل است:
***************
*** 7,12 ****
--- 7,14 ----
if test -s "$PDO_OCI_DIR/orainst/unix.rgs"; سپس
PDO_OCI_VERSION=`grep ""ocommon"" $PDO_OCI_DIR/orainst/unix.rgs | sed "s/*/:/g" | cut -d: -f 6 | برش -c 2-4`
تست -z "$PDO_OCI_VERSION" && PDO_OCI_VERSION=7.3
+ elif test -f $PDO_OCI_DIR/lib/libclntsh.$SHLIB_SUFFIX_NAME.11.2; سپس
+ PDO_OCI_VERSION=11.2
elif test -f $PDO_OCI_DIR/lib/libclntsh.$SHLIB_SUFFIX_NAME.10.1; سپس
PDO_OCI_VERSION=10.1
elif test -f $PDO_OCI_DIR/lib/libclntsh.$SHLIB_SUFFIX_NAME.9.0; سپس
***************
*** 119,124 ****
--- 121,129 ----
10.2)
PHP_ADD_LIBRARY(clntsh، 1، PDO_OCI_SHARED_LIBADD)
;;
+ 11.2)
+ PHP_ADD_LIBRARY (clntsh، 1، PDO_OCI_SHARED_LIBADD)
+ ;;
*)
AC_MSG_ERROR (نسخه Oracle پشتیبانی نشده! $PDO_OCI_VERSION)
;;
***************

با استفاده از دستور phpize محیط را برای پسوند php آماده می کنیم (به نسخه توجه کنید، اگر نسخه دیگری دارید، آن را تغییر دهید):
sudo phpize

ما نصب کننده بسته را پیکربندی می کنیم و بسته را نصب می کنیم (به نسخه توجه کنید، اگر نسخه دیگری دارید، آن را تغییر دهید):
sudo ./configure --with-pdo-oci=instantclient,/opt/oracle/instantclient/,11.2
سودو ساخت
sudo make install

ما یک فایل اتصال برای آن ایجاد می کنیم:
echo "؛ پیکربندی برای ماژول php PDO_OCI" | sudo tee /etc/php5/conf.d/pdo_oci.ini
echo extension=pdo_oci.so | sudo tee -a /etc/php5/conf.d/pdo_oci.ini

بیایید آن را جمع بندی کنیم

apache را مجددا راه اندازی کنید و پسوندهای نصب شده را بررسی کنید:
sudo /etc/init.d/apache2 راه اندازی مجدد
php -m

نتیجه

دفترچه راهنما بر اساس این پست است که کمی اصلاح شده است - اشتباهات اصلاح شده و اضافات شده است.

امیدوارم مقاله نه تنها برای همکارانم مفید باشد.


3 ژوئن 2018 آندری چرنیشوف آموزش ترجمه 1736 0

PDO مخفف PHP Data Objects است: این یک پسوند PHP برای کار با پایگاه های داده با استفاده از اشیاء است. یکی از مزایای آن در این واقعیت نهفته است که مستقیماً به یک پایگاه داده خاص مرتبط نیست: رابط آن به شما امکان می دهد به چندین محیط مختلف از جمله: MySQL، SQLite، PostgreSQL، Microsoft SQL Server دسترسی داشته باشید.

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

ایجاد پایگاه داده و جدول آزمایشی

اول از همه، ما یک پایگاه داده ایجاد می کنیم:

ایجاد پایگاه داده solar_system. اعطای تمام امتیازات به solar_system.* به "testuser"@"localhost" که با "testpassword" شناسایی شده است.

ما با استفاده از testpassword برای رمز عبور، همه امتیازات را در پایگاه داده solar_system به کاربر آزمایش کننده اعطا کرده ایم. حالا بیایید یک جدول ایجاد کنیم و آن را با اطلاعاتی پر کنیم:

استفاده از solar_system; CREATE TABLE سیارات (id TINYINT(1) Unsigned NOT NULL AUTO_INCREMENT، PRIMARY KEY(id)، نام VARCHAR(10) NOT NULL، رنگ VARCHAR(10) NOT NULL). INSERT INTO سیارات (نام، رنگ) VALUES ("زمین"، "آبی")، ("مریخ"، "قرمز")، ("مشتری"، "عجیب");

شرح اتصال DSN (نام منبع داده).

اکنون که یک پایگاه داده داریم، باید DSN را تنظیم کنیم. DSN مخفف Data Source Name است و مجموعه ای از اطلاعات مورد نیاز برای اتصال به پایگاه داده است، DSN به صورت رشته ای است. نحو بسته به پایگاه داده ای که باید به آن متصل شوید متفاوت است، اما از آنجایی که ما از MySQL/MariaDB استفاده می کنیم، باید موارد زیر را تنظیم کنیم:

  • نوع درایور مورد استفاده برای اتصال؛
  • نام رایانه میزبان که پایگاه داده روی آن اجرا می شود؛
  • پورت اتصال (اختیاری)؛
  • نام پایگاه داده؛
  • رمزگذاری (اختیاری).

فرمت خط در مورد ما به این صورت خواهد بود (ما آن را در متغیر $dsn ذخیره می کنیم):

$dsn = "mysql:host=localhost;port=3306;dbname=solar_system;charset=utf8";

ابتدا پیشوند پایگاه داده یا پیشوند پایگاه داده را تنظیم می کنیم. در این مورد، از آنجایی که ما به یک پایگاه داده نوع MySQL/MariaDB متصل می شویم، از mysql استفاده می کنیم. سپس پیشوند را از بقیه خط با دونقطه جدا کردیم و هر بخش بعدی با یک نقطه ویرگول از بقیه جدا شد.

در دو بخش بعدی نام میزبانی که پایگاه داده بر روی آن اجرا می شود و پورت مورد استفاده برای اتصال را مشخص کردیم. اگر پورتی مشخص نشده باشد، از پورت پیش فرض استفاده می شود که در این مورد 3306 است. بلافاصله پس از نام پایگاه داده charset است.

ایجاد یک شی PDO

اکنون که DSN ما آماده است، شروع به ایجاد شی PDO می کنیم. سازنده PDO از رشته DSN به عنوان پارامتر اول، نام کاربری پایگاه داده به عنوان پارامتر دوم، رمز عبور به عنوان پارامتر سوم و یک آرایه تنظیمات اختیاری به عنوان پارامتر چهارم استفاده می کند.

$options = [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION، PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC ]; $pdo = PDO جدید ($dsn، "testuser"، "testpassword"، $options);

همچنین می توان تنظیمات را پس از ایجاد شی با استفاده از متد SetAttribute() تنظیم کرد:

$pdo->SetAttribute(PDO::ATTR_ERRMODE، PDO::ERRMODE_EXCEPTION);

پیکربندی PDO برای مشاهده خطاها

بیایید نگاهی به برخی از گزینه های موجود برای PDO::ATTR_ERRMODE بیندازیم. این گزینه‌ها بسیار مهم هستند زیرا تعیین می‌کنند که PDO در هنگام بروز خطا چگونه رفتار می‌کند. گزینه های ممکن:

PDO::ERRMODE_SILENT

گزینه پیش فرض PDO به سادگی یک کد خطا و یک پیام خطا ارسال می کند. آنها را می توان با استفاده از روش های errorCode() و errorInfo() بدست آورد.

PDO::ERRMODE_EXCEPTION

به نظر من استفاده از این گزینه توصیه می شود. با کمک آن علاوه بر صدور کد خطا و اطلاعات، PDO یک PDOException را پرتاب می کند که اجرای اسکریپت را مختل می کند و برای تراکنش های PDO نیز مفید است (کمی بعد به آنها نگاه خواهیم کرد).

PDO::ERRMODE_WARNING

با این گزینه، PDO یک کد خطا و پیغام درست مانند PDO::ERRMODE_SILENT را نمایش می دهد، اما یک هشدار WARNING را نیز نمایش می دهد که اسکریپت را قطع نمی کند.

تنظیم روش نمونه گیری پیش فرض

تنظیم مهم دیگر با استفاده از ثابت PDO::DEFAULT_FETCH_MODE تنظیم می شود. این به شما اجازه می دهد تا عملیات پیش فرض متد ()fetch را پیکربندی کنید، که برای به دست آوردن نتایج درخواست استفاده می شود. در اینجا متداول ترین گزینه ها استفاده می شود:

PDO::FETCH_BOTH

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

$stmt = $pdo->query("SELECT * FROM planets"); $results = $stmt->fetch(PDO::FETCH_BOTH); آرایه (=> 1 => 1 => زمین => زمین => آبی => آبی)

PDO::FETCH_ASSOC

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

$stmt = $pdo->query("SELECT * FROM planets"); $results = $stmt->fetch(PDO::FETCH_ASSOC); آرایه (=> 1 => زمین => آبی)

PDO::FETCH_NUM

با استفاده از ثابت PDO::FETCH_NUM یک آرایه با شاخص 0 دریافت می کنیم:

آرایه (=> 1 => زمین => آبی)

PDO::FETCH_COLUMN

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

$stmt = $pdo->query("SELECT name FROM planets");

در نتیجه:

آرایه (=> زمین => مریخ => مشتری)

PDO::FETCH_KEY_PAIR

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

$stmt = $pdo->query("انتخاب نام، رنگ از سیاره ها"); $result = $stmt->fetchAll(PDO::FETCH_KEY_PAIR);

در نتیجه:

آرایه (=> آبی => قرمز => عجیب)

PDO::FETCH_OBJECT

هنگام استفاده از ثابت PDO::FETCH_OBJECT، یک شی ناشناس برای هر ردیف واکشی ایجاد می شود. ویژگی های (عمومی) آن مانند ستون ها نامگذاری می شود و نتایج پرس و جو به عنوان مقادیر استفاده می شود. استفاده از این روش برای همان پرس و جوی فوق نتیجه زیر را به همراه خواهد داشت:

$results = $stmt->fetch(PDO::FETCH_OBJ); شیء stdClass ( => زمین => آبی)

PDO::FETCH_CLASS

مانند ثابت قبلی، این مقدار ستون ها را به ویژگی های شی اختصاص می دهد، اما در این مورد باید یک کلاس موجود را پیکربندی کنیم که برای ایجاد شی مورد استفاده قرار می گیرد. برای نمایش ابتدا یک کلاس ایجاد می کنیم:

Class Planet ( $name خصوصی; خصوصی $color; تابع عمومی setName($planet_name) ( $this->name = $planet_name; ) تابع عمومی setColor($planet_color) ($this->color = $planet_color; ) تابع عمومی getName () ( return $this->name; ) تابع عمومی getColor() ( return $this->color; ) )

به سادگی کد توجه نکنید، بهتر است به کلاس Planet که ایجاد کردیم نگاه کنیم: خصوصیات آن خصوصی است و کلاس سازنده ندارد. حالا بیایید سعی کنیم نتیجه بگیریم.

هنگام استفاده از fetch() با PDO::FETCH_CLASS، قبل از تلاش برای واکشی داده ها، باید از متد setFetchMode() روی شی استفاده کنید، به عنوان مثال:

$stmt = $pdo->query("انتخاب نام، رنگ از سیاره ها"); $stmt->setFetchMode(PDO::FETCH_CLASS، "Planet");

ثابت PDO::FETCH_CLASS را به عنوان اولین آرگومان متد setFetchMode() و نام کلاس مورد استفاده برای ایجاد شی (در مورد ما "Planet") را به عنوان آرگومان دوم مشخص می کنیم. حالا بیایید کد را اجرا کنیم:

$planet = $stmt->fetch();

این باید منجر به یک شی سیاره شود:

Var_dump ($planet); شی سیاره (=> زمین => آبی)

توجه کنید که چگونه مقادیر برگردانده شده از پرس و جو به ویژگی های مربوط به شی اختصاص داده شده اند، حتی اگر خصوصی باشند.

اختصاص دادن ویژگی ها پس از ایجاد یک شی

کلاس "Planet" هیچ سازنده خاصی نداشت، بنابراین هیچ مشکلی در تخصیص ویژگی ها وجود نداشت. اما اگر کلاس سازنده ای داشته باشد که ویژگی ها در آن تنظیم و تغییر می کنند چه؟ از آنجایی که مقادیر قبل از اجرای سازنده تخصیص داده می شوند، بازنویسی می شوند.

PDO به ارائه ثابت FETCH_PROPS_LATE کمک می کند: هنگام استفاده، مقادیر پس از ایجاد شی تخصیص داده می شوند. مثال:

Class Planet ( $name خصوصی؛ $color خصوصی؛ تابع عمومی __construct($name = ماه، $color = خاکستری) ($this->name = $name; $this->color = $color; ) تابع عمومی setName($ planet_name) ($this->name = $planet_name; ) تابع عمومی setColor($planet_color) ($this->color = $planet_color; ) تابع عمومی getName() ( return $this->name; ) تابع عمومی getColor() ( بازگشت $this->color; ) )

ما کلاس Planet خود را برای ایجاد سازنده ای تغییر دادیم که دو آرگومان دارد: name name و color. این آرگومان ها دارای مقادیر پایه moon و gray هستند، به این معنی که اگر مقادیر دیگری داده نشود، اینها تنظیم می شوند.

در این صورت، اگر از FETCH_PROPS_LATE استفاده نکنیم، مهم نیست که چه مقادیری از پایگاه داده به دست می‌آید، همه ویژگی‌ها پایه باقی می‌مانند، زیرا در طی فرآیند ایجاد شی، آنها رونویسی می‌شوند. برای بررسی این موضوع، کوئری زیر را اجرا می کنیم:

$stmt = $pdo->query("SELECT name, color FROM solar_system WHERE name = "earth""); $stmt->setFetchMode(PDO::FETCH_CLASS، "Planet"); $planet = $stmt->fetch();

حالا بیایید نگاهی به شی Planet بیندازیم و بررسی کنیم که کدام مقادیر با ویژگی های آن مطابقت دارند:

Var_dump ($planet); object(Planet)#2 (2) ( ["name":"Planet":private]=> string(4) "moon" ["color":"Planet":private]=> string(4) "grey" )

همانطور که انتظار می رفت، مقادیر بازیابی شده از پایگاه داده با مقادیر پیش فرض بازنویسی شدند. اکنون، ما راه حل مشکلات را با استفاده از ثابت FETCH_PROPS_LATE (و همان پرس و جوی قبلی) نشان خواهیم داد:

$stmt->setFetchMode(PDO::FETCH_CLASS|PDO::FETCH_PROPS_LATE، "Planet"); $planet = $stmt->fetch(); var_dump ($planet); object(Planet)#4 (2) ( ["name":"Planet":private]=> string(5) "earth" ["color":"Planet":private]=> string(4) "blue" )

در نهایت نتیجه مطلوب حاصل شد. اما اگر سازنده کلاس مقادیر پایه نداشته باشد و باید مشخص شوند چه؟ این در حال حاضر ساده تر است: ما می توانیم پارامترهای سازنده را در قالب یک آرایه، به عنوان آرگومان سوم پس از نام کلاس، با استفاده از متد setFetchMode () تنظیم کنیم. به عنوان مثال، بیایید سازنده را تغییر دهیم:

Class Planet ($name خصوصی; خصوصی $color; تابع عمومی __construct($name, $color) ($this->name = $name; $this->color = $color; ) [...] )

آرگومان های سازنده اکنون مورد نیاز هستند، بنابراین ما اجرا می کنیم:

$stmt->setFetchMode(PDO::FETCH_CLASS|PDO::FETCH_PROPS_LATE، "سیاره"، ["ماه"، "خاکستری"]);

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

بازیابی چندین شی

البته می توان به طور همزمان چندین نتیجه را در قالب اشیاء به دست آورد، یا با استفاده از متد fetch() یا از طریق یک حلقه:

while ($planet = $stmt->fetch()) ( // چیزی که با نتایج مرتبط است)

یا اینکه همه نتایج را به یکباره بگیرید. در این مورد، همانطور که قبلا ذکر شد، هنگام استفاده از متد fetchAll() باید حالت واکشی را نه قبل از اجرای متد، بلکه در لحظه ای که اجرا می شود مشخص کنید:

$stmt->fetchAll(PDO::FETCH_CLASS|PDO_FETCH_PROPS_LATE، "سیاره"، ["ماه"، "خاکستری"]);

PDO::FETCH_INTO

هنگام استفاده از این ثابت، PDO یک شی جدید ایجاد نمی کند، در عوض ویژگی های یک موجود را به روز می کند، اما فقط در صورتی که عمومی باشد یا از متد __set() در داخل شی استفاده شود.

در برابر درخواست های مستقیم آماده شده است

PDO دو راه برای کار با پرس و جوها دارد: استفاده از موارد مستقیم و قابل اطمینان تر - موارد آماده.

درخواست های مستقیم

دو روش اصلی برای استفاده از پرس و جوهای مستقیم وجود دارد: query() و exec(). اولین مورد یک شی PDOStatemnt ایجاد می کند که می تواند از طریق متدهای fetch() یا fetchAll() قابل دسترسی باشد: اگر از آنها در مواردی استفاده کنید که جدول تغییر نمی کند، مانند SELECT .

روش دوم، به جای آن، تعداد ردیفی را که توسط پرس و جو اصلاح شده است، برمی گرداند: ما از آن در مواردی استفاده می کنیم که جایگزین ردیف ها می شود، مانند INSERT، DELETE یا UPDATE. از پرس و جوهای مستقیم فقط در مواردی باید استفاده کرد که هیچ متغیری در کوئری ها وجود نداشته باشد و در بی خطر بودن روش شکی وجود نداشته باشد.

پرس و جوهای آماده شده

PDO همچنین از پرس‌و‌جوهای آماده‌شده دو مرحله‌ای پشتیبانی می‌کند: زمانی که کوئری‌ها دارای متغیر هستند، مفید هستند و به طور کلی امن‌تر هستند، زیرا متد ()prepar کل کارهای لازم را برای ما انجام می‌دهد. بیایید نگاهی به نحوه استفاده از متغیرها بیندازیم. تصور کنید می خواهیم ویژگی های یک سیاره را در جدول سیارات وارد کنیم. ابتدا بیایید یک درخواست آماده کنیم:

$stmt = $pdo->prepare("INSERT INTO planets(name, color) VALUES(?, ?)");

همانطور که قبلاً گفته شد، ما از متد ()preparate استفاده می کنیم که پرس و جوی SQL را به عنوان آرگومان می گیرد و از مقادیر موقت برای متغیرها استفاده می کند. مقادیر موقت می توانند دو نوع باشند: موقعیتی و اسمی.

موقعیتی

استفاده كردن؟ مقادیر موقتی موقعیتی، کد مختصرتر است، اما باید داده ها را به همان ترتیبی که نام ستون ها در آرایه ارائه شده به عنوان آرگومان برای متد execute() درج می شود، مشخص کنیم:

$stmt->execute([$planet->name, $planet->color]);

شخصی شده

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

$stmt = $pdo->prepare("INSERT INTO planets(name, color) VALUES(:name, :color)"); $stmt->execute(["name" => $planet->name, "color" => $planet->color]);

متد ()prepare و execute() هر دو می توانند برای پرس و جوهایی که اطلاعات را از پایگاه داده تغییر می دهند یا به سادگی بازیابی می کنند استفاده شوند. در حالت اول از متدهای واکشی فهرست شده در بالا برای به دست آوردن اطلاعات و در حالت دوم از متد rowCount() استفاده می کنیم.

متدهای bindValue() و bindParam().

از متدهای bindValue() و bindParam() نیز می توان برای ارائه مقادیری که در درخواست درج می شود استفاده کرد. اولی مقدار یک متغیر داده شده را به یک مقدار موقتی موقعیتی یا نامگذاری شده که در تهیه درخواست استفاده می شود، متصل می کند. با در نظر گرفتن مورد قبلی به عنوان مثال، انجام خواهیم داد:

$stmt->bindValue("name", $planet->name, PDO::PARAM_STR);

ما مقدار $planet->name را به مقدار موقت:name متصل می کنیم. توجه داشته باشید که با استفاده از هر دو متد bindValue() و bindParam() می‌توانیم نوع متغیر را به عنوان آرگومان سوم با استفاده از یک ثابت PDO مناسب، در این مورد PDO::PARAM_STR مشخص کنیم.

با استفاده از bindParam() به جای آن می توانیم متغیر را به یک مقدار موقت مناسب مورد استفاده در آماده سازی پرس و جو متصل کنیم. توجه داشته باشید که در این حالت، متغیر به مرجع مقید است و تنها زمانی که متد execute() اجرا می شود، مقدار آن به موقت تغییر می کند. نحو مشابه دفعه قبل است:

$stmt->bindParam("name"، $planet->name، PDO::PARAM_STR)

ما متغیر را، نه مقدار آن، $planet->name را به:name محدود کرده‌ایم! همانطور که در بالا گفته شد، جایگزینی تنها زمانی اتفاق می‌افتد که متد ()execute اجرا شود، بنابراین مقدار موقت با مقدار متغیر در آن لحظه جایگزین می‌شود.

معاملات PDO

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

به عنوان یک مثال افراطی و عجیب، تصور کنید که کاربر باید فهرستی از سیارات را انتخاب می‌کرد و هر بار که انتخاب جدیدی انجام می‌داد، قبل از درج سیارات جدید، باید سیارات قبلی را از پایگاه داده حذف کنید. اگر حذف اتفاق بیفتد اما درج نشد چه؟ ما یک کاربر بدون سیاره به دست خواهیم آورد! اساساً تراکنش ها به این صورت اعمال می شوند:

$pdo->beginTransaction(); try ($stmt1 = $pdo->exec("DELETE FROM planets"); $stmt2 = $pdo->prepare("INSERT INTO planets(name, color) VALUES (?, ?)"); foreach ($planets as $planet) ($stmt2->execute([$planet->getName()، $planet->getColor()]؛ ) $pdo->commit(); ) catch (PDOException $e) ($pdo-> rollBack();)

اول از همه، متد beginTransaction() روی شی PDO، Autocommit درخواست را غیرفعال می‌کند، سپس درخواست‌ها به ترتیب مورد نیاز شروع می‌شوند. در این مرحله، مگر اینکه یک PDOException رخ دهد، درخواست‌ها به طور خودکار از طریق متد ()commit ارسال می‌شوند؛ در غیر این صورت، تراکنش‌ها از طریق متد rollBack() لغو می‌شوند و commit خودکار بازیابی می‌شود.

به این ترتیب، با درخواست های متعدد، همیشه سازگاری وجود خواهد داشت. این کاملا واضح است، اما تراکنش‌های PDO فقط می‌توانند توسط PDO::ATTR_ERRMODE که روی PDO::ERRMODE_EXCEPTION تنظیم شده است، استفاده شوند.

ابتدا بیایید پایگاه داده این آموزش را ایجاد کنیم:

ایجاد پایگاه داده solar_system. اعطای تمام امتیازات به solar_system.* به "testuser"@"localhost" که با "testpassword" شناسایی شده است.

به کاربری با testuser ورود و رمز عبور testpassword حقوق دسترسی کامل به پایگاه داده solar_system اعطا شد.

حال بیایید یک جدول ایجاد کنیم و آن را با داده هایی پر کنیم که دقت نجومی آن به طور ضمنی مشخص نیست:

استفاده از solar_system; CREATE TABLE سیارات (id TINYINT(1) Unsigned NOT NULL AUTO_INCREMENT، PRIMARY KEY(id)، نام VARCHAR(10) NOT NULL، رنگ VARCHAR(10) NOT NULL). INSERT INTO سیارات (نام، رنگ) VALUES ("زمین"، "آبی")، ("مریخ"، "قرمز")، ("مشتری"، "عجیب");

توضیحات اتصال

اکنون که پایگاه داده ایجاد شده است، بیایید DSN () را تعریف کنیم - اطلاعاتی برای اتصال به پایگاه داده، ارائه شده به عنوان یک رشته. نحو توصیف بسته به DBMS مورد استفاده متفاوت است. در مثالی که ما با MySQL/MariaDB کار می کنیم، بنابراین نشان می دهیم:

  • نام میزبانی که DBMS در آن قرار دارد.
  • پورت (در صورت استفاده از پورت استاندارد 3306 اختیاری است)؛
  • نام پایگاه داده؛
  • رمزگذاری (اختیاری).

خط DSN در این مورد به صورت زیر است:

$dsn = "mysql:host=localhost;port=3306;dbname=solar_system;charset=utf8";

ابتدا پیشوند پایگاه داده مشخص می شود. در مثال - mysql. پیشوند با یک دونقطه از بقیه خط جدا می شود و هر پارامتر بعدی با یک نقطه ویرگول از هم جدا می شود.

ایجاد یک شی PDO

اکنون که رشته DSN آماده است، بیایید یک شی PDO ایجاد کنیم. سازنده ورودی پارامترهای زیر را می پذیرد:

  1. رشته DSN.
  2. نام کاربری که به پایگاه داده دسترسی دارد.
  3. رمز عبور این کاربر
  4. آرایه ای با پارامترهای اضافی (اختیاری).
$options = [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION، PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC ]; $pdo = PDO جدید ($dsn، "testuser"، "testpassword"، $options);

پارامترهای اضافی را نیز می توان پس از ایجاد شی با استفاده از متد SetAttribute تعریف کرد:

$pdo->SetAttribute(PDO::ATTR_ERRMODE، PDO::ERRMODE_EXCEPTION);

تعریف روش نمونه گیری پیش فرض

PDO::DEFAULT_FETCH_MODE پارامتر مهمی است که روش واکشی پیش‌فرض را تعیین می‌کند. روش مشخص شده هنگام به دست آوردن نتیجه یک درخواست استفاده می شود.

PDO::FETCH_BOTH

حالت پیش فرض. نتیجه انتخاب با هر دو عدد (شروع از 0) و نام ستون نمایه می شود:

$stmt = $pdo->query("SELECT * FROM planets"); $results = $stmt->fetch(PDO::FETCH_BOTH);

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

آرایه (=> 1 => 1 => زمین => زمین => آبی => آبی)

PDO::FETCH_ASSOC

نتیجه در یک آرایه انجمنی ذخیره می شود که در آن کلید نام ستون و مقدار آن مقدار ردیف مربوطه است:

$stmt = $pdo->query("SELECT * FROM planets"); $results = $stmt->fetch(PDO::FETCH_ASSOC);

در نتیجه دریافت می کنیم:

آرایه (=> 1 => زمین => آبی)

PDO::FETCH_NUM

هنگام استفاده از این حالت، نتیجه به عنوان یک آرایه نمایه شده توسط اعداد ستون ارائه می شود (شروع از 0):

آرایه (=> 1 => زمین => آبی)

PDO::FETCH_COLUMN

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

$stmt = $pdo->query("SELECT name FROM planets");

در نتیجه دریافت می کنیم:

آرایه (=> زمین => مریخ => مشتری)

PDO::FETCH_KEY_PAIR

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

$stmt = $pdo->query("انتخاب نام، رنگ از سیاره ها"); $result = $stmt->fetchAll(PDO::FETCH_KEY_PAIR);

در نتیجه دریافت می کنیم:

آرایه (=> آبی => قرمز => عجیب)

PDO::FETCH_OBJECT

هنگام استفاده از PDO::FETCH_OBJECT، یک شی ناشناس برای هر ردیف واکشی شده ایجاد می شود. ویژگی های عمومی آن نام ستون های نمونه است و نتایج پرس و جو به عنوان مقادیر آنها استفاده می شود:

$stmt = $pdo->query("انتخاب نام، رنگ از سیاره ها"); $results = $stmt->fetch(PDO::FETCH_OBJ);

در نتیجه دریافت می کنیم:

شیء StdClass (=> زمین => آبی)

PDO::FETCH_CLASS

در این مورد، مانند مورد قبلی، مقادیر ستون به ویژگی های شی تبدیل می شوند. با این حال، شما باید یک کلاس موجود را مشخص کنید که برای ایجاد شی مورد استفاده قرار می گیرد. بیایید با یک مثال به این موضوع نگاه کنیم. ابتدا بیایید یک کلاس ایجاد کنیم:

Class Planet ( $name خصوصی; خصوصی $color; تابع عمومی setName($planet_name) ( $this->name = $planet_name; ) تابع عمومی setColor($planet_color) ($this->color = $planet_color; ) تابع عمومی getName () ( return $this->name; ) تابع عمومی getColor() ( return $this->color; ) )

لطفاً توجه داشته باشید که کلاس Planet دارای خصوصیات خصوصی است و سازنده ندارد. حالا بیایید درخواست را اجرا کنیم.

اگر از روش واکشی با PDO::FETCH_CLASS استفاده می کنید، باید قبل از ارسال درخواست برای واکشی داده ها، از روش setFetchMode استفاده کنید:

$stmt = $pdo->query("انتخاب نام، رنگ از سیاره ها"); $stmt->setFetchMode(PDO::FETCH_CLASS، "Planet");

اولین پارامتری که به متد setFetchMode می دهیم، ثابت PDO::FETCH_CLASS است. پارامتر دوم نام کلاسی است که هنگام ایجاد شی مورد استفاده قرار می گیرد. حالا بیایید انجام دهیم:

$planet = $stmt->fetch(); var_dump ($planet);

در نتیجه، یک شی سیاره به دست می آوریم:

شی سیاره (=> زمین => آبی)

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

تعریف خواص پس از اجرای سازنده

کلاس Planet سازنده صریح ندارد، بنابراین هیچ مشکلی در تخصیص خصوصیات وجود نخواهد داشت. اگر یک کلاس سازنده ای داشته باشد که ویژگی در آن تخصیص داده شده یا تغییر کرده باشد، آنها رونویسی می شوند.

هنگام استفاده از ثابت FETCH_PROPS_LATE، مقادیر ویژگی پس از اجرای سازنده تخصیص داده می شود:

Class Planet ( $name خصوصی؛ $color خصوصی؛ تابع عمومی __construct($name = ماه، $color = خاکستری) ($this->name = $name; $this->color = $color; ) تابع عمومی setName($ planet_name) ($this->name = $planet_name; ) تابع عمومی setColor($planet_color) ($this->color = $planet_color; ) تابع عمومی getName() ( return $this->name; ) تابع عمومی getColor() ( بازگشت $this->color; ) )

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

اگر از FETCH_PROPS_LATE استفاده نمی کنید، هنگام ایجاد شی، ویژگی ها با مقادیر پیش فرض بازنویسی می شوند. بگذار چک کنیم. ابتدا کوئری را اجرا می کنیم:

$stmt = $pdo->query("SELECT name, color FROM solar_system WHERE name = "earth""); $stmt->setFetchMode(PDO::FETCH_CLASS، "Planet"); $planet = $stmt->fetch(); var_dump ($planet);

در نتیجه دریافت می کنیم:

Object(Planet)#2 (2) (["name":"Planet":private]=> string(4) "moon" ["color":"Planet":private]=> string(4) "grey" )

همانطور که انتظار می رود، مقادیر بازیابی شده از پایگاه داده بازنویسی می شوند. اکنون بیایید به حل مشکل با استفاده از FETCH_PROPS_LATE (یک درخواست مشابه) نگاه کنیم:

$stmt->setFetchMode(PDO::FETCH_CLASS|PDO::FETCH_PROPS_LATE، "Planet"); $planet = $stmt->fetch(); var_dump ($planet);

در نتیجه، آنچه را که نیاز داریم به دست می آوریم:

Object(Planet)#4 (2) ( ["name":"Planet":private]=> string(5) "earth" ["color":"Planet":private]=> string(4) "blue" )

اگر سازنده کلاس مقادیر پیش‌فرض نداشته باشد و به آن‌ها نیاز باشد، پارامترهای سازنده هنگام فراخوانی متد setFetchMode با آرگومان سوم در قالب یک آرایه تنظیم می‌شوند. مثلا:

Class Planet ($name خصوصی; خصوصی $color; تابع عمومی __construct($name, $color) ($this->name = $name; $this->color = $color; ) [...] )

آرگومان های سازنده مورد نیاز است، بنابراین بیایید انجام دهیم:

$stmt->setFetchMode(PDO::FETCH_CLASS|PDO::FETCH_PROPS_LATE، "سیاره"، ["ماه"، "خاکستری"]);

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

بازیابی چندین شی

چندین نتیجه به عنوان اشیا با استفاده از روش fetch در داخل حلقه while واکشی می شوند:

while ($planet = $stmt->fetch()) ( // نتایج پردازش )

یا با نمونه برداری از همه نتایج به طور همزمان. در حالت دوم، از متد fetchAll استفاده می شود و حالت در زمان تماس مشخص می شود:

$stmt->fetchAll(PDO::FETCH_CLASS|PDO_FETCH_PROPS_LATE، "سیاره"، ["ماه"، "خاکستری"]);

PDO::FETCH_INTO

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

درخواست های آماده و مستقیم

دو روش برای اجرای پرس و جو در PDO وجود دارد:

  • مستقیم، که از یک مرحله تشکیل شده است.
  • تهیه شده که شامل دو مرحله می باشد.

درخواست های مستقیم

دو روش برای انجام پرس و جوهای مستقیم وجود دارد:

  • query برای عباراتی که تغییری ایجاد نمی کنند مانند SELECT استفاده می شود. یک شی PDOSstatemnt را برمی‌گرداند که نتایج پرس و جو از آن با استفاده از متدهای fetch یا fetchAll بازیابی می‌شوند.
  • exec برای عباراتی مانند INSERT، DELETE یا UPDATE استفاده می شود. تعداد ردیف های پردازش شده توسط درخواست را برمی گرداند.

عملگرهای مستقیم فقط در صورتی استفاده می شوند که هیچ متغیری در پرس و جو وجود نداشته باشد و شما مطمئن باشید که پرس و جو ایمن است و به درستی فرار شده است.

پرس و جوهای آماده شده

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

بیایید به یک مثال نگاه کنیم. شما می خواهید ویژگی های یک شی Planet را در جدول Planets وارد کنید. ابتدا بیایید درخواست را آماده کنیم:

$stmt = $pdo->prepare("INSERT INTO planets(name, color) VALUES(?, ?)");

ما از متد آماده استفاده می کنیم که یک پرس و جوی SQL با متغیرهای شبه (placeholder) را به عنوان آرگومان می گیرد. متغیرهای شبه می توانند دو نوع باشند: بی نام و نام.

متغیرهای شبه بی نام

متغیرهای کاذب بدون نام (جایگزین‌های موقعیتی) با ? . پرس و جوی به دست آمده فشرده است، اما نیاز دارد که مقادیر به همان ترتیب جایگزین شوند. آنها به عنوان یک آرایه از طریق متد execute ارسال می شوند:

$stmt->execute([$planet->name, $planet->color]);

به نام شبه متغیرها

هنگام استفاده از متغیرهای نامگذاری شده، ترتیب ارسال مقادیر برای جایگزینی مهم نیست، اما کد در این مورد کمتر فشرده می شود. داده ها در قالب یک آرایه انجمنی به متد execute ارسال می شوند که در آن هر کلید با نام یک متغیر شبه مطابقت دارد و مقدار آرایه مربوط به مقداری است که باید در درخواست جایگزین شود. بیایید مثال قبلی را دوباره انجام دهیم:

$stmt = $pdo->prepare("INSERT INTO planets(name, color) VALUES(:name, :color)"); $stmt->execute(["name" => $planet->name, "color" => $planet->color]);

روش های آماده سازی و اجرا هم هنگام اجرای درخواست های تغییر و هم هنگام واکشی استفاده می شود.

و اطلاعات مربوط به تعداد ردیف های پردازش شده ، در صورت لزوم ، با روش RowCount ارائه می شود.

کنترل رفتار خطای PDO

پارامتر انتخاب حالت خطا PDO :: ATTR_ERRMODE برای تعیین نحوه رفتار PDO در صورت بروز خطاها استفاده می شود. سه گزینه در دسترس است: pdo :: ermode_silent ، pdo :: ermode_exception و pdo :: ermode_warning.

PDO::ERRMODE_SILENT

گزینه پیش فرض PDO به سادگی اطلاعات مربوط به خطا را ضبط می کند ، که کد ErrorCode و ErrorInfo به شما در بدست آوردن کمک می کند.

PDO::ERRMODE_EXCEPTION

این گزینه ارجح است که در آن PDO علاوه بر اطلاعات خطا ، یک استثنا (PDOException) را پرتاب می کند. یک استثناء اجرای اسکریپت را قطع می کند ، که هنگام استفاده از معاملات PDO مفید است. نمونه ای در توضیحات معاملات آورده شده است.

PDO::ERRMODE_WARNING

در این حالت ، PDO همچنین اطلاعات خطا را ثبت می کند. جریان فیلمنامه قطع نمی شود ، اما هشدارها صادر می شود.

متدهای bindValue و bindParam

همچنین می توانید از روشهای BindValue و BindParam برای جایگزینی مقادیر در یک پرس و جو استفاده کنید. اولین مقدار متغیر را با شبه متغیر که برای تهیه درخواست استفاده می شود ، مرتبط می کند:

$stmt = $pdo->prepare("INSERT INTO planets(name, color) VALUES(:name, :color)"); $stmt->bindValue("name", $planet->name, PDO::PARAM_STR);

مقدار متغیر $ Planet-> Name را به متغیر شبه پیوند دهید: نام. توجه داشته باشید که هنگام استفاده از متدهای bindValue و bindParam، نوع متغیر به عنوان آرگومان سوم با استفاده از ثابت‌های PDO مناسب مشخص می‌شود. در مثال - PDO::PARAM_STR .

متد bindParam یک متغیر را به یک متغیر شبه متصل می کند. در این حالت، متغیر با یک مرجع شبه متغیر مرتبط است و تنها پس از فراخوانی متد execute، مقدار در درخواست درج می‌شود. بیایید به یک مثال نگاه کنیم:

$stmt->bindParam("name", $planet->name, PDO::PARAM_STR);

معاملات در PDO

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

$pdo->beginTransaction(); try ($stmt1 = $pdo->exec("DELETE FROM planets"); $stmt2 = $pdo->prepare("INSERT INTO planets(name, color) VALUES (?, ?)"); foreach ($planets as $planet) ($stmt2->execute([$planet->getName()، $planet->getColor()]؛ ) $pdo->commit(); ) catch (PDOException $e) ($pdo-> rollBack();)

متد beginTransaction اجرای خودکار درخواست ها را غیرفعال می کند و در داخل ساختار try-catch درخواست ها به ترتیب دلخواه اجرا می شوند. اگر هیچ PDOException پرتاب نشود، درخواست ها با استفاده از روش commit تکمیل می شوند. در غیر این صورت، آنها با استفاده از روش بازگشت به عقب برگشت داده می شوند و اجرای خودکار کوئری ها بازیابی می شود.

این امر باعث ایجاد ثبات در اجرای پرس و جو می شود. بدیهی است که برای این کار، PDO::ATTR_ERRMODE باید روی PDO::ERRMODE_EXCEPTION تنظیم شود.

نتیجه

اکنون که کار با PDO توضیح داده شد، اجازه دهید مزایای اصلی آن را یادداشت کنیم:

  • با PDO انتقال برنامه به DBMS های دیگر آسان است.
  • همه DBMS های محبوب پشتیبانی می شوند.
  • سیستم مدیریت خطا داخلی؛
  • گزینه های مختلف برای ارائه نتایج نمونه؛
  • پرس و جوهای آماده شده پشتیبانی می شوند، که کد را کوتاه می کند و آن را در برابر تزریق SQL مقاوم می کند.
  • تراکنش‌ها پشتیبانی می‌شوند، که به حفظ یکپارچگی داده‌ها و سازگاری پرس و جو در زمانی که کاربران به طور موازی کار می‌کنند، کمک می‌کنند.

الکساندر نالیوایکو، مترجم

چگونه Yandex از داده ها و یادگیری ماشین شما برای شخصی سازی خدمات استفاده می کند -.












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

نمونه ای از اتصال صحیح:

$host = "127.0.0.1" ;
$db = "تست" ;
$user = "root" ;
$pass = "" ;
$charset = "utf8" ;

$dsn = "mysql:host= $host ;dbname= $db ;charset= $charset " ;
$opt = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION،
PDO :: ATTR_DEFAULT_FETCH_MODE => PDO :: fetch_assoc ،
PDO::ATTR_EMULATE_PREPARES => نادرست،
];
$pdo = PDO جدید ($dsn، $user، $pass، $opt)؛

اینجا چه خبره؟

$ DSN نوع پایگاه داده ای را که ما با آن کار خواهیم کرد (MySQL) ، میزبان ، نام بانک اطلاعاتی و charset را مشخص می کند.
- به دنبال آن نام کاربری و رمز عبور
- پس از آن مجموعه ای از گزینه ها مشخص شده است که در هیچ یک از کتابچه ها در مورد آن نوشته نشده است.

با وجود این واقعیت که این آرایه یک چیز بسیار مفید است ، همانطور که در بالا ذکر شد. مهمترین چیز این است که حالت خطا فقط باید به صورت استثنائات تنظیم شود.
- اولا ، زیرا در همه حالت های دیگر PDO هیچ چیز قابل فهم در مورد خطا را گزارش نمی کند ،
- ثانیا ، زیرا استثنا همیشه حاوی یک ردپای پشته غیر قابل تعویض است ،
- سوم ، استثنائات برای رسیدگی بسیار راحت هستند.

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

در نتیجه، متغیر $pdo را دریافت می کنیم که در کل اسکریپت با آن کار می کنیم.

برای اجرای پرس و جو می توانید از دو روش استفاده کنید.
اگر هیچ متغیری به درخواست ارسال نشود، می توانید از تابع query() استفاده کنید. این درخواست را اجرا می کند و یک شی خاص - عبارت PDO را برمی گرداند. تقریباً می توانید آن را با منبع mysql که توسط mysql_query() برگردانده شده است مقایسه کنید. شما می توانید داده ها را از این شی به روش سنتی، از طریق while، یا از طریق () foreach دریافت کنید. همچنین می توانید درخواست کنید که داده های دریافتی را در قالب خاصی که در ادامه به آن پرداخته شده است، بازگردانید.
$stmt = $pdo -> query ("SELECT name FROM users" );
while ($row = $stmt -> fetch())
{
}

اگر حداقل یک متغیر به درخواست ارسال شود، این درخواست باید فقط از طریق اجرا شود عبارات آماده شده. آن چیست؟ این یک پرس و جو معمولی SQL است که در آن یک نشانگر ویژه به جای یک متغیر - یک مکان نگه دارنده قرار می گیرد. PDO از متغیرهای موقعیتی (؟) پشتیبانی می کند ، که ترتیب متغیرهای تصویب شده از آن مهم است ، و متغیرهای نامگذاری شده (: نام) ، که برای آن نظم مهم نیست. مثال ها:
$sql = ;
$sql = ;

برای اجرای چنین پرس و جوی ابتدا باید با استفاده از تابع ()preparate آماده شود. همچنین یک عبارت PDO را برمی گرداند، اما هنوز هیچ داده ای ندارد. برای دریافت آنها، باید این درخواست را اجرا کنید، زیرا قبلاً متغیرهایی را به آن منتقل کرده اید. شما می توانید آن را به دو صورت انتقال دهید:
بیشتر اوقات ، شما می توانید به سادگی روش اجرای () را اجرا کنید ، و به آن یک آرایه از متغیرها منتقل کنید:
$stmt = $pdo -> آماده کردن ( "انتخاب نام از کاربران WHERE email = ?");
$stmt -> execute (array($email ));

$stmt = $pdo -> آماده کردن ( "انتخاب نام از کاربران WHERE email = :email");
$stmt -> execute (array("email" => $email ));
همانطور که می بینید، در مورد متغیرهای نامگذاری شده، آرایه ای که در آن کلیدها باید با نام متغیرهای نگهدارنده مطابقت داشته باشند، باید برای execute() ارسال شود.

گاهی اوقات، به ندرت، ممکن است متد دوم مورد نیاز باشد، زمانی که متغیرها ابتدا با استفاده از bindValue() / bindParam() به درخواست متصل می شوند و سپس اجرا می شوند. در این حالت، هیچ چیزی برای اجرا (). یک مثال را می توان در دفترچه راهنما یافت.
هنگام استفاده از این روش ، باید BindValue () همیشه ترجیح داده شود؟ از آنجا که رفتار Bindparam () برای مبتدیان آشکار نیست و منجر به مشکلات خواهد شد.

سپس می توانید از جمله PDO به همان روشهای فوق استفاده کنید. به عنوان مثال، از طریق foreach:
$stmt = $pdo -> آماده کردن ( "انتخاب نام از کاربران WHERE email = ?");
$stmt ->
foreach ($stmt به عنوان $row)
{
echo $row [ "name" ] . "\n" ;
}

مهم:عبارات آماده شده دلیل اصلی استفاده از PDO هستند زیرا آن را دارد تنها راه امناجرای پرس و جوهای SQL که شامل متغیرها می شود.

همچنین برای اجرای مکرر یک کوئری یک بار آماده شده با مجموعه داده های مختلف می توان از ()prepare/execute() استفاده کرد. در عمل، این بسیار به ندرت مورد نیاز است و افزایش سرعت زیادی به همراه ندارد. اما درصورتی‌که نیاز به درخواست‌های زیادی از یک نوع دارید، می‌توانید آن را به صورت زیر بنویسید:

$data = آرایه(
1 => 1000,
5 => 300,
9 => 200,
);

$stmt = $pdo -> آماده کردن ( "به روز رسانی کاربران پاداش = پاداش + را تنظیم می کنند؟ شناسه کجا = ?");
foreach ($data به عنوان $id => $bonus)
{
$stmt -> execute ([ $bonus , $id ]);
}

در اینجا یک بار درخواست را آماده می کنیم و سپس چندین بار آن را اجرا می کنیم.

ما قبلاً با متد fetch() آشنا شده ایم که برای به دست آوردن پی در پی سطرها از پایگاه داده استفاده می شود. این روش یک آنالوگ از عملکرد MySQ_FETCH_ARRAY () و موارد مشابه است ، اما متفاوت عمل می کند: به جای بسیاری از کارکردها ، در اینجا یکی استفاده می شود ، اما رفتار آن توسط پارامتر گذشت مشخص می شود. من بعداً در مورد این پارامترها به تفصیل خواهم نوشت، اما به عنوان یک توصیه کوتاه، استفاده از fetch() را در حالت FETCH_LAZY توصیه می کنم:
$stmt = $pdo -> آماده کردن ( "انتخاب نام از کاربران WHERE email = ?");
$stmt -> execute([ $_GET [ "email" ]]);
while ($row = $stmt -> fetch (PDO :: FETCH_LAZY ))
{
echo $ row [ 0 ] . "\n" ;
echo $row [ "name" ] . "\n" ;
echo $row -> name . "\n" ;
}

در این حالت، هیچ حافظه اضافی هدر نمی رود، و علاوه بر این، می توان به ستون ها به هر یک از سه روش دسترسی داشت - از طریق فهرست، نام یا ویژگی.

دستور PDO همچنین یک تابع کمکی برای بدست آوردن مقدار یک ستون دارد. اگر فقط یک فیلد درخواست کنیم بسیار راحت است - در این مورد میزان نوشتن به میزان قابل توجهی کاهش می یابد:
$stmt = $pdo -> آماده کردن ( "انتخاب نام از جدول WHERE id=؟");
$stmt -> execute (array($id ));
$name = $stmt -> fetchColumn();

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

FetchAll() آرایه ای را برمی گرداند که شامل تمام ردیف هایی است که پرس و جو برگردانده است. که از آن دو نتیجه می توان گرفت:
1. این تابع نباید زمانی استفاده شود که پرس و جو داده های زیادی را برمی گرداند. در این مورد، بهتر است از یک حلقه سنتی با ()fetch استفاده کنید.
2. از آنجا که در برنامه های کاربردی PHP مدرن هرگز بلافاصله پس از دریافت ، اما برای این منظور به یک الگوی منتقل نمی شود ، Fetchall () به سادگی غیرقابل جبران می شود ، به شما امکان می دهد از نوشتن حلقه ها به صورت دستی جلوگیری کنید و از این طریق میزان کد را کاهش دهید.

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

گرفتن یک ستون
گاهی اوقات شما نیاز دارید که با درخواست یک فیلد از مجموعه ای از رشته ها، یک آرایه تک بعدی ساده بدست آورید. برای این کار از حالت PDO::FETCH_COLUMN استفاده کنید
$data = $pdo -> query ("SELECT name FROM users" ) -> fetchAll (PDO :: FETCH_COLUMN );
آرایه (
0 => "جان"،
1 => "مایک"،
2 => "مریم"،
3 => "کتی"،
)

بازیابی جفت های کلید-مقدار.
همچنین یک قالب محبوب برای دریافت همان ستون، اما نه با اعداد، بلکه توسط یکی از فیلدها نمایه می شود. ثابت PDO::FETCH_KEY_PAIR مسئول این است.
$data = $pdo -> query ("SELECT id, name FROM users" ) -> fetchAll (PDO :: FETCH_KEY_PAIR );
آرایه (
104 => "جان"،
110 => "مایک"،
120 => "مریم"،
121 => "کتی"،
)

همه سطرها را با یک فیلد نمایه کنید.
همچنین اغلب لازم است که تمام ردیف ها را از پایگاه داده دریافت کنید، اما همچنین نه با اعداد، بلکه توسط یک فیلد منحصر به فرد نمایه می شوند. ثابت PDO::FETCH_UNIQUE این کار را انجام می دهد.
$data = $pdo -> query ("SELECT * FROM users") -> fetchAll (PDO :: FETCH_UNIQUE );
آرایه (
104 => آرایه (
"name" => "جان"،
"car" => "Toyota" ,
),
110 => آرایه (
"name" => "مایک" ,
"car" => "Ford" ,
),
120 => آرایه (
"name" => "مریم"
"car" => "مزدا" ,
),
121 => آرایه (
"name" => "کتی"،
"car" => "مزدا" ,
),
)

لازم به یادآوری است که ابتدا باید یک فیلد منحصر به فرد را در ستون انتخاب کنید.

بیش از یک و نیم دوجین حالت مختلف جمع آوری داده در PDO وجود دارد. به علاوه می توانید آنها را ترکیب کنید! اما این موضوع برای یک مقاله جداگانه است.

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

$name = "% $name %" ;
$stm = $pdo -> آماده کردن ( "انتخاب * از جدول WHERE نام LIKE؟");
$stm -> execute (array($name ));
$data = $stm -> fetchAll();

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

در MySQL ، برای قالب بندی دستی یک شناسه ، شما باید دو کار را انجام دهید:
- آن را در بکتیک ("`") محصور کنید.
- با دو برابر کردن این شخصیت ها را در داخل شناسه جستجو کنید.

$field = "`" . str_replace ("`" , "``" , $_GET [ "فیلد" ]). "`" ;
$sql = $field " ;

با این حال، در اینجا یک اخطار وجود دارد. ممکن است قالب بندی به تنهایی کافی نباشد. کد فوق ما را از تزریق کلاسیک محافظت می کند ، اما در بعضی موارد دشمن هنوز هم می تواند چیزی ناخواسته بنویسد اگر بی فکر نام فیلد و نام جدول را مستقیماً در پرس و جو جایگزین کنیم. به عنوان مثال، در جدول کاربران یک قسمت مدیریت وجود دارد. اگر نام فیلدهای ورودی فیلتر نشده باشد ، پس از تولید خودکار درخواست از یک پست ، هر احمق چیزهای ناخوشایندی را در این زمینه می نویسد.

بنابراین، توصیه می‌شود که نام جداول و فیلدهای دریافتی از کاربر را از نظر اعتبار بررسی کنید، مانند مثال زیر.

هر کد جاسازی که در آموزش‌های متعدد دیده می‌شود، مایه‌ی مالیخولیا و میل به کشتن apsten را به همراه دارد. ساخت و سازهای چند کیلومتری با تکرار همین نامها - در فهرست $ _Post ، در نام های متغیر ، در نام های فیلد در یک درخواست ، در نام های نگهدارنده در یک درخواست ، در نام های نگهدارنده ، در نام های نگهدارنده و نام های متغیر هنگام اتصال.
نگاه کردن به این کد باعث می شود که بخواهم کسی را بکشم یا حداقل آن را کمی کوتاهتر کنم.

این را می توان با اتخاذ یک قرارداد انجام داد که نام فیلدهای موجود در فرم با نام فیلدها در جدول مطابقت داشته باشد. سپس این نامها فقط یک بار ذکر شده است (برای محافظت در برابر جایگزینی ، که در بالا به آن اشاره شد) ، و از یک عملکرد یاور کوچک می توان برای جمع آوری پرس و جو استفاده کرد ، که به دلیل ویژگی های MySQL ، هم برای درج و هم برای درج مناسب است و به روز رسانی پرس و جو:

تابع pdoSet ($allowed، & $values، $source = array()) (
$set = "" ;
$values ​​= آرایه();
اگر (! $source ) $source = & $_POST ;
foreach ($ مجاز به عنوان $field) (
if (isset($source [ $field ])) (
$set .= "`" . str_replace ("`" , "``" , $field ). """. "=: $field , " ;
$values ​​[ $field ] = منبع $ [ $field ];
}
}
برگشت substr ($set, 0, - 2);
}

بر این اساس کد جاسازی خواهد بود

$allowed = array("name" , "name" , "email" ); // فیلدهای مجاز
$sql = "INSERT INTO User SET " . pdoSet ($ مجاز، $values)؛
$stm = $dbh -> آماده ($sql );
$stm -> execute ($values);

و برای به روز رسانی - این:

$allowed = array("name" , "نام خانوادگی" , "email" , "password" ); // فیلدهای مجاز
$_POST ["رمز عبور" ] = MD5 ($_POST [ "ورود" ]. $_POST [ "رمز عبور" ]);
$sql = "به روز رسانی تنظیمات کاربران " . pdoSet ($ مجاز، $values). "WHERE id = :id" ;
$stm = $dbh -> آماده ($sql );
$values ​​["id" ] = $_POST ["id" ];
$stm -> execute ($values);

خیلی تاثیرگذار نیست، اما بسیار موثر است. به هر حال، به شما یادآوری می کنم که اگر از Class برای کار ایمن و راحت با MySQL استفاده می کنید، همه این کارها در دو خط انجام می شود.

PDO و کلمات کلیدی
غیرممکن است که در اینجا به چیزی غیر از فیلتر کردن دست پیدا کنید. بنابراین، احمقانه است که همه اپراتورهایی را که مستقیماً در درخواست مشخص نشده اند از طریق لیست سفید اجرا کنید:

$dirs = array("ASC" , "DESC" );
$key = array_search($_GET["dir"]، $dirs));
$dir = $orders [ $key ];
$sql = «انتخاب * از «جدول» به ترتیب$field $dir " ;



 


خواندن:



بررسی Samsung Galaxy A5 (2017): متوسط ​​با محافظت در برابر آب و سلفی های جالب

بررسی Samsung Galaxy A5 (2017): متوسط ​​با محافظت در برابر آب و سلفی های جالب

سامسونگ گلکسی A5 2017 با سرعت نور به فروش می رسد. اما آیا گوشی هوشمند واقعا ارزش پول را دارد؟ پردازنده، دوربین، اسپیکر را جدا می کنیم سامسونگ...

ترویج اکوتوریسم به عنوان راهی برای توسعه آگاهی زیست محیطی (با استفاده از مثال روستای Russkinskiye) نحوه ترویج یک برنامه زیست محیطی

ترویج اکوتوریسم به عنوان راهی برای توسعه آگاهی زیست محیطی (با استفاده از مثال یک روستا

ما لیستی از پیوندهای سایت های اینترنتی در مورد موضوعات زیست محیطی و زیست محیطی را به توجه شما ارائه می کنیم. http://www.nature.ok.ru/ نادر و...

لنا میرو: "چرا وقتی تناسب اندام وجود دارد به جادو نیاز دارید؟

لنا میرو:

لنا میرو (النا میروننکو) - نویسنده، فیلمنامه نویس، وبلاگ نویس در LiveJournal. متولد 24 ژوئن 1981 در Stary Oskol روسیه. قد 169...

این چیزی است که در زندگی زنی اتفاق می افتد که می تواند هر کسی را توهین کند

این چیزی است که در زندگی زنی اتفاق می افتد که می تواند هر کسی را توهین کند

این راز نیست که یک صفحه وبلاگ نویس پولی و تبلیغی در اینترنت وجود دارد - لنا میرو خاص. دختر هیچ چیز شگفت انگیزی ندارد...

فید-تصویر RSS