ساخت کنترلر users و فرم ثبت‌نام

Build User Controller and Registration Form

25 بهمن 1399
پروژه ساخت شبکه ی اجتماعی: ساخت کنترلر users و فرم ثبت نام

ساخت کنترلر users

در جلسات قبل قسمت های ابتدایی UI را طراحی کردیم اما فعلا هیچ کارکردی برای صفحات مختلف آن وجود ندارد. بنابراین در این قسمت می خواهیم کنترلر users را بسازیم تا بتوانیم صفحات login و register را نیز ایجاد کنیم.

وارد پوشه controllers شده و فایلی جدید به نام Users.php بسازید. درون این فایل کلاس Users را خواهیم داشت که یک constructor دارد. تقریبا تنها کار این constructor بارگذاری model است اما فعلا آن را نمی نویسیم، اول به سراغ ثبت نام یا همان register می رویم:

public function register(){

}

کار این متد دو چیز است:

  • بارگذاری فرم ها هنگام مراجعه به صفحه register
  • مدیریت فرم ثبت نام پس از ثبت توسط کاربر (ارسال درخواست POST)

بنابراین اولین کار که باید بکنیم این است که مطمئن شویم درخواست ارسالی از نوع POST است (فرم ثبت و ارسال شده است) یا یک درخواست معمولی برای بارگذاری صفحه ثبت نام می باشد. بنابراین:

