php التسجيل و تفعيل العضوية من طرف الإدارة

php التسجيل و تفعيل العضوية من طرف الإدارة

بتاريخ: 11-11-2014   

بدون شك لقد صادفتم و لو مرة أثناء فتح حساباتكم على المواقع أو المنتديات . أنه بعد ملأ استمارة التسجيل بنجاح ، يشعركم صاحب الموقع أن عضويتكم ليست مفعلة بعد ، إلى حين أن يتم دراستها و الموافقة عليها من طرف إدارة الموقع . و يبقى القرار في يد هذه الإدارة ، إما أن تقبل و تُفعّل حسابكم لكي تصبحوا أعضاء أو ترفض منحكم هذه العضوية لأسباب تخصها .
في هذا الموضوع سأقترح عليكم سكريبتا عمليا للإستئناس ، يدور حول طريقة تفعيل هذا النوع من العضوية . سيقوم الزائر بالتسجيل أي ملأ استمارة التسجيل و إرسالها . سنقوم بتخزين بياناته في القاعدة ، لكن عضويته ستكون غير مفعلة ، بحيث حتى إن حاول ربط الإتصال فلن يتمكن من ذلك ، حتى يقوم صاحب الموقع بالموافقة على عضويته
سنحتاج لإنشاء جدول في قاعدة البيانات و بعض الصفحات :

  • site_members : إنشاء جدول للأعضاء في قاعدة البيانات
  • index.php : إنشاء صفحة الإستقبال ، سنضع فيها الروابط للصفحات الأخرى
  • registration.php : إنشاء صفحة تضم استمارة لتسجيل الأعضاء الجدد
  • registration-confirm.php : إنشاء صفحة لمعالجة بيانات استمارة التسجيل
  • administration.php : إنشاء صفحة الإدارة : لعرض الأعضاء الغير المفعلين
  • activation : إنشاء صفحة لتفعيل العضوية
  • connexion.php : إنشاء صفحة تضم استمارة الدخول
  • connexion-confirm.php : إنشاء صفحة لمعالجة بيانات استمارة الدخول
  • logout.php : إنشاء صفحة لتسجيل الخروج

أولا قبل كل شيء يجب ربط الإتصال بقاعدة البيانات

<?php
try 
{
  $db = new PDO('mysql:host=localhost;dbname=test;charset=utf8', 'root', '');
} 
catch(PDOException $e)
{
  die('خطأ:'. $e->getMessage());
}
?>

سأضع هذه الشيفرة في صفحة مستقلة "db-connection.php" داخل ملف سميته "includes" و سنقوم بإقحامها كلما دعت الضرورة
غيروا قيم ربط الإتصال حسب توضيبكم

إنشاء جدول الأعضاء : site_members

