PHP Object Oriented Programming
PHP Object Oriented Programming পর্ব-৭: Static Method, Properties and Late Static Binding
Static Method এবং Property কি ?
Late Static Binding নিয়ে আমরা একটু পরেই আলোচনা করব, তার আগে চলুন static কি? সেই বিষয়ে আলোচনা করা যাক।
Object ছাড়া সরাসরি class এর Method এবং Property গুলোকে access করার জন্য সেই method এবং property গুলোকে কে static ঘোষণা করতে হয়। আর static ঘোষণা করার জন্য Method এবং Property নামের পূর্বে static কীওয়ার্ড ব্যবহার করতে হবে। static keyword টি কে access modifier ও বলা যায়। চলুন একটা উদাহরণ দিয়ে দেখা যাক:
<?php class testStatic{ // static methods and properties are defined with the static keyword. //You can add static keyword before or after visibility (Public, Private, Protected) public static $count = 0; static public $counter=1; public static function counter(){ } static public function anotherCounter(){ } } ?>
Static Method এবং Property গুলো কিভাবে access বা ব্যবহার করব?
Static Method এবং Property গুলোর ব্যবহার দুইভাবে ভাগ করা যায়।
১. class এর বাহিরে ব্যবহার
২. class এর ভিতরে ব্যবহার
Static Method এবং Property গুলোর class এর বাহিরে ব্যবহার :
Static Method এবং Property গুলোকে class এর বাহির থেকে Object ছাড়া ব্যবহার করতে চাইলে প্রথমে class এর নামের সাথে (::) scope resolution operator দিতে হয় , তারপর static Method অথবা Property এর নাম লিখতে হয় । আরো ভালো ভাবে বুঝার জন্য নিম্নের উদাহরণটি দেখুন :
<?php class testStatic{ public static $count = 0; public static function counter(){ echo "Its Static Counter"; } } //Accessing Static Property and Method Outside of the Class testStatic::$count=5; // Assigning Value to static Property echo testStatic::$count; // Calling Static Property with Updated Value echo "<br>"; testStatic::counter(); // Calling Static Method with Updated Value ?>
Note: scope resolution operator এর পর property নাম এর সাথে অবশ্যই $ (dollar sign) দিতে হবে।
Static Method এবং Property গুলোর class এর ভিতরে ব্যবহার :
Static Method এবং Property গুলোকে class এর ভিতরে $this pseudo-variable ছাড়া ব্যবহার করতে চাইলে প্রথমে class এর নাম অথবা self keyword এর সাথে (::) scope resolution operator দিতে হয় , তারপর static Method অথবা Property এর নাম দিতে হয় । আরো ভালো ভাবে বুঝার জন্য নিম্নের উদাহরণটি দেখুন :
<?php class testStatic{ public static $count = 0; public static function counter(){ echo "Its Static Counter: "; echo self::$count++,"<br>"; // accessing static Property inside class } } // Calling Static Method Outside Class testStatic::counter(); testStatic::counter(); testStatic::counter(); ?>
Result:
Create Mathematical Operation with static properties and methods
চলুন static methods এবং properties সহ PHP OOP (Object-Oriented Programming) এর একটি বাস্তব উদাহরণ বিবেচনা করা যাক। এই উদাহরণে, আমরা একটি MathUtility ক্লাস তৈরি করব যাতে গাণিতিক ক্রিয়াকলাপ সম্পাদনের জন্য static methods এবং property রয়েছে।
class MathUtility { // Static property to store the total number of calculations private static $totalCalculations = 0; // Static method to add two numbers public static function add($a, $b) { self::$totalCalculations++; // Increment the total calculations count return $a + $b; } // Static method to subtract two numbers public static function subtract($a, $b) { self::$totalCalculations++; // Increment the total calculations count return $a - $b; } // Static method to get the total number of calculations public static function getTotalCalculations() { return self::$totalCalculations; } } // Example usage $result1 = MathUtility::add(5, 3); // Result: 8 $result2 = MathUtility::subtract(10, 4); // Result: 6 // Get the total number of calculations $totalCalculations = MathUtility::getTotalCalculations(); // Display results echo "Result 1: $result1<br>"; echo "Result 2: $result2<br>"; echo "Total Calculations: $totalCalculations";
এই উদাহরণে:
- ১. MathUtility ক্লাসের একটি private static property $totalCalculations সম্পাদিত গণনার total number ট্র্যাক রাখার জন্য রয়েছে।
- ২. Two static methods, add এবং subtract, mathematical operations (addition এবং subtraction) operations এবং total calculations count বৃদ্ধি করে।
- ৩. আরেকটি static method, getTotalCalculations, যা total number রিট্রিভ করে।
- ৪. ক্লাসের বাইরে, আমরা ক্লাসের কোনো instance তৈরি না করেই static methods (add, subtract, getTotalCalculations) কল করার জন্য class name এবং :: (double colon) সিনট্যাক্স ব্যবহার করি।
- ৫. গণনার ফলাফলগুলি সম্পাদিত গণনার মোট সংখ্যা সহ প্রদর্শিত হয়।
Log Count with Static Properties and Methods
চলুন Static Method এবং Properties ব্যবহার করে আরো একটি উদাহরণ দেখা যাক:
এই class টি messages লগ করা, লগ কাউন্ট ট্র্যাক রাখা এবং লগগুলি বের করার একটি মেথড প্রদানের জন্য দায়িত্বে থাকবে।
class Logger { // Static property to store the logs private static $logs = []; // Static property to store the total number of logs private static $totalLogs = 0; // Static method to log a message public static function log($message) { $timestamp = date('Y-m-d H:i:s'); $logEntry = "$timestamp - $message"; self::$logs[] = $logEntry; // Add the log entry to the logs array self::$totalLogs++; // Increment the total logs count } // Static method to get all logs public static function getLogs() { return self::$logs; } // Static method to get the total number of logs public static function getTotalLogs() { return self::$totalLogs; } } // Example usage Logger::log("User logged in."); Logger::log("Error: Database connection failed."); Logger::log("New product added."); // Get all logs and total log count $allLogs = Logger::getLogs(); $totalLogs = Logger::getTotalLogs(); // Display logs and total log count echo "All Logs:<br>"; foreach ($allLogs as $log) { echo "- $log<br>"; } echo "<br>Total Logs: $totalLogs";
Create Secure User Management System with static property and methods
ইউজারের ডেটা, authentication এবং রেজিস্টার্ড ইউজার সংখ্যা গণনা করার জন্য static methods এবং Static Properties দিয়ে আরো একটি উদাহরণ দেখা যাক :
class User { // Static property to store user data private static $users = []; // Static property to store the total number of registered users private static $totalUsers = 0; // Static method to register a new user public static function register($username, $email, $password) { // Validate username, email, and password if (!self::isValidUsername($username) || !self::isValidEmail($email) || !self::isValidPassword($password)) { return false; // Registration failed due to invalid data } // Hash the password before storing it $hashedPassword = password_hash($password, PASSWORD_DEFAULT); // Add the new user to the users array self::$users[$username] = [ 'username' => $username, 'email' => $email, 'hashedPassword' => $hashedPassword, ]; // Increment the total users count self::$totalUsers++; return true; // Registration successful } // Static method to authenticate a user public static function authenticate($username, $password) { // Check if the user exists if (isset(self::$users[$username])) { $hashedPassword = self::$users[$username]['hashedPassword']; // Verify the password if (password_verify($password, $hashedPassword)) { return true; // Authentication successful } } return false; // Authentication failed } // Static method to get the total number of registered users public static function getTotalUsers() { return self::$totalUsers; } // Static method for username validation private static function isValidUsername($username) { // Add validation rules for the username (e.g., minimum length) return strlen($username) >= 4; } // Static method for email validation private static function isValidEmail($email) { // Use PHP's built-in email validation for simplicity return filter_var($email, FILTER_VALIDATE_EMAIL) !== false; } // Static method for password validation private static function isValidPassword($password) { // Add validation rules for the password (e.g., minimum length) return strlen($password) >= 8; } } // Example usage if (User::register('john_doe', 'john@example.com', 'password123')) { echo "Registration successful!<br>"; } else { echo "Registration failed. Invalid data!<br>"; } if (User::authenticate('john_doe', 'password123')) { echo "Authentication successful!<br>"; } else { echo "Authentication failed. Invalid credentials!<br>"; } // Get the total number of registered users $totalUsers = User::getTotalUsers(); // Display total users count echo "Total Registered Users: $totalUsers";
Late Static Binding কি ?
PHP তে Static Method এবং Property গুলোকে class এর ভিতরে কল করার জন্য $this pseudo-variable এর পরিবর্তে class এর নাম অথবা “self” keyword এর সাথে (::) scope resolution operator দিয়ে ব্যবহার করা হয় , তখন যেই class এ “self” keyword ব্যবহার করা হয়েছে, “self” keyword শুধু ঐ ক্লাসকেই নির্দিষ্ট করে নেয়। আর তাতে Parent Class এর static Method এবং Property গুলোকে child class এ inherit হয়না। আর সেই জন্য PHP 5.3 থেকে Parent Class এর Static Method এবং Property গুলোকে কে child class এ inherit করার জন্য static Method এবং Property কল করার সময় “self” keyword এর পরিবর্তে “static” keyword ব্যবহার প্রয়োগ করা হয়েছে, আর এটাকেই PHP 5.3 থেকে Late Static Binding বলা হয়। আরো ভালো ভাবে বুঝার জন্য নিম্নের উদাহরণ দুটি দেখুন :
উদাহরণ: “self” keyword এর ব্যবহার
<?php class Course{ protected static $courseName = 'Professional PHP'; public static function getCourseName(){ return self::$courseName; } } class Student extends Course{ protected static $courseName = 'Laravel'; } echo Student::getCourseName(); // Professional PHP, not Laravel
ব্যাখ্যা:
- প্রথমত, আমরা Course নামক একটি Class তৈরী করি যার মধ্যে আছে $courseName নামে একটি static property যার Value হচ্ছে “PHP Professional” এবং getCourseName নামে একটি static Method তৈরী করি যা $courseName Property এর value return করবে। লক্ষ্য করবেন, যে আমরা Course Class এর ভিতরে static property তে access করার জন্য self এবং “::” scope resolution Operator ব্যবহার করেছি।
- দ্বিতীয়ত , আমরা Student নামে Course class থেকে একটি child class তৈরী করি, এবং Student class এর মধ্যেও $courseName নামে একটি static property আছে যার value হচ্ছে “Laravel” .
- তৃতীয়ত , আমরা আমাদের Student child class দিয়ে Course class থেকে getCourseName method কল করি। যাতে আমরা আমাদের Student Child Class এর course name হিসেবে “laravel” পাই। যাই হোক Course class এর getCourseName Method টি আমাদের কে ফলাফল হিসেবে “Laravel” এর পরিবর্তে “PHP Professional” রিটার্ন করে, এর কারণ হচ্ছে self keyword যেই class এ কল করা হয় সেই class ছাড়া child বা অন্য কোনো class কে নির্দিষ্ট করেনা।
উপরের সমস্যা কে সমাধান করার জন্য PHP 5.3 থেকে Late Static Binding সুবিধা যোগ করে। মূলত, self keyword এর পরিবর্তে static keyword টি ব্যবহার করা হয়েছে, যেন যেই class থেকে call করা হবে যেন সেই class কে নির্দিষ্ট করে। চলুন উপরে আমাদের উদাহরণ পরিবর্তন করা যাক:
উদাহরণ: “static” keyword বা Late Static Binding এর ব্যবহার
<?php class Course{ protected static $courseName = 'Professional PHP'; public static function getCourseName(){ return static::$courseName; } } class Student extends Course{ protected static $courseName = 'Laravel'; } echo Student::getCourseName(); // Laravel
এখন আমরা আমাদের প্রত্যাশিত ফলাফল পাব।
Create a Employee Management System with Late Static Binding Feature
আসুন পিএইচপি-তে late static binding ব্যবহার করে একটি বাস্তব-বিশ্বের উদাহরণ তৈরি করি। এই উদাহরণে, আমরা একটি কোম্পানিতে বিভিন্ন ধরনের কর্মচারীদের পরিচালনার জন্য একটি simple framework তৈরি করব। আমরা একটি generic Employee class বাস্তবায়ন করতে late static binding ব্যবহার করব এবং তারপর ম্যানেজার এবং ডেভেলপারের মতো নির্দিষ্ট এমপ্লয়ীদের টাইপ গুলো তৈরি করব।
class Employee { protected static $employeeCount = 0; protected $name; protected $salary; public function __construct($name, $salary) { $this->name = $name; $this->salary = $salary; static::$employeeCount++; } public static function getEmployeeCount() { return static::$employeeCount; } public function getDetails() { return "Name: {$this->name}, Salary: {$this->salary}"; } } class Manager extends Employee { protected static $managerCount = 0; protected $department; public function __construct($name, $salary, $department) { parent::__construct($name, $salary); $this->department = $department; static::$managerCount++; } public static function getManagerCount() { return static::$managerCount; } public function getDetails() { $parentDetails = parent::getDetails(); return "$parentDetails, Department: {$this->department}"; } } class Developer extends Employee { protected static $developerCount = 0; protected $programmingLanguage; public function __construct($name, $salary, $programmingLanguage) { parent::__construct($name, $salary); $this->programmingLanguage = $programmingLanguage; static::$developerCount++; } public static function getDeveloperCount() { return static::$developerCount; } public function getDetails() { $parentDetails = parent::getDetails(); return "$parentDetails, Programming Language: {$this->programmingLanguage}"; } } // Example usage $manager1 = new Manager('John Doe', 60000, 'Human Resources'); $developer1 = new Developer('Alice Smith', 50000, 'PHP'); $developer2 = new Developer('Bob Johnson', 55000, 'JavaScript'); // Get total counts for all employees, managers, and developers $totalEmployees = Employee::getEmployeeCount(); $totalManagers = Manager::getManagerCount(); $totalDevelopers = Developer::getDeveloperCount(); // Display employee details and counts echo "Employee Details:<br>"; echo $manager1->getDetails() . "<br>"; echo $developer1->getDetails() . "<br>"; echo $developer2->getDetails() . "<br>"; echo "<br>Total Employees: $totalEmployees<br>"; echo "Total Managers: $totalManagers<br>"; echo "Total Developers: $totalDevelopers";
Create Content Management Sytem with Late Static Binding
আসুন একটি content management system (CMS) আরও বিস্তৃত উদাহরণ বিবেচনা করা যাক যেখানে articles, videos এবং images এর মতো বিভিন্ন ধরনের কনটেন্ট এলিমেন্ট গুলি পরিচালনা করতে late static binding ব্যবহার করা হয়। প্রতিটি কনটেন্ট টাইপের নির্দিষ্ট আচরণের সাথে নিজস্ব ক্লাস থাকবে, এবং একটি factory class, late static binding ব্যবহার করে কনটেন্ট টাইপের উপর ভিত্তি করে ডায়নামিক্যাললি instances তৈরি করবে।
abstract class Content { protected $title; protected $url; public function __construct($title, $url) { $this->title = $title; $this->url = $url; } abstract public function render(); } class Article extends Content { public function render() { return "Rendering Article: {$this->title}"; } } class Video extends Content { public function render() { return "Rendering Video: {$this->title}"; } } class Image extends Content { public function render() { return "Rendering Image: {$this->title}"; } } class ContentFactory { public static function createContent($type, $title, $url) { $className = ucfirst($type); if (class_exists($className)) { return new $className($title, $url); } else { throw new Exception("Invalid content type: $type"); } } } // Example usage try { $article = ContentFactory::createContent('article', 'PHP Best Practices', '/articles/php-best-practices'); $video = ContentFactory::createContent('video', 'Introduction to OOP', '/videos/oop-introduction'); $image = ContentFactory::createContent('image', 'Sunset Landscape', '/images/sunset-landscape'); echo $article->render() . "<br>"; echo $video->render() . "<br>"; echo $image->render() . "<br>"; } catch (Exception $e) { echo "Error: " . $e->getMessage(); }
এই উদাহরণটি ব্যাখ্যা করে যে কিভাবে late static binding একটি content management system এ ব্যবহার করা যেতে পারে তাদের নিজস্ব আচরণের সাথে বিভিন্ন কন্টেন্টের ধরন পরিচালনা করার জন্য যখন dynamic creation এবং রেন্ডারিংয়ের এর সুযোগ দেয়।
PDO-Enhanced Database Model with Late Static Binding
এখানে আমরা একটি ডাটাবেস সংযোগ স্থাপনের জন্য একটি DatabaseConnection ক্লাস তৈরি করব, এবং DatabaseModel ক্লাস CRUD (Create, Read, Update, Delete) অপারেশনের জন্য এই সংযোগটি ব্যবহার করবে। এই উদাহরণটি বুঝার জন্য নিম্নোক্ত Database table দুটি তৈরি করে নিন :
-- Table structure for users CREATE TABLE users ( id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(255) NOT NULL, email VARCHAR(255) NOT NULL ); -- Table structure for products CREATE TABLE products ( id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(255) NOT NULL, price DECIMAL(10, 2) NOT NULL );
এবার আমরা ক্লাস গুলো তৈরি করব :
class DatabaseConnection { private static $connection; public static function getConnection() { if (!isset(self::$connection)) { $host = 'your_database_host'; $dbname = 'your_database_name'; $username = 'your_database_username'; $password = 'your_database_password'; try { self::$connection = new PDO("mysql:host=$host;dbname=$dbname", $username, $password); self::$connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); } catch (PDOException $e) { die("Connection failed: " . $e->getMessage()); } } return self::$connection; } } class DatabaseModel { protected static $table; protected $data; public function __construct(array $data) { $this->data = $data; } public function save() { $columns = implode(', ', array_keys($this->data)); $values = implode(', ', array_fill(0, count($this->data), '?')); $query = "INSERT INTO {$this::$table} ($columns) VALUES ($values)"; $stmt = DatabaseConnection::getConnection()->prepare($query); $stmt->execute(array_values($this->data)); echo "Saved data to the '{$this::$table}' table.<br>"; } public static function find($id) { $query = "SELECT * FROM {$this::$table} WHERE id = ?"; $stmt = DatabaseConnection::getConnection()->prepare($query); $stmt->execute([$id]); $data = $stmt->fetch(PDO::FETCH_ASSOC); if ($data) { echo "Fetched data from the '{$this::$table}' table for ID $id.<br>"; return new static($data); } else { echo "No data found for ID $id in the '{$this::$table}' table.<br>"; return null; } } } class User extends DatabaseModel { protected static $table = 'users'; } class Product extends DatabaseModel { protected static $table = 'products'; } // Example usage $user = new User(['name' => 'John Doe', 'email' => 'john@example.com']); $user->save(); $product = new Product(['name' => 'Laptop', 'price' => 999]); $product->save(); $retrievedUser = User::find(1); $retrievedProduct = Product::find(101);
এই উদাহরণটি দেখায় যে কিভাবে late static binding একটি flexible এবং extensible database model system তৈরি করতে ব্যবহার করা যেতে পারে, বিভিন্ন মডেলগুলিকে প্রতিটি মডেলের জন্য টেবিলের নাম এবং নির্দিষ্ট আচরণগুলি কাস্টমাইজ করার সময় common database interaction method গুলি ভাগ করার অনুমতি দেয়।
One thought on “PHP Object Oriented Programming পর্ব-৭: Static Method, Properties and Late Static Binding”
Leave a Reply
You must be logged in to post a comment.
You are helping me a lot. I am passing maximum hours in your blog to learn interesting lesson.