آموزش ارتباط با دیتابیس بوسیله PDO
توی تعطیلات عید تصمیم گرفتم که بیشتر در مورد PHP تحقیق کنم. همین باعث شد که برم سمت یادگیری PDO که روش بهتری برای ارتباط با دیتابیس هستش.
از مزیت های استفاده از PDO این هست که اگر روزی احیانا خواستید از mysql به postgres یا هر سیستم مدیریت پایگاه داده دیگه ای سوییچ کنید PDO به راحت ترین شکل ممکن این کار رو براتون انجام میده. به همین دلیل تصمیم گرفتم کلاسی که نوشتم رو توی انجمن هم بگذارم تا شاید به کار دوستان بیاد.
سعی کردم کلاس رو خوب داکیومنت کنم تا بتونید براحتی ازش استفاده کنید.
/**
* Created By Hossein Ahmadi.<br> * email: <a href="mailto:h.ahmadicorp@gmail.com">h.ahmadicorp@gmail.com</a><hr> * the simple pdo class. * Class PdoDatabase * @author:Hossein Ahmadi * @package PhpTest\Database */ class PdoDatabase{ private $connection; private static $instance; private $params; /** * this class uses singleton design pattern.<br> * don't instantiate class with new PdoDatabase(); * use PdoDatabase::getInstance() instead. * @return PdoDatabase */ public static function getInstance(){ if (self::$instance == null){ self::$instance = new PdoDatabase(); } return self::$instance; } private function __construct(){ //read the ini settings file $this->params = readIni('db.ini'); try{ $this->connection = new \PDO("mysql:host=".$this->params->DB_HOST.";dbname=".$this->params->DB_NAME, $this->params->DB_USER_NAME,$this->params->DB_PASS); echo "Connected!"; }catch (\PDOException $e){ echo $e->getMessage(); } /*configuration of environments. *Please Change the configuration for your own good. */ if ($this->params->ENV == "development"){ $this->connection->setAttribute(\PDO::ATTR_ERRMODE,\PDO::ERRMODE_EXCEPTION); }else if ($this->params->ENV == "production"){ $this->connection->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION); } } /** * perform Transactions.<br>Don't Forget to change Exception Handling.<hr> * @param array $queries * @param null $errorPage * @see http://dev.mysql.com/doc/refman/5.7/en/sql-syntax-transactions.html */ public function transaction(array $queries,$errorPage=null){ try { $this->connection->beginTransaction(); foreach ($queries as $query) { $this->connection->exec($query); } $this->connection->commit(); }catch (\PDOException $e){ $this->connection->rollBack(); if ($this->params->ENV == "development"){ echo $e->getMessage(); }else{ header("Location: ".$errorPage); exit; } } } /** * insert the given query and returns the inserted row id * @param $query * @return string * */ public function insert($query){ $this->connection->exec($query); return $this->connection->lastInsertId(); } /** * prepared query for preventing sql injection attacks * @param $query * @param array $params * @return array * @see https://www.owasp.org/index.php/SQL_Injection */ public function preparedQuery($query,array $params){ $statement = $this->connection->prepare($query); foreach($params as $param){ if (count($param) > 3){ $statement->bindParam($param[0],$param[1],$param[2],$param[3]); }else{ $statement->bindParam($param[0],$param[1],$param[2]); } } $statement->execute(); return $statement->fetchAll(\PDO::FETCH_OBJ); } /** * the simple query for fetching data. please use preparedQuery method instead. * @param $query * @return array * */ public function query($query){ foreach($this->connection->query($query) as $result){ yield $result; } return; } /** * returns the first matching row of dataBase in objective mode<br> * use like this => $fetchedData->name.$fetchedData->id * @param $query * @return mixed */ public function first($query){ $statement = $this->connection->query($query); return $statement->fetch(\PDO::FETCH_OBJ); } /** * updates the table with given query. * @param $query * @return int */ public function update($query){ return $this->connection->exec($query); } /** * close the Database connection. */ public function close(){ $this->connection = null; } /** * inserts Bunch of values to Database Tables with the performance Rights. * @param $sql * @param array $params * @return string */ public function bunchInsert($sql,array $params){ $it = new \ArrayIterator($params); $cit = new \CachingIterator($it); foreach($cit as $value){ $sql .="('".$cit->key()."','".$cit->current()."')"; if ($cit->hasNext()){ $sql .=","; } } $this->connection->exec($sql); return $sql; } }
نحوه استفاده:
$db = PdoDatabase::getInstance();
خوب برای اینکه از دیتابیس query بگیرید اونهم از نوع امنش که sql injection نخوره از این روش استفاده کنید:
$params = ['0'=>[':post_id',$post_id,PDO::PARAM_INT], '1'=>[':phone_number',$phone,PDO::PARAM_STR,strlen($phone)]]; $result = $db->preparedQuery('SELECT * FROM phone WHERE post_id=:post_id AND phone_number=:phone_number',$params); foreach($result as $res){ echo 'id : '.$res->post_id.'<br>'.$res->phone_number.'<br><br>'; }
params$: آرایه ای از کلیدها و مقادیرشون و همچنین پارامتر سوم برای تعیین نوع داده ای و پارامتر چهارم برای تعیین طول در رشته ها است.
برای انجام Transaction از این روش استفاده کنید:
$queries = ["INSERT INTO orders (refid,submit_date) VALUES(1210,'2016-03-26')" ,"INSERT INTO phone (post_id,phone_number) VALUES(2,'09369190591')" ,"INSERT INTO phone (post_id,phone_number) VALUES(3,'09198370872')"]; $db->transaction($queries);
خوب برای استفاده از این روش ابتدا یک آرایه ای از insert ها میسازیم و اونرو به متد transaction پاس میدیم. این متد همچنین یک پارامتر دوم برای زمانیکه transaction درست انجام نشد داره که بصورت پیش فرض ریدایرکت به صفحه ارور 500 هستش.
همچنین اگر خواستید تعداد زیادی insert در یک جدول داشته باشید میتونید از متد زیر استفاده کنید که performance بالایی برای اینکار داره:
$params = ['Test1'=>'Test1 Content','Test2'=>'Test2 Content','Test3'=>'Test3 Content', 'Test4'=>'Test4 Content','Test 5'=>'Test 5 Content']; $returned = $db->bunchInsert("INSERT INTO posts (title,content) VALUES ",$params);
در اینجا هم ابتدا یک آرایه میسازیم که توی اون مقادیری که میخوایم در جدول ذخیره کنیم رو قرار میدیم و سپس متد bunchInsert رو صدا میزنیم و query مون رو به همراه مقادیر بهش میدیم.
استفاده از متد insert هم مانند بقیه است فقط توجه کنید که این متد ID سطری که وارد جدول کردید رو بهتون بر میگردونه.
همچنین دقت به این نکته لازمه که من تنظیمات دیتابیس رو توی فایل ini ذخیره کردم و از این طریق تنظیمات رو میخونم که شما باید روش خودتون رو جایگزین کنید.
همچنین اگر خواستید که از روش غیر امن query بگیرید به این روش عمل کنید:
foreach($db->query('SELECT * FROM phone') as $result){ echo $result['id'].PHP_EOL.$result['phone_number'].PHP_EOL.$result['post_id'].'<br>'; }
موفق باشید.
پاسخگویی و مشاهده پاسخ های این سوال تنها برای اعضای ویژه سایت امکان پذیر است .
چنانچه تمایل دارید به همه بخش ها دسترسی داشته باشید میتوانید از این بخش لایسنس این آموزش را خریداری نمایید .