کلاس پایگاه داده (بخش 2)

(Database Class (Part 2

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

در جلسه قبل با استفاده از فایل Post.php مطمئن شدیم که به پایگاه داده متصل هستیم. در واقع با استفاده از constructor فایل Database.php به پایگاه داده متصل می شویم اما امکانات دیگری به آن اضافه نکرده بودیم. بنابراین در این جلسه می خواهیم آن را تکمیل کنیم.

ابتدا باید قابلیت کار با prepared statement ها را به آن بدهیم بنابراین می گوییم:

// Prepare statement with query
    public function query($sql){
      $this->stmt = $this->dbh->prepare($sql);
    }

اگر یادتان باشد dbh همان database handler ما بود که با آن از PDO نمونه سازی کرده بودیم:

dbh = new PDO($dsn, $this->user, $this->pass, $options);

دستور SQL خود را نیز به همین dbh داده ایم.

حالا باید متدی برای bind کردن مقادیر داشته باشیم (bind کردن یعنی چسباندن مقادیر به placeholder ها در prepared statement ها – به دوره آموزشی PDO مراجعه کنید) بنابراین می گوییم:

public function bind($param, $value, $type = null){

{

ما می خواهیم از متدی به نام bindValue در PDO استفاده کنیم. این متد پارامتر هایی را می گیرد که به تابع bind خودمان (تابع بالایی) پاس داده ایم: param همان named placeholder در prepared statement ها هستند (مثلا emal: و ...)، value مقدار param است (مثلا info@roxo.ir) و type مشخص می کند که value از چه نوعی است (آیا رشته است؟ آیا عدد صحیح است؟ و...).

دو مثال برای درک بهتر bind param:

مثال اول - اجرای prepared statement ها از نوع named placeholder:

<?php
/* Execute a prepared statement by binding PHP variables */
$calories = 150;
$colour = 'red';
$sth = $dbh->prepare('SELECT name, colour, calories
    FROM fruit
    WHERE calories < :calories AND colour = :colour');
$sth->bindParam(':calories', $calories, PDO::PARAM_INT);
$sth->bindParam(':colour', $colour, PDO::PARAM_STR, 12);
$sth->execute();
?>

مثال دوم - اجرای prepared statement ها از نوع positional placeholder:

<?php
/* Execute a prepared statement by binding PHP variables */
$calories = 150;
$colour = 'red';
$sth = $dbh->prepare('SELECT name, colour, calories
    FROM fruit
    WHERE calories < ? AND colour = ?');
$sth->bindParam(1, $calories, PDO::PARAM_INT);
$sth->bindParam(2, $colour, PDO::PARAM_STR, 12);
$sth->execute();
?>

type را در حالت پیش فرض null گذاشته ایم اما برای مشخص کردن آن از یک switch استفاده می کنیم:

switch(true){
          case is_int($value):
            $type = PDO::PARAM_INT;
            break;
          case is_bool($value):
            $type = PDO::PARAM_BOOL;
            break;
          case is_null($value):
            $type = PDO::PARAM_NULL;
            break;
          default:
            $type = PDO::PARAM_STR;
        }

از آنجا که می خواهیم این Switch همیشه اجرا شود در قسمت شرطی true را گذاشته ایم (همیشه باید مشخص شود که نوع value چیست). در آخر نیز باید آن را با استفاده از متد bindValue به stmt متصل کنیم بنابراین کد تکمیل شده این قسمت می شود:

// Bind values
    public function bind($param, $value, $type = null){
      if(is_null($type)){
        switch(true){
          case is_int($value):
            $type = PDO::PARAM_INT;
            break;
          case is_bool($value):
            $type = PDO::PARAM_BOOL;
            break;
          case is_null($value):
            $type = PDO::PARAM_NULL;
            break;
          default:
            $type = PDO::PARAM_STR;
        }
      }

      $this->stmt->bindValue($param, $value, $type);
    }

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

// Execute the prepared statement
    public function execute(){
      return $this->stmt->execute();
    }

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

// Get result set as array of objects
    public function resultSet(){
      $this->execute();
      return $this->stmt->fetchAll(PDO::FETCH_OBJ);
    }

حالا یک متد دیگر برای زمانی مینویسیم که بخواهیم فقط یک ردیف/داده خاص از نتایج را برگردانیم:

// Get single record as object
    public function single(){
      $this->execute();
      return $this->stmt->fetch(PDO::FETCH_OBJ);
    }

یک متد دیگر هم برای دریافت تعداد ردیف های برگشتی مینویسیم:

// Get row count
    public function rowCount(){
      return $this->stmt->rowCount();
    }

حالا پایگاه داده ما تکمیل شده است و نباید در اجرای کوئری ها مشکلی داشته باشیم. برای تست کردن آن به PHPMyAdmin میرویم و پایگاه داده ای که در جلسه قبل ساختیم (tmvc) را کامل می کنیم. جدولی به نام posts بسازید. از فیلد های مورد نظر، در فیلد name اول عبارت id را بنویسید. تیک A_I را نیز زده و آن را به عنوان کلید PRIMARY انتخاب کنید. حالا به تب Insert رفته و دو post با title های post one و post two بسازید. بنابراین جدول ما دو ردیف دارد post one و post two (که در ستون title هستند) و یک ستون دیگر به نام id.

اکنون به فایل Post.php در پوشه models بروید. می خواهیم متدی به نام getPosts بسازیم تا کلاس پایگاه داده مان را تست کنیم. درون این متد بنویسید:

public function getPosts(){
      $this->db->query("SELECT * FROM posts");

      return $this->db->resultSet();
      
    }

حالا به فایل Pages.php می رویم و درون متد index می گوییم:

public function index(){
      $posts = $this->postModel->getPosts();
      
      $data = [
        'title' => 'Welcome',
        'posts' => $posts
      ];
     
      $this->view('pages/index', $data);
    }

حالا نوبت تست کردن است! وارد پوشه views و سپس inc شوید و فایل index.php را باز کنید. از آنجایی که نتایج بازگشتی به صورت آرایه هستند برای نمایش باید در یک حلقه گردش کنیم:

<ul>
    <?php foreach($data['posts'] as $post) : ?>
      <li><?php echo $post->title; ?></li> 
    <?php endforeach; ?>
  </ul>

نتیجه باید به صورت زیر نمایش داده شود:

  • Post one
  • Post two

خب این هم از پایگاه داده و فریم ورک ما! در قسمت بعدی میخواهیم کد های فریم ورک مان را تر و تمیز کنیم. به طور مثال فایل Post.php نباید در فریم ورک ما باشد چرا که فریم ورک مستقل از برنامه است؛ این فایل فقط برای تست کردن فریم ورک بود. بنابراین باید برخی از فایل ها را جا به جا و حذف کنیم که این کار ها را به جلسه بعد منتقل می کنیم.

دانلود فایل کدها تا این جلسه

امیدوارم از این قسمت لذت برده باشید.

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

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