CREATE TABLE IF NOT EXISTS `site_members` (
  `user_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `user_name` varchar(40) NOT NULL,
  `user_email` varchar(70) NOT NULL,
  `user_password` varchar(255) NOT NULL,
  `activation` tinyint(1) NOT NULL,
  PRIMARY KEY (`user_id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;

عندما يقوم عضو جديد بملأ استمارة التسجيل و إرسالها ، نقوم بتخزين بياناته في القاعدة . لقد أضفت حقلا من نوع boolean في جدول الأعضاء "site_members" . و سميته "activation" . سيأخذ هذا الحقل مبدئيا قيمة "false" . و عندما نقوم لاحقا بتفعيل العضوية ، سنعتمد على هذا الحقل و سنعطيه قيمة "true" .
سأعطيكم شيفرة صفحة الإستقبال ، و سأضع فيها الروابط إلى الصفحات التي سننشئها لتسهيل العملية عليكم

index.php

<?php
session_start();
$session_id = isset($_SESSION['id']) ? (int) $_SESSION['id'] : 0;
$session_user = isset($_SESSION['user']) ? htmlspecialchars($_SESSION['user']) : '';
?>
<!DOCTYPE html>
<html dir='rtl'>
<head>
  <meta chrset='utf-8'>
</head>
<body>
  <h1>صفحة الإستقبال index.php</h1>
  <h1>مرحبا بك <span style="color:orange"><?php echo $session_user;?></span></h1>
<?php
if($session_id != 0 ) {
  echo '<p><a href="logout.php">الخروج</a></p>';
} else {
  echo '
  <p><a href="registration.php">التّسجيل</a></p>
  <p><a href="connexion.php">الدّخول</a></p>
  ';
}
?>
<p><a href="administration.php">الإدارة</a></p>
</body>
</html>

تسجيل الأعضاء الجدد

لتسجيل الأعضاء الجدد سنحتاج لصفحتين :

  • registration.php : صفحة تضم استمارة التسجيل
  • registration-confirm.php: صفحة معالجة بيانات الإستمارة و تخزينها في القاعدة :

registration.php

<!DOCTYPE html>
<html dir='rtl'>
<head>
  <meta charset='utf-8'>
  <style>
   label {display: inline-block;width:120px;margin-top:1px;}
  </style>
</head>
<body>
  <h1>استمارة التسجيل</h1>
  <form method="post" action="registration-confirm.php">
    <label for="pseudo">الإسم</label><input  type="text" name="pseudo" id="pseudo" required><br>
    <label for="email">البريد الإلكتروني</label><input type="email" name="email" id="email" required><br>
    <label for="password">كلمة المرور</label><input type="password" name="password" id="password" required><br>
    <label for="password_confirm">تأكيد كلمة المرور</label><input type="password" name="password_confirm" id="password_confirm" required><br>

      <p><input type="submit" name="submitted" value="موافق" ></p>
  </form>
</body>
</html>

.
registration-confirm.php
في هذه الصفحة سنقوم بمعالجة بيانات الإستمارة ، و قد ركزت على النقاط التالية

  • تعيين متغير جدول $error ، حتى نجمع فيه جميع الأخطاء التي قد يرتكبها العضو أثناء التسجيل ثم عرضها
  • التأكد من أن العضو قام بملأ جميع حقول الإستمارة
  • التأكد من صحة البريد الإلكتروني
  • التأكد من أن كلمة المرور و تأكيد كلمة المرور متطابقتين
  • التأكد من أن إسم المستخدم فريدا و لم يتم استعماله من طرف شخص آخر
  • التأكد من أن البريد الإلكتروني فريدا و لم يتم استعماله من طرف شخص آخر
<?php
include 'includes/db-connection.php';

if (isset($_POST['submitted'])) {

  $error = array(); // تعيين جدول لجمع الأخطاء

  if (empty($_POST['pseudo'])) { //إذا كان حقل الإسم فارغا
    //إضافة خطأ للجدول
    $error[] = 'المرجو ملأ حقل إسم المستخدم '; 
  } else {
    $user = $_POST['pseudo']; //إنشاء متغير للإسم
  }

  if (empty($_POST['email'])) {
    $error[] = 'المرجو ملأ حقل البريد الإلكتروني';
  } else {
    if (!filter_var($_POST['email'], FILTER_VALIDATE_EMAIL)) {
      $error[] = "! عذرا ، البريد الإلكتروني غير صحيح";
    } else {
      $email = $_POST['email'];
    }
  }

  if (empty($_POST['password'])) {
    $error[] = 'المرجو ملأ حقل كلمة المرور ';
  } else {
    $password = $_POST['password'];
  }
  if (empty($_POST['password_confirm'])) {
    $error[] = 'المرجو ملأ حقل تأكيد كلمة المرور ';
  } else {
    $password_confirm = $_POST['password_confirm'];
  }

  if (!empty($_POST['password']) AND !empty($_POST['password_confirm'])) {
    if ($_POST['password'] != $_POST['password_confirm'] ) {
      $error[] = 'حقلي كلمة المرور و تأكيد كلمة المرور غير متطابقين';
    }
  }
 // التأكد بأن العضو لم يستعمل إسما أو بريدا إلكترونيا موجودين مسبقا في القاعدة
  $response = $db->prepare('SELECT user_name, user_email
            FROM site_members
           ');
  $response->execute();
  $members = $response->fetchALL();
  $response->CloseCursor();

  foreach ($members as $member) {
    if (!empty($_POST['pseudo']) AND $_POST['pseudo'] == $member['user_name']) {
      $error[] = 'المرجو تغيير إسم المستخدم . هذا الإسم موجود مسبقا';
    }
    if (!empty($_POST['email']) AND $_POST['email'] == $member['user_email']) {
      $error[] = 'المرجو تغيير العنوان الإلكتروني ، هذا البريد موجود مسبقا';
    }
  }
 
  if (empty($error)) // إذا لم نسجل أي خطأ ، نرسل البيانات إلى القاعدة
  {
    $activation = false; // عدم تفعيل العضوية حاليا
    $stmt= $db->prepare('INSERT INTO site_members (user_name, user_email, user_password, activation) 
              VALUES (:name, :mail, :pass, :act)
            ');
    $stmt->bindValue(':name',$user,PDO::PARAM_STR);
    $stmt->bindValue(':mail',$email,PDO::PARAM_STR);
    $stmt->bindValue(':pass',$password,PDO::PARAM_STR);
    $stmt->bindValue(':act',$activation,PDO::PARAM_INT);
    $stmt->execute();
    $stmt->CloseCursor();
	
	echo '<p>تم تسجيلك بنجاح ، في انتظار تفعيل عضويتك من طرف الإدارة ، نتمنى لك أوقاتا طيبة </p>';
	
  } else { // أو نقوم بعرض الأخطاء الناجمة
   echo '<div> <ol>';
   foreach ($error as $key => $values) {
     echo '  <li>' . $values . '</li>';
   }
   echo '</ol></div>';
   }


} else { 
   echo '<p>المرجو ملأ الإستمارة</p>';
}
?>

يمكنكم من الآن بدأ تسجيل الأعضاء
لاحظتم بأننا ملأنا حقل "activation" بقيمة "false" ، سنعتمد على هذا الحقل لتفعيل العضوية .

بالنسبة لكلمة المرور ، قمنا بتخزينها بالواضح ، لأنه ليست موضوعنا حاليا . لمعرفة كيف يتم حمايتها و تشفيرها المرجو الإطلاع على فحوى هذا الدرس تشفير كلمة المرور باستعمال bcrypt

الدخول أو ربط الإتصال

لإتاحة الأعضاء الولوج إلى حساباتهم سنحتاج إلى صفحتين :

  • connexion.php : صفحة تضم استمارة الدخول
  • connexion-confirm.php : صفحة لمعالجة استمارة الدخول

connexion.php
يمكننا الإعتماد إما على إسم العضو أو بريده الإلكتروني لإتاحة الأعضاء الولوج إلى حسابهم .

<!DOCTYPE html>
<html dir='rtl'>
<head>
  <meta charset='utf-8'>
  <style>
   label {display: inline-block;width:120px;margin-top:1px;}
  </style>
</head>
<body>
  <h1>استمارة الدخول</h1>
  <form method="post" action="connexion-confirm.php">
    <label for="pseudo">الإسم</label><input  type="text" name="pseudo" id="pseudo" required><br>
    <label for="password">كلمة المرور</label><input type="password" name="password" id="password" required><br>
    <p><input type="submit" name="submitted" value="موافق" ></p>
  </form>
</body>
</html>

connexion-confirm.php

<?php
session_start();
include 'includes/db-connection.php';

if (isset($_POST['submitted'])) {

  $error = array(); // تعيين جدول لجمع الأخطاء
  
  if (empty($_POST['pseudo'])) { //إذا كان حقل الإسم فارغا
    //إضافة خطأ للجدول
    $error[] = 'المرجو ملأ حقل إسم المستخدم '; 
  } else {
    $user = $_POST['pseudo']; //إنشاء متغير للإسم
  }

  if (empty($_POST['password'])) {
    $error[] = 'المرجو ملأ حقل كلمة المرور ';
  } else {
    $password = $_POST['password'];
  }   
 
  if (empty($error))
  {
    // أخذ البيانات من القاعدة اعتمادا على إسم العضو و كلمة مروره 
    // و عضويته يجب أن تكون مفعلة
    $activation = true;
    $response = $db->prepare('SELECT user_id, user_name, user_password, activation 
            FROM site_members
            WHERE user_name = :nom 
            AND user_password = :pass 
            AND activation = :act
           ');
    $response->bindValue(':nom',$user,PDO::PARAM_STR);
    $response->bindValue(':pass',$password,PDO::PARAM_STR);
    $response->bindValue(':act',$activation,PDO::PARAM_INT);
    $response->execute();
    $member = $response->fetch();
    $response->CloseCursor();

    if(!$member) {
      echo 'البيانات غير صحيحة أو العضو غير مُفعّل';
    } else {
      $_SESSION['id'] = $member['user_id'];
      $_SESSION['user'] = $member['user_name'];
      // ثم تحويله تلقائيا إلى أي صفحة نريد 
      header('location:index.php');
    }	
	
  } else { // أو نقوم بعرض الأخطاء الناجمة
       echo '<div> <ol>';
       foreach ($error as $key => $values) {
       echo '  <li>' . $values . '</li>';
    }
       echo '</ol></div>';
    }
} else { 
   echo '<p>المرجو ملأ الإستمارة</p>';
}
?>

إذا قمتم بالتسجيل و حاولتم ربط الإتصال ، لن تتمكنوا حاليا من ذلك حتى لو أدخلتم إسما و كلمة مرور صحيحين ، لأن العضوية غير مفعلة $activation = false .

تفعيل العضوية

لتفعيل العضوية سنحتاج إلى صفحتين على الأقل :
administration.php : في هذه الصفحة ، سنقوم باستعلام لأخذ جميع الأعضاء الغير المفعلين من قاعدة البيانات ، حتى نتعرف عليهم و نستطيع بعد ذلك تفعيل عضويتهم بطريقة منفردة .
activation.php : في هذه الصفحة سنقوم بتفعيل عضوية أي عضو أردناه

administration.php

<?php 
session_start(); // لكي تحموا الصفحة لاحقا بواسطة الجلسة
include 'includes/db-connection.php';

$activation = false;

$response = $db->prepare('SELECT user_id, user_name
            FROM site_members
            WHERE activation = :act
           ');
$response->bindValue(':act',$activation,PDO::PARAM_INT);
$response->execute();
$members = $response->fetchALL();
$response->CloseCursor();

echo '<h1>صفحة تفعيل الأعضاء</h1>
<table>
 <tr>
   <th>إسم العضو</th>
   <th>تفعيل العضوية</th>
 </tr>';
foreach ($members as $member) {
echo '
 <tr>
   <td>'.htmlspecialchars($member['user_name']).'</td>
   <td><a href="activation.php?id='.(int)$member['user_id'].'"> تفعيل</a></td>
 </tr>
 ';
}
echo '</table> ';
?>

.
activation.php
لتفعيل أي عضو ، فالأمر جد سهل ، سنقوم بتحيين جدول الأعضاء و نعطي قيمة true لحقل "activation" المعني

<?php 
session_start(); // لكي تحموا الصفحة لاحقا بواسطة الجلسة
/*
 ** CSRF كما يجب أيضا أن تحموا هذه الصفحة لاحقا من ثغرة 
 */

include 'includes/db-connection.php';
//id نستقبل معرف 
// للعضو الذي نريد تفعيل عضويته
$id = (isset($_GET['id'])) ? (int) $_GET['id'] : 0;

$activation = true;
$response = $db->prepare('UPDATE site_members 
            SET activation = :act
            WHERE user_id = :id
           ');
$response->bindValue(':act',$activation,PDO::PARAM_INT);
$response->bindValue(':id',$id,PDO::PARAM_INT);
$response->execute();
$response->CloseCursor();
  
  echo 'تم تفعيل العضو بنجاح <br>
  <a href="index.php">صفحة الإستقبال</a><br>
  <a href="administration.php">صفحة الإدارة</a>';
?>

logout.php
صفحة تسجيل الخروج

<?php 
session_start();
session_destroy();
header('location:index.php');
exit();