تکمیل فرآیند Login و Logout

Completing the Login and Logout Process

25 بهمن 1399
پروژه ساخت شبکه ی اجتماعی: تکمیل فرآیند Login و Logout

تکمیل فرآیند Login

در جلسه قبل کار ساخت flash message ها را تمام کردیم. حالا باید کدنویسی فرآیند ثبت نام را انجام دهیم. اگر یادتان باشد در کدنویسی فرآیند ثبت نام از کدی استفاده کردیم که ایمیل وارد شده را در پایگاه داده چک می کرد تا تکراری نباشد. برای ورود نیز می توانیم از همان کدها استفاده کنیم تا ببینیم ایمیل وارد شده برای login اصلا وجود دارد (قبلا ثبت نام شده) یا خیر.

از پوشه controllers وارد فایل Users.php شوید. می خواهیم پایین تر از کدهای Validate password کدهای بررسی ایمیل را می نویسیم. کدهای Validate password به این شکل بودند:

// Validate Password
        if(empty($data['password'])){
          $data['password_err'] = 'Please enter password';
        }

پایین تر از این کدها از همان model قبلی استفاده می کنیم و می گوییم:

// Check for user/email
        if($this->userModel->findUserByEmail($data['email'])){
          // User found
        } else {
          // User not found
          $data['email_err'] = 'No user found';
        }

این تابع ایمیل وارد شده را بررسی می کند تا مطمئن شود وجود دارد (در جلسات قبلی مربوط به register توضیح داده شد). اگر در حال حاضر به صفحه localhost/shareposts/users/login بروید و با ایمیلی که در پایگاه داده وجود ندارد login شوید به شما پیام No user found نمایش داده می شود.

بر اساس این کد اگر کاربر پیدا شود پیام خطا برای email_err تنظیم نمی شود و فرآیند ورود ادامه پیدا می کند بنابراین به قسمت پایین تر (کامنت Make sure errors are empty) بروید. کدهای این قسمت تا این لحظه به شکل زیر بودند:

// Make sure errors are empty
        if(empty($data['email_err']) && empty($data['password_err'])){
          // Validated
          die('SUCCESS');
        } else {
          // Load view with errors
          $this->view('users/login', $data);
        }