public function register(){
      // Check for POST
      if($_SERVER['REQUEST_METHOD'] == 'POST'){
        // Process form
      } else {
		// load form
		  echo 'load form';
}

اگر درخواست POST بود باید فرم پردازش شود که کدهای آن را بعدا می نویسیم و در غیر این صورت باید خود فرم بارگذاری شود. اگر الان به آدرس localhost/shareposts/users/register برویم عبارت "load form" برایمان نمایش داده می شود دلیلش هم این است که وارد کردن یک آدرس در نوار آدرس مرورگر درخواست POST محسوب نمی شود. این یک تست بود بنابراین 'echo 'load form را حذف می کنیم تا کدهای واقعی را بنویسیم.

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

public function register(){
      // Check for POST
      if($_SERVER['REQUEST_METHOD'] == 'POST'){
        // Process form
      } else {
        // Init data
        $data =[
          'name' => '',
          'email' => '',
          'password' => '',
          'confirm_password' => '',
          'name_err' => '',
          'email_err' => '',
          'password_err' => '',
          'confirm_password_err' => ''
        ];

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

توضیح کد:

فیلدهای name و email و password برای ذخیره اطلاعات کاربر در همین زمینه ها هستند که فعلا خالی می مانند تا زمانی که کاربر اطلاعاتی را توسط فرم ثبت کند. فیلدهای name_err و email_err و password_err و confirm_password_err برای مواقعی هستند که کاربر اطلاعات را به اشتباه وارد می کند؛ مثلا ایمیل کاربر بدین شکل وارد شده است: myemail_.com این ایمیل یک ایمیل نامعتبر است بنابراین خطای آن در این فیلدها ذخیره می شود تا بعدا به کاربر اعلام شود. همچنین مقادیر وارد شده توسط کاربر را (در صورت خطا) در فرم نگه می داریم تا با هر خطا مجبور نشود دوباره تمام فرم را پر کند. در آخر مانند دفعات قبلی view مورد نظر را بارگذاری کرده (فایل register.php که هنوز نساخته ایم) و آرایه data$ را به آن می دهیم.

نکته: اگر یادتان باشد پسوند فایل های php را به view نمیدادیم و برنامه را طوری نوشته ایم که خود View پسوند php. را در آخر register قرار بدهد. در صورت فراموشی به جلسات اولیه ساخت فریم ورک مراجعه کنید.

حالا وارد پوشه Views شوید و در آنجا یک پوشه دیگر به نام users می سازیم. در داخل این پوشه یک فایل به نام register.php بسازید و مانند view های دیگر header و footer های سایت را در این فایل نیز include کنید:

<?php require APPROOT . '/views/inc/header.php'; ?>


<?php require APPROOT . '/views/inc/footer.php'; ?>

حالا بین header و footer باید فرم ما قرار بگیرد بنابراین روی بوت استرپ و HTML متمرکز می شویم. ابتدا یک div با کلاس row می سازیم و درون آن یک div شش ستونه (کلاس col-md-6) دیگر قرار می دهیم. از آنجایی که می خواهیم فرم در وسط صفحه قرار بگیرد به همین div شش ستونه کلاس mx-auto را می دهیم (margin:auto). یک card نیز درون این div قرار دهید که درونش یک h1 داشته باشد. محتویات فایل register.php تا این لحظه بدین شکل است:

<?php require APPROOT . '/views/inc/header.php'; ?>
  <div class="row">
    <div class="col-md-6 mx-auto">
      <div class="card card-body bg-light mt-5">
        <h2>Create An Account</h2>
      </div>
    </div>
  </div>
<?php require APPROOT . '/views/inc/footer.php'; ?>

اگر الان بخواهیم آن را تست کنیم و به آدرس localhost/shareposts/users/register برویم با خطا مواجه می شویم (از نوع call to undefined method برای متد view). آیا دلیل این مسئله را می دانید؟

دلیلش این است که ما کنترلر users را extend نکردیم! کلاس ما تا این لحظه به شکل زیر بود:

class Users

اما باید به شکل زیر شود:

class Users extends Controller

تا بتواند از کدهای controller استفاده کند (مبحث وراثت کدها). بنابراین کدهای کنترلر users تا این لحظه به شکل زیر هستند:

<?php
  class Users extends Controller {
    public function __construct(){

    }

    public function register(){
      // Check for POST
      if($_SERVER['REQUEST_METHOD'] == 'POST'){
        // Process form
      } else {
        // Init data
        $data =[
          'name' => '',
          'email' => '',
          'password' => '',
          'confirm_password' => '',
          'name_err' => '',
          'email_err' => '',
          'password_err' => '',
          'confirm_password_err' => ''
        ];

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

حالا باید فرم را تکمیل کنیم. از آنجا که این دوره تمرکزی روی front-end ندارد من کدهای HTML (از صفحه register.php) را برای شما کپی می کنم و سپس به صورت خلاصه آن ها را توضیح می دهم (آشنایی با HTML از پیش نیاز های این دوره می باشد):

<?php require APPROOT . '/views/inc/header.php'; ?>
  <div class="row">
    <div class="col-md-6 mx-auto">
      <div class="card card-body bg-light mt-5">
        <h2>Create An Account</h2>
        <p>Please fill out this form to register with us</p>
        <form action="<?php echo URLROOT; ?>/users/register" method="post">
          <div class="form-group">
            <label for="name">Name: <sup>*</sup></label>
            <input type="text" name="name" class="form-control form-control-lg <?php echo (!empty($data['name_err'])) ? 'is-invalid' : ''; ?>" value="<?php echo $data['name']; ?>">
            <span class="invalid-feedback"><?php echo $data['name_err']; ?></span>
          </div>
          <div class="form-group">
            <label for="email">Email: <sup>*</sup></label>
            <input type="email" name="email" class="form-control form-control-lg <?php echo (!empty($data['email_err'])) ? 'is-invalid' : ''; ?>" value="<?php echo $data['email']; ?>">
            <span class="invalid-feedback"><?php echo $data['email_err']; ?></span>
          </div>
          <div class="form-group">
            <label for="password">Password: <sup>*</sup></label>
            <input type="password" name="password" class="form-control form-control-lg <?php echo (!empty($data['password_err'])) ? 'is-invalid' : ''; ?>" value="<?php echo $data['password']; ?>">
            <span class="invalid-feedback"><?php echo $data['password_err']; ?></span>
          </div>
          <div class="form-group">
            <label for="confirm_password">Confirm Password: <sup>*</sup></label>
            <input type="password" name="confirm_password" class="form-control form-control-lg <?php echo (!empty($data['confirm_password_err'])) ? 'is-invalid' : ''; ?>" value="<?php echo $data['confirm_password']; ?>">
            <span class="invalid-feedback"><?php echo $data['confirm_password_err']; ?></span>
          </div>

          <div class="row">
            <div class="col">
              <input type="submit" value="Register" class="btn btn-success btn-block">
            </div>
            <div class="col">
              <a href="<?php echo URLROOT; ?>/users/login" class="btn btn-light btn-block">Have an account? Login</a>
            </div>
          </div>
        </form>
      </div>
    </div>
  </div>
<?php require APPROOT . '/views/inc/footer.php'; ?>

توضیحات کد:

در مورد action عنصر form بارها صحبت کرده ایم؛ صفحه ای است که پردازش فرم در آنجا انجام خواهد شد (ما همین صفحه را داده ایم). همچنین بوت استرپ کلاسی به نام is-invalid دارد که خط قرمزی دور فیلد های فرم ایجاد می کند و به کاربر نشان می دهد که خطایی وجود دارد. بالاتر یک آرایه data ساختیم که در آن فیلد های name و email و ... را ساخته ایم سپس اعضای name_err و email_err و ... را نیز ساختیم تا خطاها را در آن قرار دهیم. بنابراین می توانیم بگوییم اگر مثلا عضو name_err آرایه خالی نبود (خطایی داشتیم) کلاس is-invalid را echo کن، در غیر این صورت نیز چیزی echo نکن:

echo (!empty($data['name_err'])) ? 'is-invalid' : '';

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

value="<?php echo $data['name']; ?>"

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

<span class="invalid-feedback"><?php echo $data['name_err']; ?></span>

همین کاری که با فیلد name کردیم با 3 فیلد دیگر نیز انجام می دهیم، فقط به جای name باید email و password و ... را چک کنیم.

پس از انجام این کار یک row دیگر اضافه کرده ایم تا لینک ثبت نام (ثبت و ارسال اطلاعات فرم) و لینک login را در آن قرار دهیم:

<div class="row">
            <div class="col">
              <input type="submit" value="Register" class="btn btn-success btn-block">
            </div>
            <div class="col">
              <a href="<?php echo URLROOT; ?>/users/login" class="btn btn-light btn-block">Have an account? Login</a>
            </div>
          </div>

این فرم register ما است. برای ساخت فرم login نیز دقیقا همین را کپی می کنیم به غیر از چند فیلد که فقط هنگام ثبت نام نیاز داریم. قبل از آن به فایل Users.php رفته و متد register را عینا کپی کنید. به جای register نام آن را login بگذارید و موارد name و name_err و confirm_password و confirm_password_err را از Data حذف کنید. سپس به view صفحه login را پاس دهید:

public function login(){
      // Check for POST
      if($_SERVER['REQUEST_METHOD'] == 'POST'){
        // Process form
      } else {
        // Init data
        $data =[    
          'email' => '',
          'password' => '',
          'email_err' => '',
          'password_err' => '',        
        ];

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

حالا در پوشه views>users یک فایل دیگر به نام login.php بسازید. محتوای آن را دقیقا از register.php کپی کنید و موارد زیر را تغییر دهید:

  • متن خطاها و متون دیگر را متناسب با فرآیند login و متناسب با نوع فرم خود تغییر دهید. مثلا لطفا نام کاربری خود را کامل کنید و ...
  • action مربوط به فرم را نیز روی صفحه users/login تنظیم کنید.
  • کل form-group مربوط به name و confirm_password را حذف کنید.
  • مقدار value از دکمه submit را به login تغییر دهید.
  • لینک login آخر صفحه را نیز به register تغییر دهید چرا که الان در صفحه login هستیم.

محتوای login.php به شکل زیر خواهد بود:

<?php require APPROOT . '/views/inc/header.php'; ?>
  <div class="row">
    <div class="col-md-6 mx-auto">
      <div class="card card-body bg-light mt-5">
        <h2>Login</h2>
        <p>Please fill in your credentials to log in</p>
        <form action="<?php echo URLROOT; ?>/users/login" method="post">
          <div class="form-group">
            <label for="email">Email: <sup>*</sup></label>
            <input type="email" name="email" class="form-control form-control-lg <?php echo (!empty($data['email_err'])) ? 'is-invalid' : ''; ?>" value="<?php echo $data['email']; ?>">
            <span class="invalid-feedback"><?php echo $data['email_err']; ?></span>
          </div>
          <div class="form-group">
            <label for="password">Password: <sup>*</sup></label>
            <input type="password" name="password" class="form-control form-control-lg <?php echo (!empty($data['password_err'])) ? 'is-invalid' : ''; ?>" value="<?php echo $data['password']; ?>">
            <span class="invalid-feedback"><?php echo $data['password_err']; ?></span>
          </div>
          <div class="row">
            <div class="col">
              <input type="submit" value="Login" class="btn btn-success btn-block">
            </div>
            <div class="col">
              <a href="<?php echo URLROOT; ?>/users/register" class="btn btn-light btn-block">No account? Register</a>
            </div>
          </div>
        </form>
      </div>
    </div>
  </div>
<?php require APPROOT . '/views/inc/footer.php'; ?>

در ضمن برای تکمیل کار به صفحه navbar.php بروید (از جلسه قبل) و کلاس active را از لینک ها حذف کنید تا ظاهر بهتری پیدا کنند. همچنین یک div با کلاس container دقیقا زیر عنصر nav باز کنید و قبل از تگ پایانی عنصر nav آن را ببندید. دلیل این کار این است که لینک های navbar به گوشه های صفحه چسبیده اند و ما می خواهیم آن ها را کمی به وسط تر بیاوریم. البته این موارد سلیقه ای است و شما می توانید هر طور خواستید آن ها را ویرایش کنید.

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

امیدوارم از این قسمت لذت برده باشید. در جلسات بعدی روی اعتبارسنجی فرم ها و تکمیل این موارد کار خواهیم کرد.

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

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