এই টিউটোরিয়ালে, আমি আপনাকে দেখাব কিভাবে একটি অবজেক্ট-ওরিয়েন্টেড Function এর মাধ্যমে PHP PDO ব্যবহার করে একটি সহজ লগইন এবং সাইনআপ সিস্টেম তৈরি করা যায়। আমরা আমাদের Mysql ডাটাবেসের সাথে যোগাযোগ করার জন্য PDO ব্যবহার করব।
কেন PDO ব্যবহার করবো ?
পিডিও-তে নিরাপত্তা এবং একাধিক ড্রাইভার সমর্থনের মতো অনেক সুবিধা রয়েছে এবং এর মানে আপনি একটি ভিন্ন ডাটাবেস ড্রাইভারকে সমর্থন করার জন্য আপনার পিএইচপি স্ক্রিপ্টগুলিকে সহজেই পরিবর্তন করতে পারেন।
- DSN : একটি ডেটা সোর্স নেম (DSN) হল, একটি ডেটা স্ট্রাকচার যাতে একটি নির্দিষ্ট ডাটাবেস সম্পর্কে তথ্য থাকে যা একটি ওপেন ডাটাবেস কানেক্টিভিটি ( ODBC ) ড্রাইভারের সাথে সংযোগ করার জন্য প্রয়োজন৷
- Method : একটি Method হল একটি ক্লাসের ভিতরের একটি ফাংশন। কিন্তু আপনার সুযোগ প্রসারিত করার জন্য, অবজেক্ট-ওরিয়েন্টেড প্রোগ্রামিং-এর একটি Method হল একটি ক্লাসের সাথে যুক্ত একটি Method। একটি Method ক্লাস থেকে তৈরি করা বস্তুর আচরণ সংজ্ঞায়িত করে। এটি বলার আরেকটি উপায় হল যে একটি Method হল একটি কর্ম যা একটি বস্তু সম্পাদন করতে সক্ষম।
- Magic Method : পিএইচপি Magic হিসাবে শুরু হওয়া সমস্ত ফাংশনের নাম সংরক্ষণ করে। এগুলি এমন Method যা একটি নির্দিষ্ট বস্তু ব্যবহার করার সময় নির্দিষ্ট পরিস্থিতিতে Response দেওয়ার অনুমতি দেয়।
- Model : একটি মডেল হল কিছু ধরণের ডেটার উপস্থাপনা এবং সেগুলি পরিবর্তন করার পদ্ধতি রয়েছে। উদাহরণস্বরূপ: আপনি কখনই একটি কন্ট্রোলারে এসকিউএল কোয়েরি রাখেন না, সেগুলি মডেলে রাখা হয় এবং কন্ট্রোলার মডেলটিকে Execute করার জন্য কল করবে।
- Controller : কন্ট্রোলার একটি ক্লাসে সম্পর্কিত রুট লজিককে Marge করতে পারে, পাশাপাশি Constructor Method এর মতো আরও উন্নত কাঠামোর বৈশিষ্ট্যগুলির সুবিধা নিতে পারে।
- CRUD : কম্পিউটার প্রোগ্রামিং-এ, ক্রিয়েট, রিড, আপডেট এবং ডিলিট (CRUD) হল স্থায়ী স্টোরেজের চারটি মৌলিক কাজ।
এই পাঠ থেকে সেরাটা পাওয়ার জন্য, নিম্নলিখিত প্রয়োজনীয়তাগুলি পূরণ করতে হবে।
- একটি লোকালহোস্ট সার্ভার: আপনি নিচের যেকোনো একটির সর্বশেষ সংস্করণ ডাউনলোড করতে পারেন। আপনার অপারেটিং সিস্টেমের উপর নির্ভর করে XAMPP, LAMPP, MAMPP, এবং AMPPS।
- একটি Code Editor: আপনার কোডগুলি লিখতে একটি Code Editor৷ ব্যক্তিগতভাবে, আমি আপনাকে Visual Studio Code Editor ডাউনলোড করার পরামর্শ দিচ্ছি ।
- একটি Css ফ্রেমওয়ার্ক: একটি Css ফ্রেমওয়ার্ক যেমন MaterializeCss, Bootstrap4, বা SkeletonCss। এটি সবই নির্ভর করে আপনি যে সিএসএস ফ্রেমওয়ার্ক পছন্দ করেন তার উপর। কিন্তু এই প্রজেক্টের জন্য, আমি বুটস্ট্র্যাপ সাজেস্ট করি ।
- PHP এর প্রাথমিক জ্ঞান।
- Github থেকে Mysql ডেটাবেস ডাউনলোড করুন ।
সমস্ত প্রয়োজনীয়তা সন্তুষ্ট হলে, আমরা এখন PDO (PHP DATA OBJECTS) সম্পর্কে কথা বলতে কিছু সময় নিতে পারি।
Project Directory
*/ ld-auth (Parent Folder or Project)
*/ assets (Our Css And Js Lives Here)
*/ css
*/controller
/Controller.php
/Dashboard.php
/Login.php
/Logout.php
/Register.php
*/Model
/DashboardModel.php
/Db.php
/LoginModel.php
/RegisterModel.php
dashboard.php
index.php
logout.php
nav.php
register.php
1. Db.php সম্পাদনা করা (মডেল ফোল্ডার)
মডেল ফোল্ডারে, Db.php ফাইলটি আমাদের Mysql ডাটাবেসের সাথে সংযোগ স্থাপনের জন্য প্রয়োজনীয় সমস্ত কনফিগারেশন ধারণ করবে।
আমাদের Db.php ফাইলটি মডেল ফোল্ডারের প্রতিটি অন্যান্য শ্রেণীর জন্য একটি Base Class হিসাবে কাজ করছে।
<?php
class Db {
protected $dbName = 'learning_dollars_db'; /** Database Name */
protected $dbHost = 'localhost'; /** Database Host */
protected $dbUser = 'root'; /** Database Root */
protected $dbPass = ''; /** Databse Password */
protected $dbHandler, $dbStmt;
/**
* @param null|void
* @return null|void
* @desc Creates or resume an existing database connection...
**/
public function __construct()
{
// Create a DSN Resource...
$Dsn = "mysql:host=" . $this->dbHost . ';dbname=' . $this->dbName;
//create a pdo options array
$Options = array(
PDO::ATTR_PERSISTENT => true,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
);
try {
$this->dbHandler = new PDO($Dsn, $this->dbUser, $this->dbPass, $Options);
} catch (Exception $e) {
var_dump('Couldn\'t Establish A Database Connection. Due to the following reason: ' . $e->getMessage());
}
}
/**
* @param string
* @return null|void
* @desc Creates a PDO statement object
**/
public function query($query)
{
$this->dbStmt = $this->dbHandler->prepare($query);
}
/**
* @param string|integer|
* @return null|void
* @desc Matches the correct datatype to the PDO Statement Object.
**/
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;
break;
}
}
$this->dbStmt->bindValue($param, $value, $type);
}
/**
* @param null|void
* @return null|void
* @desc Executes a PDO Statement Object or a db query...
**/
public function execute()
{
$this->dbStmt->execute();
return true;
}
/**
* @param null|void
* @return null|void
* @desc Executes a PDO Statement Object an returns a single database record as an associative array...
**/
public function fetch()
{
$this->execute();
return $this->dbStmt->fetch(PDO::FETCH_ASSOC);
}
/**
* @param null|void
* @return null|void
* @desc Executes a PDO Statement Object an returns nultiple database record as an associative array...
**/
public function fetchAll()
{
$this->execute();
return $this->dbStmt->fetchAll(PDO::FETCH_ASSOC);
}
}
?>
আমাদের ক্লাসে কিছু সুরক্ষিত বৈশিষ্ট্য রয়েছে যা আমরা আমাদের DSN (ডেটা সোর্স নেম) তৈরি করতে ব্যবহার করব যা একটি নতুন PDO সংযোগ তৈরি করার জন্য প্রয়োজনীয়।
__construct() ম্যাজিক Method
সমস্ত Magic আমাদের __construct ম্যাজিক Method এ ঘটে, যেখানে আমাদের PDO সংযোগের জন্য কিছু বুদ্ধিমান কনফিগারেশন/এট্রিবিউটের পাশাপাশি আমাদের Dsn তৈরি করা হয়েছিল।
$options অ্যারেটি ডাটাবেস সংযোগের জন্য PDO অবজেক্ট তৈরি করার সময় ব্যবহৃত হয়। এটি পিএডিও এট্রিবিউটগুলির মান সেট করে যা ডাটাবেস সংযোগের পদক্ষেপ এবং ডেটা প্রস্তুতিকরণের জন্য ব্যবহৃত হয়।
- PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION: এটি ত্রুটি মোড সেট করে যা ডাটাবেস কনেকশনে ত্রুটি ঘটালে এক্সেপশন তৈরি করে। এটি দ্বারা আপনি ডাটাবেস ত্রুটির উপর নিয়ন্ত্রণ পাবেন এবং ত্রুটি সম্পর্কিত বিস্তারিত তথ্য পাবেন।
- PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC: এটি ডিফল্ট ডেটা প্রস্তুতিকরণ মোড সেট করে যা সংগ্রহযোগ্য এসোসিয়েটিভ অ্যারে রিটার্ন করে। এটি দ্বারা আপনি ডেটাবেস থেকে ডেটা প্রাপ্ত করার সময় এক্সেস করা পদ্ধতি নির্ধারণ করতে পারবেন।
- PDO::ATTR_EMULATE_PREPARES => false: এটি প্রিপ্যারড স্টেটমেন্টগুলির প্রিমারি প্রস্তুতিকরণ চালু/বন্ধ করে। এটি সক্রিয় করা হয়ে থাকলে PDO প্রিপ্যারড স্টেটমেন্টগুলি বার্তা প্রস্তুতি করতে আগ্রহী হয় এবং সাধারণ SQL প্রস্তুতিকরণ ব্যবহার করে। তবে, অসুবিধার কারণে এটি সেট করা যেতে পারে। সাধারণত এটি অক্টিভ করা না হলেও ভাল এবং সুরক্ষিত উপায় হলে সক্রিয় করতে রাখা।
এই প্যারামিটারগুলি ব্যবহার করা উচিত এবং সুরক্ষিত কোড বানানোর জন্য প্রস্তাবিত প্রয়োজনীয়।
Query() Method
ক্যোয়ারী পদ্ধতি যা একটি একক আর্গুমেন্ট গ্রহণ করে এবং শূন্য বা অকার্যকর ফেরত দেয় সেটি ডাটাবেস সংযোগটি পুনরায় ব্যবহার করার জন্য দায়ী যা তৈরি করা হয়েছিল এবং $dbHandler সুরক্ষিত ভেরিয়েবলে পাঠানো হয়েছিল।
> PDOStatement::execute() পদ্ধতি দ্বারা কার্যকর করার জন্য একটি SQL স্টেটমেন্ট প্রস্তুত করে। বিবৃতি টেমপ্লেটে শূন্য বা ততোধিক নামযুক্ত (:নাম) বা প্রশ্ন চিহ্ন (?) প্যারামিটার মার্কার থাকতে পারে যার জন্য বিবৃতিটি কার্যকর করার সময় প্রকৃত মান প্রতিস্থাপিত হবে। একই স্টেটমেন্ট টেমপ্লেটের মধ্যে নামযুক্ত এবং প্রশ্ন চিহ্ন প্যারামিটার মার্কার উভয়ই ব্যবহার করা যাবে না; শুধুমাত্র এক বা অন্য প্যারামিটার শৈলী। যেকোন ব্যবহারকারী-ইনপুট আবদ্ধ করতে এই পরামিতিগুলি ব্যবহার করুন, সরাসরি ক্যোয়ারীতে ব্যবহারকারী-ইনপুট অন্তর্ভুক্ত করবেন না।
Bind() Method
Bind Method – 3টি parameter গ্রহণ করে, $param , $value , এবং $type । সঠিক ডেটা টাইপকে $type- এ আবদ্ধ করার জন্য $type নাল থাকলে Method টি একটি সুইচ স্টেটমেন্ট চালায় ।
উপলব্ধ PDO ডেটা প্রকার:
- PDO::PARAM_BOOL: একটি বুলিয়ান ডেটা টাইপ প্রতিনিধিত্ব করে।
- PDO::PARAM_NULL: SQL NULL ডেটা টাইপ প্রতিনিধিত্ব করে।
- PDO::PARAM_INT: SQL INTEGEER ডেটা টাইপ প্রতিনিধিত্ব করে।
- PDO::PARAM_STR: SQL CHAR, VARCHAR, বা অন্যান্য স্ট্রিং ডেটা টাইপ প্রতিনিধিত্ব করে।
> PDOStatement::bindValue() ফাংশন পিএইচপি-তে একটি অন্তর্নির্মিত ফাংশন যা একটি মানকে একটি প্যারামিটারের সাথে আবদ্ধ করতে ব্যবহৃত হয়। এই ফাংশনটি এসকিউএল-এ সংশ্লিষ্ট নামযুক্ত বা প্রশ্ন চিহ্ন স্থানধারকের সাথে একটি মান আবদ্ধ করে যা বিবৃতি প্রস্তুত করতে ব্যবহৃত হয়।
Execute() Method
এক্সিকিউট মেথড কোন প্যারামিটার পায় না এবং একটি বুলিয়ান সত্য বা বুলিয়ান মিথ্যা প্রদান করে। এই পদ্ধতিটি PDO-এর এক্সিকিউট মেথডকে আহ্বান বা কল করার চেষ্টা করে যা প্রস্তুত স্টেটমেন্ট বা জেনারেট করা স্টেটমেন্ট অবজেক্টকে এক্সিকিউট করে।
> PDOStatement::execute সাফল্যের উপর একটি বুলিয়ান সত্য বা ব্যর্থতার উপর একটি বুলিয়ান মিথ্যা প্রদান করে।
Fetch() Method
Fetch Method টি ডিবি ক্লাস এক্সিকিউট পদ্ধতিকে আহ্বান করে যা জেনারেট করা PDO প্রস্তুত বিবৃতি কার্যকর করে এবং Fetch Method যা ফেচ নামে আরেকটি পিডিও পদ্ধতিকে কল করে । একটি একক প্যারামিটার নেয় এবং ফলাফলটি কীভাবে প্রক্রিয়া করা হয় তা নির্ধারণ করে এবং একটি হিসাবে পাস করা ফর্ম্যাটটি ব্যবহার করে এটি ফেরত দেয়।
FetchAll() Method
fetchAll পদ্ধতিটি Db ক্লাস এক্সিকিউট পদ্ধতিকেও আহ্বান করে যা আগে ব্যাখ্যা করা হয়েছিল । শুধুমাত্র পার্থক্য হল যে fetchAll পদ্ধতিটি প্রস্তুত বিবৃতিতে fetch_all নামক একটি PDO পদ্ধতি কল করে যা একটি একক যুক্তি নেয় এবং প্রস্তুত বিবৃতি শর্তের উপর নির্ভর করে ডাটাবেসের সমস্ত মিলে যাওয়া রেকর্ড সমন্বিত একটি তালিকা প্রদান করে।
2. LoginModel.php সম্পাদনা করা (মডেল ফোল্ডার)
LoginModel-এ একটি ক্লাস রয়েছে যা মডেল ফোল্ডারে Db.php ফাইল থেকে Db ক্লাস প্রসারিত করে।
LoginModel ক্লাসে একটি একক পদ্ধতি রয়েছে যা একটি ইমেল ঠিকানার উপর ভিত্তি করে ব্যবহারকারীর জন্য অনুসন্ধান করে এবং একটি অ্যারে প্রদান করে।
LoginModel.php ফাইলটি খুলুন এবং নীচের কোড স্নিপেট পেস্ট করুন।
<?php
require_once(__dir__ . '/Db.php');
class LoginModel extends Db {
/**
* @param string
* @return array
* @desc Returns a user record based on the method parameter....
**/
public function fetchEmail(string $email) :array
{
$this->query("SELECT * FROM `db_user` WHERE `email` = :email");
$this->bind('email', $email);
$this->execute();
$Email = $this->fetch();
if (empty($Email)) {
$Response = array(
'status' => true,
'data' => $Email
);
return $Response;
}
if (!empty($Email)) {
$Response = array(
'status' => false,
'data' => $Email
);
return $Response;
}
}
}
?>
FetchEmail() Method
fetchEmail method টি একটি $email কে একমাত্র প্যারামিটার হিসাবে নেয় এবং পূর্ববর্তী অপারেশনের ফলাফলের উপর নির্ভর করে একটি অ্যারে প্রদান করে । fetchEmail ফাংশন যেমন Db Class পদ্ধতি ব্যবহার করে
3. RegisterModel.php সম্পাদনা করা (মডেল ফোল্ডার)
রেজিস্টার মডেল ফাইলটি ডিবি ক্লাস Include করে যা ফাইলের শীর্ষে প্রয়োজনীয়। RegisterModel ক্লাসে createUser এবং fetchUser দুটি Method রয়েছে যা একটি নতুন ব্যবহারকারী তৈরি এবং একটি নতুন ব্যবহারকারীকে ফিরিয়ে দেওয়ার জন্য দায়ী।
আপনার RegisterModel.php ফাইলে নিম্নলিখিত কোড স্নিপেট থাকা উচিত।
<?php
require_once(__dir__ . '/Db.php');
class RegisterModel extends Db {
/**
* @param array
* @return array
* @desc Creates and returns a user record....
**/
public function createUser(array $user) :array
{
$this->query("INSERT INTO `db_user` (name, email, phone_no, password) VALUES (:name, :email, :phone_no, :password)");
$this->bind('name', $user['name']);
$this->bind('email', $user['email']);
$this->bind('phone_no', $user['phone']);
$this->bind('password', $user['password']);
if ($this->execute()) {
$Response = array(
'status' => true,
);
return $Response;
} else {
$Response = array(
'status' => false
);
return $Response;
}
}
/**
* @param string
* @return array
* @desc Returns a user record based on the method parameter....
**/
public function fetchUser(string $email) :array
{
$this->query("SELECT * FROM `db_user` WHERE `email` = :email");
$this->bind('email', $email);
$this->execute();
$User = $this->fetch();
if (!empty($User)) {
$Response = array(
'status' => true,
'data' => $User
);
return $Response;
}
return array(
'status' => false,
'data' => []
);
}
}
?>
CreateUser() Method
createUser Method একটি অ্যারেকে একমাত্র প্যারামিটার হিসাবে গ্রহণ করে এবং ডেটাবেস অপারেশনের ফলাফলের উপর নির্ভর করে একটি অ্যারে প্রদান করে । createUser Method টি Db ক্লাসে প্রদত্ত Method ব্যবহার করে ।
FetchUser() Method
fetchUser Method একটি ইমেল স্ট্রিংকে একমাত্র প্যারামিটার হিসাবে গ্রহণ করে এবং ডেটাবেস অপারেশনের ফলাফলের উপর নির্ভর করে ইমেল সহ ব্যবহারকারীকে সমন্বিত একটি অ্যারে প্রদান করে । Method টি ইমেল Address সহ একটি ব্যবহারকারীর সংস্থান প্রদান করে।
4. DashboardModel.php সম্পাদনা করা (মডেল ফোল্ডার)
DashboardModel.php ফাইলে Db.php ফাইল থেকে Db ক্লাস রয়েছে। ড্যাশবোর্ডমডেল ডিবি ক্লাস প্রসারিত করে এবং সংবাদের অ্যারে ফেরত দেওয়ার জন্য ডিবি ক্লাসে প্রদত্ত পদ্ধতি ব্যবহার করে ।
যে বলে, আমাদের DashboardModel.php ফাইলটি নীচের লাইনের মতো হওয়া উচিত।
<?php
require_once(__dir__ . '/Db.php');
class DashboardModel extends Db {
/**
* @param null
* @return array
* @desc Returns an array of news....
**/
public function fetchNews() :array
{
$this->query("SELECT * FROM `db_news` ORDER BY `id` DESC");
$this->execute();
$News = $this->fetchAll();
if (count($News) > 0) {
$Response = array(
'status' => true,
'data' => $News
);
return $Response;
}
$Response = array(
'status' => false,
'data' => []
);
return $Response;
}
}
?>
FetchNews() Method
fetchNews Method কোন প্যারামিটার পায় না কিন্তু Db ক্লাসে প্রদত্ত Method ব্যবহার করে খবরের একটি অ্যারে প্রদান করে ।
5. Controller.php সম্পাদনা করা (কন্ট্রোলার ফোল্ডার)
এই ফাইলটি কন্ট্রোলার ফোল্ডারে অন্যান্য কন্ট্রোলারের জন্য বেস কন্ট্রোলার হিসাবে কাজ করে কারণ এটি অন্যান্য কন্ট্রোলার বেস কন্ট্রোলার প্রসারিত করার ফলে Method গুলি পুনঃব্যবহার করা সহজ করে তোলে।
Controller.php ফাইলটি নিচের লাইনের মতো দেখতে হবে।
<?php
session_start();
class Controller { }
?>
6. Dashboard Controller সম্পাদনা করা
এই ফাইলটিতে ড্যাশবোর্ড কন্ট্রোলার নামে একটি ক্লাস রয়েছে যা Base কন্ট্রোলারকে Include করে। ফাইলটি কিছু নির্ভরতায় লোড হয় যা আমরা আগে তৈরি করেছিলাম News আনার জন্য ড্যাশবোর্ড মডেলের প্রয়োজন।
আমাদের Dashboard.php ফাইল নিম্নলিখিত মত হওয়া উচিত.
<?php
require_once(__dir__ . '/Controller.php');
require_once('./Model/DashboardModel.php');
class Dashboard extends Controller {
public $active = 'dashboard'; //for highlighting the active link...
private $dashboardModel;
/**
* @param null|void
* @return null|void
* @desc Checks if the user session is set and creates a new instance of the DashboardModel...
**/
public function __construct()
{
if (!isset($_SESSION['auth_status'])) header("Location: index.php");
$this->dashboardModel = new DashboardModel();
}
/**
* @param null|void
* @return array
* @desc Returns an array of news by calling the DashboardModel fetchNews method...
**/
public function getNews() :array
{
return $this->dashboardModel->fetchNews();
}
}
?>
__Constructor() Magic Method
ড্যাশবোর্ড ক্লাসের একটি Object তৈরি হওয়ার সাথে সাথে এই Method টি কার্যকর করা হয়। এই Method টি সেশন অ্যারেতে auth_status কী সেট করা আছে কিনা তা পরীক্ষা করে। এবং DashboardModel ক্লাসের একটি নতুন Object তৈরি করে যদি এটি বিদ্যমান থাকে, অন্যথায় এটি লগইন Page এ একটি HTTP পুনঃনির্দেশ করে।
GetNews() Method
এই পদ্ধতিটি ব্যক্তিগত $dashboardModel সম্পত্তি ব্যবহার করে যা DashboardModel ক্লাসের একটি উদাহরণ। $ dashboardModel DashboardModel ক্লাসে উপলব্ধ Method গুলিকে প্রকাশ করে যা News এর তালিকা পেতে সহজ করে তোলে৷
7. Login.php সম্পাদনা করা (কন্ট্রোলার ফোল্ডার)
এই ফাইলটিতে লগইন কন্ট্রোলার নামে একটি ক্লাস রয়েছে যা বেস কন্ট্রোলারকে প্রসারিত করে। ব্যবহারকারীর ইমেল ঠিকানার উপর ভিত্তি করে ব্যবহারকারীকে আনার জন্য লগইন মডেলের প্রয়োজন করে ফাইলটি কিছু নির্ভরতার মধ্যেও লোড হয়।
আমাদের Login.php ফাইল নিম্নলিখিত মত হওয়া উচিত.
<?php
require_once(__dir__ . '/Controller.php');
require_once('./Model/LoginModel.php');
class Login extends Controller {
public $active = 'login'; //for highlighting the active link...
private $loginModel;
/**
* @param null|void
* @return null|void
* @desc Checks if the user session is set and creates a new instance of the LoginModel...
**/
public function __construct()
{
if (isset($_SESSION['auth_status'])) header("Location: dashboard.php");
$this->loginModel = new LoginModel();
}
/**
* @param array
* @return array|boolean
* @desc Verifies and redirects a user by calling the login method on the LoginModel...
**/
public function login(array $data)
{
$email = stripcslashes(strip_tags($data['email']));
$password = stripcslashes(strip_tags($data['password']));
$EmailRecords = $this->loginModel->fetchEmail($email);
if (!$EmailRecords['status']) {
if (password_verify($password, $EmailRecords['data']['password'])) {
//check if the remember_me was selected...
$Response = array(
'status' => true
);
$_SESSION['data'] = $EmailRecords['data'];
$_SESSION['auth_status'] = true;
header("Location: dashboard.php");
}
$Response = array(
'status' => false,
);
return $Response;
}
$Response = array(
'status' => false,
);
return $Response;
}
}
?>
8. Register.php সম্পাদনা করা (কন্ট্রোলার ফোল্ডার)
এই ফাইলটিতে রেজিস্টার কন্ট্রোলার নামে একটি ক্লাস রয়েছে যা বেস কন্ট্রোলারকে প্রসারিত করে। এটি একটি নির্ভরতা হিসাবে RegisterModel প্রয়োজন. রেজিস্টার ক্লাসের একটি নতুন দৃষ্টান্ত তৈরি করা হলে তা তাৎক্ষণিক হয়।
Register.php নীচের লাইন মত দেখতে হবে.
<?php
require_once(__dir__ . '/Controller.php');
require_once('./Model/RegisterModel.php');
class Register extends Controller {
public $active = 'Register'; //for highlighting the active link...
private $registerModel;
/**
* @param null|void
* @return null|void
* @desc Checks if the user session is set and creates a new instance of the RegisterModel...
**/
public function __construct()
{
if (isset($_SESSION['auth_status'])) header("Location: dashboard.php");
$this->registerModel = new RegisterModel();
}
/**
* @param array
* @return array|boolean
* @desc Verifies, Creates, and returns a user by calling the register method on the RegisterModel...
**/
public function register(array $data)
{
$name = stripcslashes(strip_tags($data['name']));
$email = stripcslashes(strip_tags($data['email']));
$phone = stripcslashes(strip_tags($data['phone']));
$password = stripcslashes(strip_tags($data['password']));
$EmailStatus = $this->registerModel->fetchUser($email)['status'];
$Error = array(
'name' => '',
'email' => '',
'phone' => '',
'password' => '',
'status' => false
);
if (preg_match('/[^A-Za-z\s]/', $name)) {
$Error['name'] = 'Only Alphabets are allowed.';
return $Error;
}
if (!empty($EmailStatus)) {
$Error['email'] = 'Sorry. This Email Address has been taken.';
return $Error;
}
if (preg_match('/[^0-9_]/', $phone)) {
$Error['phone'] = 'Please, use a valid phone number.';
return $Error;
}
if (strlen($password) < 7) {
$Error['password'] = 'Please, use a stronger password.';
return $Error;
}
$Payload = array(
'name' => $name,
'email' => $email,
'phone' => $phone,
'password' => password_hash($password, PASSWORD_BCRYPT)
);
$Response = $this->registerModel->createUser($Payload);
$Data = $this->registerModel->fetchUser($email)['data'];
unset($Data['password']); //Makes a whole lot of sense to get rid of any critical information...
if (!$Response['status']) {
$Response['status'] = 'Sorry, An unexpected error occurred and your request could not be completed.';
return $Response;
}
$_SESSION['data'] = $Data;
$_SESSION['auth_status'] = true;
header("Location: dashboard.php");
return true;
}
}
?>
Register() Method
এই পদ্ধতিটি একটি নতুন ব্যবহারকারী তৈরি করার জন্য সমস্ত কার্য পরিচালনা করে। পদ্ধতিটি একটি অ্যারে গ্রহণ করে এবং একটি অ্যারে ফেরত দেয় যদি ব্যবহারকারী যাচাইকরণে ব্যর্থ হয় । অন্যথায় একটি Http পুনঃনির্দেশ ফেরত দেওয়া হয় এবং ব্যবহারকারীর জন্য একটি নতুন সেশন তৈরি করা হয়।
9. Logout.php সম্পাদনা করা (কন্ট্রোলার ফোল্ডার)
এই ফাইলটিতে লগআউট কন্ট্রোলার নামে একটি ক্লাস রয়েছে যা বেস কন্ট্রোলারকে প্রসারিত করে।
Logout.php নীচের লাইনের মত দেখতে হবে.
<?php
require_once(__dir__ . '/Controller.php');
class Logout extends Controller {
/**
* @param null|void
* @return null|void
* @desc Destroys the application session and redirects to the login page...
**/
public function __construct()
{
session_destroy();
header("Location: index.php");
}
}
?>
10. আমাদের ভিউ ফাইল তৈরি করা
যেহেতু কন্ট্রোলার এবং মডেলগুলি সফলভাবে তৈরি করা হয়েছে, আমরা এখন আমাদের ভিউ ফাইলগুলি তৈরি করা শুরু করতে পারি। ভিউ ফাইলগুলি প্রজেক্টের রুট ডিরেক্টরিতে বাস করতে চলেছে।
এটি সত্যিই সর্বোত্তম পদ্ধতি নয় তবে একটি বড় অ্যাপ্লিকেশনের জন্য, আপনি সম্ভবত জিনিসগুলিকে পরিষ্কার এবং পেশাদার রাখার জন্য একটি পৃথক ফোল্ডারে ভিউ ফাইলগুলি রাখতে চান।
এটি মূলত ত্রুটি প্রদর্শনের জন্য কিছু সতর্কতা সহ একটি সাধারণ HTML ফর্ম হতে যাচ্ছে।
Nav.php সম্পাদনা করা হচ্ছে (রুট ডির)
nav.php আমাদের ভিউ এর বেস নেভিগেশন হিসেবে কাজ করবে। অন্য সব মতামত nav.php প্রসারিত করা হবে. আমাদের nav.php-এ, আমাদের কাছে একটি সাধারণ PHP কোড দ্বীপ রয়েছে যা বর্তমান ফাইলের শিরোনাম প্রিন্ট করে এবং বর্তমানে সক্রিয় ফাইলটিকে হাইলাইট করে।
আমাদের নেভিগেশনের জন্য সঠিক রাউটিং পরিচালনা করতে nav.php লোড হয় এবং একটি কনফিগার ডিরেক্টরি ব্যবহার করে যা নীচের স্নিপেটের মতো দেখায়।
<?php
define("BASE_URL", 'http://localhost/' . basename(__DIR__) . '/');
?>
<?php require_once('./config.php'); ?>
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<meta name="application-name" content="LD Talent Login Project">
<meta name="author" content="Ilori Stephen A">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>LD Talent | <?php echo ucfirst($active); ?></title>
<!-- Css Styles... -->
<link rel="stylesheet" href="./assets/css/bootstrap.min.css">
<link rel="stylesheet" href="./assets/css/style.css">
<!-- Script -->
<script src="./assets/js/jquery.js" charset="utf-8"></script>
<script src="./assets/js/bootstrap.min.js" charset="utf-8"></script>
</head>
<body>
<nav class="navbar navbar-expand-md navbar-dark fixed-top bg-dark">
<div class="container">
<a class="navbar-brand" href="#">LD Talent</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarCollapse" aria-controls="navbarCollapse" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarCollapse">
<ul class="navbar-nav ml-auto">
<?php if (!isset($_SESSION['auth_status'])) : ?>
<li class="nav-item">
<a class="nav-link <?php if (strtolower($active) === 'login') echo 'active'; ?>" href="<?php echo BASE_URL; ?>index.php">Login</a>
</li>
<li class="nav-item">
<a class="nav-link <?php if (strtolower($active) === 'register') echo 'active'; ?>" href="<?php echo BASE_URL; ?>register.php" tabindex="-1" aria-disabled="true">Register</a>
</li>
<?php elseif (isset($_SESSION['auth_status'])) : ?>
<li class="nav-item">
<a href="<?php echo BASE_URL; ?>dashboard.php" class="nav-link <?php if (strtolower($active) === 'dashboard') echo 'active'; ?>">Dashboard</a>
</li>
<?php endif; ?>
<?php if (isset($_SESSION['auth_status'])) : ?>
<li class="nav-item">
<a class="nav-link" href="<?php echo BASE_URL; ?>logout.php">Logout</a>
</li>
<?php endif; ?>
</ul>
</div>
</div>
</nav>
Index.php সম্পাদনা (রুট ডির)
index.php ফাইলটি আমাদের লগইন পৃষ্ঠা হিসাবে কাজ করে কারণ আপনি দেখতে পাবেন যে ফাইলের শীর্ষে লগইন কন্ট্রোলার ক্লাস প্রয়োজন। ক্লাসের একটি নতুন উদাহরণ তৈরি করা হয় এবং লগইন পদ্ধতিটি শুধুমাত্র তখনই কল করা হয় যখন একটি HTTP POST অনুরোধ করা হয়।
সেই ব্যাখ্যা সহ, নিম্নলিখিত কোড স্নিপেটটি index.php ফাইলে অনুলিপি করুন।
<?php require_once('./controller/Login.php'); ?>
<?php
$Login = new Login();
$Response = [];
$active = $Login->active;
if (isset($_POST) && count($_POST) > 0) $Response = $Login->login($_POST);
?>
<?php require('./nav.php'); ?>
<main role="main" class="container">
<div class="container">
<div class="row justify-content-center mt-10">
<div class="col-xs-12 col-sm-12 col-md-12 col-xl-4 col-lg-4 center-align center-block">
<?php if (isset($Response['status']) && !$Response['status']) : ?>
<div class="alert alert-danger" role="alert">
<span><B>Oops!</B> Invalid Credentials Used.</span>
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true" class="text-danger">×</span>
</button>
</div>
<?php endif; ?>
<div class="card shadow-lg p-3 mb-5 bg-white rounded">
<form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>" class="form-signin">
<h4 class="h3 mb-3 font-weight-normal text-center">Sign in</h4>
<div class="col-xs-12 col-sm-12 col-md-12 col-xl-12 col-lg-12 mt-4">
<div class="form-group">
<label for="inputEmail" class="sr-only">Email address</label>
<input type="email" id="inputEmail" class="form-control" placeholder="Email address" name="email" required autofocus>
</div>
</div>
<div class="col-xs-12 col-sm-12 col-md-12 col-xl-12 col-lg-12">
<div class="form-group">
<label for="inputPassword" class="sr-only">Password</label>
<input type="password" name="password" id="inputPassword" class="form-control" placeholder="Password" required>
</div>
</div>
<div class="col-xs-12 col-sm-12 col-md-12 col-xl-12 col-lg-12">
<button class="btn btn-md btn-primary btn-block" type="submit">Sign in</button>
</div>
<p class="mt-5 text-center mb-3 text-muted">© Ilori Stephen A <?php echo date('Y'); ?></p>
</form>
</div>
</div>
</div>
</div>
</main>
</body>
</html>
Register.php সম্পাদনা করা হচ্ছে (রুট ডির)
register.php ফাইলটিতে একটি নতুন ব্যবহারকারী তৈরি করার জন্য HTML ফর্ম রয়েছে। ফাইলের শীর্ষে রেজিস্টার কন্ট্রোলার ক্লাস প্রয়োজন। ক্লাসের একটি নতুন উদাহরণ তৈরি করা হয় এবং একটি HTTP POST অনুরোধ করা হলেই রেজিস্টার পদ্ধতিটি কল করা হয়।
ব্যবহারকারী বৈধকরণে ব্যর্থ হলে, ত্রুটিগুলি $Response ভেরিয়েবলে পাঠানো হয় যা অ্যারেতে একটি কী চেক করে শর্তসাপেক্ষে রেন্ডার করা হয়।
register.php ফাইলটি নিচের লাইনের মত দেখতে হবে।
<?php require_once('./controller/Register.php'); ?>
<?php
$Register = new Register();
$Response = [];
$active = $Register->active;
if (isset($_POST) && count($_POST) > 0) $Response = $Register->register($_POST);
?>
<?php require('./nav.php'); ?>
<main role="main" class="container">
<div class="container">
<div class="row justify-content-center mt-5">
<div class="col-xs-12 col-sm-12 col-md-12 col-xl-4 col-lg-4 center-align center-block">
<?php if (isset($Response['status']) && !$Response['status']) : ?>
<br>
<div class="alert alert-danger" role="alert">
<span><B>Oops!</B> Some errors occurred in your form.</span>
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true" class="text-danger">×</span>
</button>
</div>
<?php endif; ?>
<div class="card shadow-lg p-3 mb-5 bg-white rounded">
<form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>" class="form-signin">
<h4 class="h3 mb-3 font-weight-normal text-center">Register</h4>
<div class="col-xs-12 col-sm-12 col-md-12 col-xl-12 col-lg-12 mt-4">
<div class="form-group">
<label for="inputName" class="sr-only">Names</label>
<input type="text" id="inputName" class="form-control" placeholder="Enter Full Name" name="name" required autofocus value="<?php if (isset($_POST['name'])) echo $_POST['name']; ?>">
<?php if (isset($Response['name']) && !empty($Response['name'])): ?>
<small class="text-danger"><?php echo $Response['name']; ?></small>
<?php endif; ?>
</div>
</div>
<div class="col-xs-12 col-sm-12 col-md-12 col-xl-12 col-lg-12 mt-4">
<div class="form-group">
<label for="inputEmail" class="sr-only">Email</label>
<input type="email" id="inputEmail" class="form-control" placeholder="Enter Email Address" name="email" required autofocus value="<?php if (isset($_POST['email'])) echo $_POST['email']; ?>">
<?php if (isset($Response['email']) && !empty($Response['email'])): ?>
<small class="text-danger"><?php echo $Response['email']; ?></small>
<?php endif; ?>
</div>
</div>
<div class="col-xs-12 col-sm-12 col-md-12 col-xl-12 col-lg-12 mt-4">
<div class="form-group">
<label for="inputPhone" class="sr-only">Phone Number</label>
<input type="text" id="inputPhone" class="form-control" placeholder="Enter Phone" name="phone" required autofocus value="<?php if (isset($_POST['phone'])) echo $_POST['phone'] ?>">
<?php if (isset($Response['phone']) && !empty($Response['phone'])): ?>
<small class="text-danger"><?php echo $Response['phone']; ?></small>
<?php endif; ?>
</div>
</div>
<div class="col-xs-12 col-sm-12 col-md-12 col-xl-12 col-lg-12">
<div class="form-group">
<label for="inputPassword" class="sr-only">Password</label>
<input type="password" name="password" id="inputPassword" class="form-control" placeholder="Password" required>
<?php if (isset($Response['password']) && !empty($Response['password'])): ?>
<small class="text-danger"><?php echo $Response['password']; ?></small>
<?php endif; ?>
</div>
</div>
<div class="col-xs-12 col-sm-12 col-md-12 col-xl-12 col-lg-12">
<button class="btn btn-md btn-primary btn-block" type="submit">Register</button>
</div>
<p class="mt-5 text-center mb-3 text-muted">© Ilori Stephen A <?php echo date('Y'); ?></p>
</form>
</div>
</div>
</div>
</div>
</main>
</body>
</html>
Dashboard.php সম্পাদনা করা হচ্ছে (Rot Dir)
ড্যাশবোর্ড ভিউ হল যেখানে ব্যবহারকারীদের একটি সফল লগইন বা সাইনআপ অনুরোধের পরে পুনঃনির্দেশিত করা হয়৷ এটির জন্য ড্যাশবোর্ড কন্ট্রোলার ক্লাস প্রয়োজন এবং ক্লাসের একটি উদাহরণ তৈরি করে যা সমস্ত সংরক্ষিত খবরগুলি আনার জন্য getNews পদ্ধতিটি চালু করে।
dashboard.php ফাইলটি নিচের লাইনের মত দেখতে হবে।
<?php require_once('./controller/Dashboard.php'); ?>
<?php
$Dashboard = new Dashboard();
$Response = [];
$active = $Dashboard->active;
$News = $Dashboard->getNews();
?>
<?php require('./nav.php'); ?>
<main role="main" class="container">
<div class="container">
<div class="row mt-5">
<div class="col-xs-12 col-sm-12 col-md-12 col-xl-12 col-lg-12">
<h2>News</h2>
<hr>
</div>
</div>
<div class="row">
<?php if ($News['status']) : ?>
<?php foreach ($News['data'] as $new) : ?>
<div class="col-xs-12 col-sm-12 col-md-12 col-xl-4 col-lg-4">
<div class="card shadow-lg p-3 mb-5 bg-white rounded">
<div class="news_title">
<h3><?php echo ucwords($new['title']); ?></h3>
</div>
<div class="news_body">
<p><?php echo $new['content']; ?> <a href="javascript:void(0)">Read More</a></p>
</div>
</div>
</div>
<?php endforeach; ?>
<?php endif; ?>
</div>
</div>
</main>
</body>
</html>
Logout.php সম্পাদনা করা হচ্ছে (রুট ডির)
লগআউট ফাইলটি হল যেখানে ব্যবহারকারীর সেশনটি ধ্বংস হয়ে যায় এবং index.php ভিউতে একটি পুনঃনির্দেশ শুরু হয়।
যে বলে, logout.php ফাইলটি নীচের লাইনের মতো হওয়া উচিত।
<?php require_once('./controller/Logout.php'); ?>
<?php new Logout(); ?>