ما باید آن را تغییر دهیم تا به جای نمایش پیام SUCCESS فرآیند واقعی اتفاق بیفتد. ابتدا ('die('SUCCESS را حذف کنید. برای login کردن کاربر از یک model استفاده می کنیم و آن را درون یک متغیر به نام loggedInUser قرار می دهیم:

$loggedInUser = $this->userModel->login($data['email'], $data['password']);

این model دو چیز می گیرد: ایمیل و رمز عبور کاربر. توجه داشته باشید که رمز عبور هنوز هش نشده است چرا که از سمت فرم می آید.

حالا با یک شرط if باید login بودن را بررسی کنیم:

if($loggedInUser){
            // Create Session
          } else {
            $data['password_err'] = 'Password incorrect';

            $this->view('users/login', $data);
          }

در آخر با استفاده از view فرم را دوباره نمایش داده ایم.

حالا باید model مربوطه را تعریف کنیم بنابراین از پوشه models وارد فایل User.php شوید و کدهای زیر را به آن اضافه کنید:

// Login User
    public function login($email, $password){
      $this->db->query('SELECT * FROM users WHERE email = :email');
      $this->db->bind(':email', $email);

      $row = $this->db->single();

      $hashed_password = $row->password;
      if(password_verify($password, $hashed_password)){
        return $row;
      } else {
        return false;
      }
    }

این متد ایمیل و رمز عبور مورد نظر ما را می گیرد. سپس کوئری ما به دنبال ایمیل وارد شده می گردد و از آنجایی که هر کاربر فقط می تواند از یک ایمیل استفاده کند از متد ()single برای دریافت این ردیف استفاده می کنیم. سپس متغیری به نام hashed_password ایجاد کرده و ستون password از ردیف برگردانده شده را دریافت می کنیم. این password به صورت هش شده در پایگاه داده قرار دارد.

سپس از یک تابع PHP به نام ()password_verify استفاده کرده ایم. این تابع رمز عبور هش نشده (از سمت فرم) را میگیرد و آن را هش می کند و سپس با مقدار هش شده در پایگاه داده مقایسه می کند. اگر یکی بودند یعنی رمز عبور صحیح است و true برگردانده می شود.

حالا اگر به controller برگردید (فایل Users.php) متوجه می شوید که متغیر loggedInUser  یا ردیف row را دریافت می کند یا false. به همین دلیل است که در خط بعدی آن را در شرط if گذاشته ایم:

if($loggedInUser){
            // Create Session
          } else {
            $data['password_err'] = 'Password incorrect';

            $this->view('users/login', $data);
          }

بنابراین اگر false نباشد باید session های مربوطه را ایجاد کنیم در غیر این صورت صفحه login را با خطای مورد نظر برگردانیم. برای تست کردن می توانید از یک پیام مانند ('die ('SUCCESS استفاده کنید.

حالا باید به جای کامنت Create Session (یا دستور ('die ('SUCCESS) واقعا session های login را بسازیم. می توانیم این کار را مستقیما همینجا انجام دهیم اما من ترجیح می دهم که یک متد جداگانه به نام createUserSession برایش تعریف کنیم بنابراین فعلا می نویسیم:

if($loggedInUser){
            // Create Session
            $this->createUserSession($loggedInUser);
          } else {
            $data['password_err'] = 'Password incorrect';

            $this->view('users/login', $data);
          }

برای نوشتن متد جدید به قسمت پایین همین فایل بروید (قبل از براکت پایانی کلاس) و تابع جدید را تعریف کنید:

public function createUserSession($user){
      $_SESSION['user_id'] = $user->id;
      $_SESSION['user_email'] = $user->email;
      $_SESSION['user_name'] = $user->name;
      redirect('pages/index');
    }

در دستوراتی مانند user->id$ متغیر user$ از همان تابع ()login می آید. حتما یادتان هست که این تابع یک متغیر به نام row$ را برمی گرداند که حاوی یک ردیف از پایگاه داده بود. این ردیف شامل id و email و دیگر ستون های پایگاه داده است و این id از آن ردیف گرفته می شود. به همین شکل id و name و email را از آن ردیف گرفته ایم و در آخر کاربر را موقتا به صفحه index منتقل می کنیم.

حالا برای تست کدهایمان و فرآیند login بهتر است navbar را ویرایش کنیم. حتما دیده اید زمانی که کاربری وارد سایت می شود دیگر گزینه های login و register برایش نمایش داده نمی شود. بنابراین به فایل navbar.php رفته و بعد از خط 18 (عنصر <ul>) کدها را بدین شکل ویرایش کنید:

<ul class="navbar-nav ml-auto">
          <?php if(isset($_SESSION['user_id'])) : ?>
         
          <?php else : ?>
            <li class="nav-item">
              <a class="nav-link" href="<?php echo URLROOT; ?>/users/register">Register</a>
            </li>
            <li class="nav-item">
              <a class="nav-link" href="<?php echo URLROOT; ?>/users/login">Login</a>
            </li>
          <?php endif; ?>

در حال حاضر اگر به صفحه اول سایت برویم و login باشیم نباید هیچ چیزی برایمان نمایش داده شود و اگر login نباشیم نیز باید گزینه های login و register را ببینیم. الان که login هستیم و برای تست به صفحه localhost/shareposts/pages/index برویم هیچ کدام از این گزینه ها دیده نمی شوند.

اما بهتر است کار دیگری انجام دهیم. یکی از <li> های موجود را در قسمت if کپی کنید تا گزینه logout برای کاربران وارد شده نمایش داده شود:

<ul class="navbar-nav ml-auto">
          <?php if(isset($_SESSION['user_id'])) : ?>
          <li class="nav-item">
              <a class="nav-link" href="<?php echo URLROOT; ?>/users/logout">Logout</a>
            </li>
          <?php else : ?>
            <li class="nav-item">
              <a class="nav-link" href="<?php echo URLROOT; ?>/users/register">Register</a>
            </li>
            <li class="nav-item">
              <a class="nav-link" href="<?php echo URLROOT; ?>/users/login">Login</a>
            </li>
          <?php endif; ?>

البته این گزینه فعلا کاری انجام نمی دهد، چرا که هنوز کدهای آن را ننوشته ایم. به فایل Users.php برگردید و پایین تر از تابع createUserSession تابع logout را نیز تعریف کنید. خروج یا logout کردن هیچ کار خاصی نمیخواهد بلکه کافی است session ها را حذف کنید:

public function logout(){
      unset($_SESSION['user_id']);
      unset($_SESSION['user_email']);
      unset($_SESSION['user_name']);
      session_destroy();
      redirect('users/login');
    }

نکته: دستور session_destroy را برای محکم کاری اضافه کرده ایم تا اگر Session دیگری باقی مانده بود آن ها را نیز حذف کند.

حالا می توانید به راحتی این فرآیند را تست کنید تا از صحت عملکرد آن مطمئن شوید.

یک تابع دیگر به نام isLoggedIn نیز باید بسازیم:

public function isLoggedIn(){
      if(isset($_SESSION['user_id'])){
        return true;
      } else {
        return false;
      }
    }

این تابع مشخص می کند که کاربر login شده یا هنوز وارد حساب خود نشده است. از این تابع بعد ها استفاده خواهیم کرد.

دانلود فایل های پروژه تا این قسمت

امیدوارم از این قسمت لذت برده باشید. در قسمت های بعدی وارد مبحث گذاشتن پست و ویرایش آن و... صحبت خواهیم کرد.

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

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