-
July 21st, 2013, 22:23
#1
هشدار جدی در مورد توابع دیتابیس php و اموزش PDO
سلام و خسته نباشید،
در وب سایت PHP: Hypertext Preprocessor هشدار جدیدی در مورد توابع mysql_* ( مانند mysql_connect , mysql_close , mysql_query و ... ) داده شده که واقعا نیازه اونو جدی بگیرید
تمام این توابع کنار گذاشته شده اند و در ورژن های بعدی حذف خواهند شد
و به زودی تمام اسکریپت هایی که از این توابع استفاده میکنند از کار خواهند افتاد !
پس این تایپک رو جدی بگیرید
متن هشدار خود سایت
همانطور که ذکر شده 2 راه جایگزین پیشنهاد شده
1-استفاده از mysqli
2-استفاده از pdo
خب در سایت های مختلف مقایسه هایی انجام شده که بنده از سایت Web development tutorials, from beginner to advanced | Nettuts+ یک مقایسه رو برای شما بیان میکنم
|
PDO |
|
|
|
|
|
|
|
|
|
|
MySQLi |
|
|
پشتیبانی از دیتابیس |
12 نوع مختلف |
|
|
|
|
|
|
|
|
|
|
تنها mysql |
|
|
API |
شی گرای |
|
|
|
|
|
|
|
|
|
|
شی گرایی + توابع |
|
|
پارامتر های اسمی |
بله |
|
|
|
|
|
|
|
|
|
|
خیر |
|
|
در مورد تفاوت های دیگر با توابع قدیمی mysql در همین تایپک به بحث میپردازم
همچنین ابتدا اموزش PDO رو بیان خواهم کرد و سپس در صورت نیاز MySQLi
با این وجود اگر به هیچ کدام اشنایی نداریم پیشنهاد میکنم حتما از PDO استفاده کنید
تمام مطالب توسط خود بنده نوشته شد است با استفاده از 3 منبع که در پایان ذکر میکنم
کپی برداری از مطالب با ذکر لینک تایپک بلامانع است
ویرایش توسط cooper47 : July 22nd, 2013 در ساعت 05:53
-
-
July 21st, 2013 22:23
# ADS
-
July 22nd, 2013, 02:00
#2
پاسخ : هشدار جدی در مورد توابع دیتابیس php و اموزش PDO
اتصال به دیتابیس
PDO از 12 نوع مختلف دیتابیس پشتیبانی میکند به شرطی که درایور ان نصب باشد،
با این وجود چون قصد جایگزینی توابع mysql_* رو داریم، دیتابیس mysql رو بررسی خواهیم کرد
کد PHP:
$db = new PDO("mysql:host=$host;dbname=$dbname", $user, $pass);
در هنگام ساخت شی PDO یک ارگومان متنی به آن میدهیم که در مثال بالا "mysql:host=$host;dbname=$dbname", $user, $pass می باشد
که host هست ما و متغیر های user pass یوزر و پسورد دیتابیس هستند
دقت کنید تمام توابع با متغیر $db در اموزش بیان میشود و اگر با یک نام دیگر این شی رو ایجاد کردید باید با اون نام توابع رو استفاده کنید
قطع اتصال دیتابیس
برای قطع اتصال تنها کافی هست شی را از بین ببرید و یا مقدار جدید به ان بدهید
با یکی از دستورات بالا دیتابیس بسته خواهد شد.
-
تعداد تشکر ها ازcooper47 به دلیل پست مفید
-
July 22nd, 2013, 02:31
#3
پاسخ : هشدار جدی در مورد توابع دیتابیس php و اموزش PDO
تنظیمات خصوصیات دیتابیس
با استفاده از متد setAttribute میتوانید خصوصیات مورد نظر خود را تنظیم کنید،
این که روش خوبی هست که قبل از کار با دیتابیس خصوصیات رو تنظیم کنید
بعضی از این خصوصیات در لینک PHP: PDO::setAttribute - Manual قابل مشاهده هست
در اینجا به چند خصوصیت مهم می پردازم
PDO::ATTR_ERRMODE
با این خصوصیت تعیین میکنید در هنگام مواجه با ارور در اجرای دستورات ، PDO چگونه برخورد کند
مقادیر این خصوصیت
PDO::ERRMODE_SILENT ( پیش فرض )
با این مقدار تنها اررور در متغیر pdo ذخیره میشود و هیچ عمل دیگری صورت نمیگیرد ( نحوه کار با اررور ذخیره شده رو در اینده توضیح خواهم داد)
PDO::ERRMODE_WARNING
با این مقدار pdo یک هشدار ایجاد میکند که بر حسب کانفیگ شما ، به کاربر نمایش داده میشود یا در فایل ذخیره میشود یا اصلا ذخیره نمیشود.
PDO::ERRMODE_EXCEPTION (پیشنهاد بنده )
با استفاده از این مقدار در صورت برخورد با اررور throw رخ میدهد
دقت کنید برای استفاده از این خصوصیت باید از try catch استفاده کنید
یک مثال برای ست کردن و PDO::ERRMODE_EXCEPTION
کد PHP:
try {
$db = new PDO("mysql:host=$host;dbname=$dbname", $user, $pass); //اتصال
$db->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION ); //ست کردن نحوه نمایش ارور
$db->prepare('DELECT test FROM db'); // یک دستور که باعث ایجاد خطا میشود
}
catch(PDOException $e) {
echo "یک خطا رخ داده است : ".$e->getMessage()ک
}
PDO::ATTR_DEFAULT_FETCH_MODE
با استفاده از این خصوصیت نحوه fetch (خروجی یک ردیف ) را معین میکنید
مقدایر به صورت زیر است
PDO::FETCH_ASSOC
خروجی یک ارایه با اندیس های نام فیلد ها می باشد ( اگر دارای فیلد name باشد مقدار به صورت ['name'] قابل دسترسی هست )
PDO::FETCH_BOUND
یک نوع خاصی از خروجی هست که نیازمند درس های اینده هست، و تا اون موقع بدون توضیح رها میشود
PDO::FETCH_CLASSیک نوع خاصی از خروجی هست که نیازمند درس های اینده هست، و تا اون موقع بدون توضیح رها میشود
PDO::FETCH_NUM
خروجی یک ارایه با اندیس های شماره می باشد ( اگر اولین فیلد name باشد مقدار به صورت [0] قابل دسترسی هست )
PDO::FETCH_BOTH (پیشفرض)
تلفیقی از FETCH_ASSOC و FETCH_NUM
PDO::FETCH_OBJ (پیشنهاد بنده)
خروجی به صورت شی خواهد بود ( اگر در خروجی فیلد name باشد و متغیر $row باشد، مقدار فیلد با $row->name قابل دسترس خواهد بود )
PDO::ATTR_EMULATE_PREPARES
در مورد این در آینده صحبت میکتیم، با این وجود فعلا این مقدار را false قرار بدید(مهم)
نمونه کد برای تغییر خصوصیات
کد PHP:
$db->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_BOTH);
$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
-
تعداد تشکر ها از cooper47 به دلیل پست مفید
-
July 22nd, 2013, 02:42
#4
عضو دائم
پاسخ : هشدار جدی در مورد توابع دیتابیس php و اموزش PDO
اینو هم بنده اضافه کنم حتما باید extention PDO ئ همچنین mysqli روی سرور و php کامپایل گردد در غیر اینصورت از PDO و mysqli نمیتوانید روی سرور استفاده نمایید
روی پنل هایی مانند directadmin - kloxo بصورت default فعال می باشد اما روی پنل هایی مانند سی پنل - پلسک پیش فرض فعال نمی باشد
:: کارشناس فنی هاستینگ و مدیریت سرور
:: کانفیگ حرفه ای سرور مجازی و اختصاصی و رفع اشکال سرور از سال 1388
:: وب سایت :
www.nginxweb.ir | تلفن شرکت:
02191300834
-
تعداد تشکر ها ازnginxweb به دلیل پست مفید
-
July 22nd, 2013, 04:26
#5
پاسخ : هشدار جدی در مورد توابع دیتابیس php و اموزش PDO
متد quote جایگزین تابع mysql_real_escape_string
با استفاده از این متد میتوانید در برابر حملات sql injection برنامه خود را محافظت کنید
دقت داشته باشید قبل از اجرای این کد باید charset را ست کنید
برای utf-8 کد زیر را به کار ببرید
کد PHP:
$db->exec("SET NAMES utf8");
خوب 2 ارگومان تابع دارد
ارگومان اول متغیر ما هست
ارگومان دوم که اختیاری هست نوع متغیر رو بیان میکند برای مثال PDO::PARAM_STR یا PDO::PARAM_INT یا PDO::PARAM_NULL
به توصیه PHP هم دقت کنید
you are
strongly recommended to use
PDO::prepare() to prepare SQL statement
همانطور که ذکر کرده استفاده ازین تابع توصیه نمیشود و سرعت کمتری دارند، به جای اون استفاده از prepare پیشنهاد شده که در اینده اموزش داده خواهد شد
هشدار: این تابع برای تمام نوع متغیر ها quotes ( علامت ' ) را در 2 طرف متغیر قرار میدهد و نیاز به قرار دادن ان در کوئری نیست !
مثال :
کد PHP:
$unsafe = "I'm Ali!"; //متغیر مورد نظر
$safe = $db->quote($unsafe); //مقدار خروجی : 'I''m Ali!'
اجرای کوئری Query با PDO
خوب قسمت اصلی دیتابیس مسلما اجرای دستورات هست
3 متد برای اینکار در PDO موجود هست که به توضیح 2 متد در اینجا اکتفا میکنم
1-متد exec
این متد دستورات شما رو اجرا میکند و تعداد ردیف تحت تاثیر را برمیگرداند ( برای UPDATE , DELETE و CREATE )
هشدار: این متد برای دستورات SELECT به هیچ وجه کاربرد ندارد
هشدار2: این تابع در صورت مواجه با خطا مقدار FALSE را برمیگرداند، برای مقایسه برای جلوگیری از اشتباه شدن مقدار FALSE با 0 باید از ==! استفاده کنید به مثال توجه کنید
کد PHP:
if($db->exec($query) === false ) // درست
echo 'خطا رخ داد';
if($db->exec($query) == false ) // نادرست
echo 'خطا رخ داد';
if(! $db->exec($query) ) //نادرست
echo 'خطا رخ داد';
2-متد query
در صورتی که مایل به اجرای دستورات SELECT هستید ( برای بقیه دستورات هم میتوانید از این متد استفاده کنید ) این متد کاربرد دارد
دقت کنید خروجی این متد یک شئ دیگر هست به نام PDOStatement
و برای پردازش اطلاعات باید اموزش این شی که در اینده مطرح خواهد شد را بخوانید
یک دستور ساده
کد PHP:
$query = "SELECT * FROM `users`";
$result = $db->query($query);
//$result یک شئ از نوع دیگر است
print_r($result->fetchAll());
در مورد متد fetchAll بعدا صحبت خواهد شد فعلا بدانید این متد تمام ردیف ها را برمیگرداند و متد fetch یک ردیف را
3-متد prepare
کار با این متد همانند متد قبلی هست ولی تفاوت هایی دارند که بعدا ذکر خواهد شد
خروجی این متد یک شئ دیگر هست به نام PDOStatement
فعلا بدانید مثال بالا را با prepare میتوان به این شکل اجرا کرد
کد PHP:
$query = "SELECT * FROM `users`";
$result = $db->prepare($query);
$result->execute(); // این خط اضافه شده است
print_r($result->fetchAll());
-
تعداد تشکر ها ازcooper47 به دلیل پست مفید
-
July 22nd, 2013, 05:07
#6
پاسخ : هشدار جدی در مورد توابع دیتابیس php و اموزش PDO
PDOStatement چیست ؟
بعد از اجرای متد های prepare و query خروجی انها به صورت PDOStatement هست،
PDOStatement در واقع شی ای برای پردازش اطلاعات می باشد و دارای متد های مختلفی هست
در اینجا متد های مهم و پر کاربرد ذکر خواهد شد
متغیر $result در اموزش ازین پس یک PDOStatement می باشد
متد setFetchMode
این متد همانند خصوصیت PDO::ATTR_DEFAULT_FETCH_MODE که در پست http://www.webhostingtalk.ir/f148/86678/#post819518 اموزش داده شد نحوه خروجی ردیف ها را تعیین می کند
دقت کنید تفاوت ان این است که تنها برای این شی کاربرد دارد
برای مثال اگر شما 2 PDOStatement دارید و در یکی این خصوصیت را تغییر دهید در دیگری تغییر نمیکند
مقدار پیشفرض ان مقداری است که به PDO::ATTR_DEFAULT_FETCH_MODE دادید
متد fetch
این متد یک ردیف را برمیگرداند ( خروجی بسته به fetchmode میتواند ارایه یا شی باشد )
دقت کنید در ورودی این متد هم میتوانید نحوه خروجی را جدا تنظیم کنید
برای مثال
کد PHP:
$result->fetch(PDO::FETCH_OBJ)
متد fetchAll
این متد ارایه ای از تمام ردیف ها را بر میگرداند ( مقدار هر فیلد ارایه بسته به fetchmode میتواند ارایه یا شی باشد )
دقت کنید در ورودی این متد هم میتوانید نحوه خروجی را جدا تنظیم کنید
متد rowCount
این متد جایگزین متد mysql_num_rows و mysql_affected_rows می باشد
در صورتی که دستور INSERT , UPDATE , DELETE اجرا شده باشد تعداد ردیف های تحت تاثیر قرار گرفته را بر میگرداند
در غیر این صورت در بعضی از دیتابیس ها ( از جمله MySQL ) اگر دستور SELECT اجرا شده باشد تعداد ردیف های انتخابی را برمیگرداند
-
تعداد تشکر ها ازcooper47 به دلیل پست مفید
-
July 22nd, 2013, 05:32
#7
پاسخ : هشدار جدی در مورد توابع دیتابیس php و اموزش PDO
Prepared Statements( متد prepare )
تا اینجا اکثر توضیحات جایگزینی برای توابع mysql بود و با توضیحات بالا تقریبا میتوانید توابع را جایگزین کنید
اما دست نگه دارید !
امکان جدیدی اضافه شده است !
Prepared Statements !
با استفاده از این امکان میتوانید سرعت را افزایش دهید ، امنیت کد های خود را بالا ببرید
یکی از کابرد های Prepared Statements این هست که شما میتوانید با استفاده از اون چندین دستور مشابه با ارسال تنها متغیر اجرا کنید،
فرض کنید میخواهید در دیتابیس 2 ردیف ذخیره کنید ، اگر به روش قبلی بخواهید اینکارو انجام بدید باید 2 بار کوئری مشابه بنویسید که تنها مقادیر فیلد ها عوض خواهد شد
اما با Prepared Statements میتوانید یک کوئری بنویسید و مقداری فیلد ها را جداگانه به دیتابیس ارسال کنید
در Prepared Statements شما به جای مقادیر یک مکان قرار میدهید
جایگزین میتواند با نام باشد یا بدون نام
مکان بدون نام
در این روش شما به جای مقدار تنها علامت سوال ( ؟ ) قرار میدهید
برای مثال
کد PHP:
$query = "SELECT * FROM `users` WHERE username = ?";
$result = $db->prepare($query);
مکان با نام
در این روش شما به جای مقدار تنها نامی برای ان مکان انتخاب میکنید ( دقت کنید نام با : شروع می شود )
برای مثال
کد PHP:
$query = "SELECT * FROM `users` WHERE username = :username"; // :username
$result = $db->prepare($query);
مقدار دهی به مکان با متد bindParam از PDOStatement
در هردو روش مکان دهی بعد از اجرای متد prepare خروجی همانطور که ذکر شد شی PDOStatement هست
این شئ متدی به نام bindParam دارد که با کمک ان میتوان مقدار مکان ها را مشخص کرد
برای مثال
در روش بدون نام
ورودی اول شماره مکان است
کد PHP:
$result->bindParam(1, $_POST['username']);
در روش با نام
ورودی اول نام مکان است
کد PHP:
$result->bindParam(':username', $_POST['username']);
دقت کنید برای تاکید ورودی را از متغیر POST دادم ( که کاربر وارد میکنه ) که بیان کنم این روش کاملا در برابر تزریق کد امن هست
اجرای Prepared Statement
برای اجرای کوئری بعد از مقدار دهی به مکان ها با استفاده از متد execute در PDOStatement دستور را اجرا میکنیم
مثال
کد PHP:
$result->execute();
print_r($result->fetchAll);
روش کوتاه برای مقدار دهی مکان ها با تابع execute
مثلا استفاده از تابع bindParam برای تک تک مکان ها کاری سخت هست
روش سریع تری برای اینکار وجود دارد
برای این روش مقداری را به صورت ارایه به متد execute ارسال کنید
در روش بدون نام ارایه بدون اندیس یا با اندیس شماره ها می باشد
در روش با نام اندیس باید نام مکان باشد ( بدون : )
مثال بدون نام
کد PHP:
$query = "SELECT * FROM `users` WHERE username = ? AND password = ?";
$result = $db->prepare($query);
$result->execute(array($username,$password));
مثال با نام
کد PHP:
$query = "SELECT * FROM `users` WHERE username = :username AND password = :password";
$result = $db->prepare($query);
$result->execute(array('username'=>$username,'password'=>$password));
اجرای چند کوئری مشابه با یک کوئری
با استفاده از این امکان میتوانید در سرعت و حجم کد ها تغییر ایجاد کنید
برای اینکار کافی هست ابتدا مکان ها را ست کنید و بعد از اجرای execute مکان های جدید قرار دهید و دوباره دستور execute را اجرا کنید
مثال
کد PHP:
$query = "INSERT INTO `users` (`username`,`password`) VALUES (:username,:password)";
$result = $db->prepare($query);
$result->execute(array('username'=>'test','password'=>'test')); // ساخت یوزر جدید
$result->execute(array('username'=>'admin','password'=>'admin')); // ساخت یوزر دیگر با همان دستور
-
تعداد تشکر ها ازcooper47 به دلیل پست مفید
-
July 22nd, 2013, 09:39
#8
پاسخ : هشدار جدی در مورد توابع دیتابیس php و اموزش PDO
مطالب تکمیلی
PDO::FETCH_BOUND و متد bindColumn از PDOStatement
با استفاده این 2 میتوانید در هنگام fetch به متغیر های از پیش تعریف شده مقدار دهید
مثال
کد PHP:
$db->bindColumn(1,$username); //با شماره
$db->bindColumn('password',$password); //با نام فیلد
while($row = $db->fetch(PDO::FETCH_BOUND))
{
echo $username.'-'.$password;
}
PDO::FETCH_CLASS
با استفاده از این امکان میتوانید خروجی را در یک شی قرار دهید
مثال
کد PHP:
class User
{
public $username;
public $password;
}
$STH->setFetchMode(PDO::FETCH_CLASS, 'User');
while($user = $db->fetch())
{
echo $user->username.'-'.$user->password;
}
PDO::ATTR_EMULATE_PREPARES
قبلا ذکر شد مقدار این خصوصیت را false قرار دهید، اما این خصوصیت چیست
اکثر دیتابیس های جدید از prepare پشتیبانی میکنند ولی ورژن های قدیمی پشتیبانی نمیکنند، هنگامی که این مقدار true باشد pdo عملیات prepare را شبیه سازی میکند،
با این وجود توصیه میشود همیشه این مقدار را خاموش کنید ، چرا که pdo در ورژن جدید php قرار داده شده هست و مسلما هنگامی که ورژن php این هست ورژن دیتابیس هم پشتیبانی خواهد کرد
گرفتن اخرین ای دی ذخیره شده در دیتابیس
کد PHP:
echo $db->lastInsertId();
اخرین ای دی را به شما بر میگرداند
تعداد ردیف های تحت تاثیر قرار گرفته
1-اگر از exec استفاده کردید
متد exec تعداد را بر میگرداند
2-اگر از prepare و query استفاده کردید
متد rowCount از PDOStatement تعداد را بر میگرداند
-
تعداد تشکر ها ازcooper47 به دلیل پست مفید