PHP Object Oriented Programming পর্ব-১১: PHP Object Serializing

PHP OOP তে Object Serializing এবং unserializing কি?

serialize

বিভিন্ন PHP ভিত্তিক প্রজেক্ট ডেভেলপ করার সময় Object গুলোকে web forms, url এর মাধ্যমে pass করার জন্যে অথবা text file এবং Database এ সংরক্ষণ করার জন্য , অনেক সময় আমাদেরকে Object গুলোকে string এ convert বা রূপান্তর করার প্রয়োজন হয়। । PHP OOP তে Object কে string এ পরিবর্তন করার পদ্ধতিকে Object Serializing বলা হয়। এবং string কে Object এ পরিবর্তন করার পদ্ধতিকে Object Unserializing বলা হয়।

PHP OOP তে কিভাবে Object কে string এ রূপান্তর বা Serializing করা হয়?

PHP তে serialize() function দিয়ে Object কে string এ রূপান্তর করা হয়। চলুন একটা উদাহরণ দিয়ে বুঝা যাক:

<?php
class Member
{
  public $username = "";
  private $loggedIn = false;
  
  public function login() {
    $this->loggedIn = true;
  }
  
  public function logout() {
    $this->loggedIn = false;
  }
  
  public function isLoggedIn() {
    return $this->loggedIn;
  }
}
 
$member = new Member();
$member->username = "Farhan";
$member->login();
 
$memberString = serialize($member);
echo "Converted the Member to a string: $memberString \n";
?>

PHP Serialize Example

ব্যাখ্যা: লক্ষ্য করুন, আমরা একটা সাধারণ Member class তৈরী করি। এবং $username নামে একটি public এবং $loggedIn নামে private property তৈরী করি। এবং তিনটি public function যথাক্রমে login(), logout() এবং isLoggedIn() তৈরী করি। আমাদের script টি তারপর একটি নতুন Object তৈরি করে, আর “Farhan” নামে একটি user কে $username property তে সেট করি , এবং Login Method দিয়ে ইউজার “Farhan” কে লগ ইন করাই।

তারপর আমরা serialize() function কে কল করি এবং Member Object কে serialize() function এর মধ্যে Pass করাই। serialize () function টি Object এর একটি string return করে , যা আমরা $memberString এ সংরক্ষণ করি এবং page এ show করি।

https://blog.w3programmers.com/php-course/

PHP OOP তে কিভাবে String কে Object এ রূপান্তর বা Unserializing করা হয়?

PHP তে unserialize() function দিয়ে String কে Object এ রূপান্তর করা হয়। চলুন একটা উদাহরণ দিয়ে বুঝা যাক:

<?php
class Member
{
  public $username = "";
  private $loggedIn = false;
  
  public function login() {
    $this->loggedIn = true;
  }
  
  public function logout() {
    $this->loggedIn = false;
  }
  
  public function isLoggedIn() {
    return $this->loggedIn;
  }
}
 
$member = new Member();
$member->username = "Farhan";
$member->login();
 
$memberString = serialize( $member );
$member2 = unserialize( $memberString );
echo $member2->username . " is " . ( $member2->isLoggedIn() ? "logged in" : "logged out" ) . "<br>";
  

Unserializing Example

ব্যাখ্যা: লক্ষ্য করুন আমাদের serialize() function দিয়ে তৈরী string কে unserialize function দিয়ে আবার object এ রূপান্তর করি এবং $member2 নামক ভ্যারিয়েবল এ রাখি। এখন আমরা $member2 Object variable হিসেবে ব্যবহার করি।

https://blog.w3programmers.com/php-course/

একটা বড় Object এর সব গুলো property এর পরিবর্তে নির্দিষ্ট কিছু property কে নিয়ে string এ convert বা serialize করার উপায় কি?

একটা বড় Object এর সব গুলো property এর পরিবর্তে নির্দিষ্ট কিছু property কে নিয়ে string এ convert বা serialize করতে চাইলে PHP তে __sleep() ম্যাজিক মেথড টি ব্যবহার করতে হয়। চলুন দুইটি উদাহরণ দিয়ে বিষয়টা বুঝা যাক :

__sleep() মেথড ব্যতীত serialize উদাহরণ :

<?php
class Member{
  public $Name="Masud Alam";
  public $Email="masud@mail.com";
  public $mobile="01788990099";
  public  $address="Dhaka,Bangladesh";
}
 
$member = new Member();
 
$memberString = serialize( $member );

echo $memberString;
?>

Result:

O:6:"Member":4:{s:4:"Name";s:10:"Masud Alam";s:5:"Email";
s:14:"masud@mail.com";s:6:"mobile";
s:11:"01788990099";s:7:"address";s:16:"Dhaka,Bangladesh";}

ব্যাখ্যা : লক্ষ্য করুন , আমাদের সব গুলো property সহ Object টি serialize string এ রূপান্তর হয়ে গেছে।

__sleep() মেথড সহ serialize উদাহরণ :

<?php
class Member{
  public $Name="Masud Alam";
  public $Email="masud@mail.com";
  public $mobile="01788990099";
  public  $address="Dhaka,Bangladesh";
  public function __sleep(){
    return ["Name","Email"];
  }
}
 
$member = new Member();
 
$memberString = serialize( $member );

echo $memberString;
?>

sleep example

ব্যাখ্যা : লক্ষ্য করুন , আমাদের সব গুলো property এর মধ্যে শুধু __sleep() এর মধ্যে যে property গুলো array এর মধ্যে দেওয়া আছে , শুধু সেগুলো string এ রূপান্তর বা serialize হয়েছে ।

একটি serialize string কে unserialize বা Object এ convert করার সময় Object টিকে reestablish বা re-initialization অর্থাৎ , যেমন: Database Connection , session start করা যাবে ?

একটি serialize string কে unserialize বা Object এ convert করার সময় Object টিকে reestablish বা re-initialization করতে চাইলে PHP তে __wakeup() ম্যাজিক মেথড টি ব্যবহার করতে হয়। চলুন একটি উদাহরণ দিয়ে বিষয়টা বুঝা যাক :

<?php
class Connection
{
    protected $link;
    private $dsn, $username, $password;
    
    public function __construct($dsn, $username, $password)
    {
        $this->dsn = $dsn;
        $this->username = $username;
        $this->password = $password;
        $this->connect();
    }
    
    private function connect()
    {
        $this->link = new PDO($this->dsn, $this->username, $this->password);
    }
    
    public function __sleep()
    {
        return array('dsn', 'username', 'password');
    }
    
    public function __wakeup()
    {
        $this->connect();
    }
}?>

বাস্তব-বিশ্বের পরিপ্রেক্ষিতে PHP Object serialization এবং un-serialization এর ব্যবহারের ক্ষেত্র গুলো নিম্নে দেওয়া হলো :

১. Session Persistence:

  • ১. সেশন ভেরিয়েবলে অবজেক্ট সহ complex data structure গুলো সংরক্ষণ করা।
  • ২. সিরিয়ালাইজড ডেটা একটি ডাটাবেসে সংরক্ষণ করা যেতে পারে বা একাধিক সার্ভার জুড়ে ভাগ করা যেতে পারে।

নিম্নের উদাহরণটি লক্ষ্য করুন :

Task.php Class File

<?php 
class Task {
    private $title;
    private $description;
    private $dueDate;
    private $status;

    public function __construct($title, $description, $dueDate, $status) {
        $this->title = $title;
        $this->description = $description;
        $this->dueDate = $dueDate;
        $this->status = $status;
    }

      // Getter method for status
      public function getStatus() {
        return $this->status;
    }

    // Getter method for title
    public function getTitle() {
        return $this->title;
    }

    // Magic method to define which properties to serialize
    public function __sleep() {
        return ['title', 'description', 'dueDate', 'status'];
    }

    // Magic method to restore any resources that the object may have
    public function __wakeup() {
        // For demonstration purposes, let's update the status on wakeup
        $this->status = 'Unserialized';
        echo "Task object has been unserialized.\n";
    }

    // Getter methods for private properties
    // Additional methods for task-related actions can be added
}

TaskManager.php Class File Code

<?php
class TaskManager {
    private $tasks = [];

    public function addTask(Task $task) {
        $this->tasks[] = $task;
    }

    public function getTasks() {
        return $this->tasks;
    }

    // Magic method to define which properties to serialize
    public function __serialize(): array {
        return ['tasks' => $this->tasks];
    }

    // Magic method to restore any resources that the object may have
    public function __unserialize(array $data): void {
        $this->tasks = $data['tasks'];
        echo "TaskManager object has been unserialized.\n";
    }

    // Additional methods for task manager actions can be added
}

TaskUsage.php Code

<?php
include 'Task.php';
include 'taskmanager.php';
// Start or resume the session
session_start();

// Check if the task manager is already in the session
if (!isset($_SESSION['task_manager'])) {
    // If not, create a new task manager
    $taskManager = new TaskManager();

    // Create tasks and add them to the task manager
    $task1 = new Task('Complete Project', 'Finish coding and testing', '2023-12-31', 'Pending');
    $task2 = new Task('Review Proposal', 'Check and provide feedback', '2023-12-15', 'In Progress');

    $taskManager->addTask($task1);
    $taskManager->addTask($task2);

    // Store the task manager object in the session
    $_SESSION['task_manager'] = $taskManager;

    // Serialize the task manager before storing it in the session
    $serializedTaskManager = serialize($_SESSION['task_manager']);
    $_SESSION['serialized_task_manager'] = $serializedTaskManager;
} else {
    // If the task manager is already in the session, unserialize it
    $unserializedTaskManager = unserialize($_SESSION['serialized_task_manager']);

    // Access task manager properties
    $tasks = $unserializedTaskManager->getTasks();
    foreach ($tasks as $task) {
        echo "Task: {$task->getTitle()}, Status: {$task->getStatus()}\n<br>";
    }
}


// Perform additional actions or modifications
// For demonstration purposes, we'll add a new task to the task manager
$newTask = new Task('Write Documentation', 'Document the code and features', '2023-12-20', 'Pending');
$unserializedTaskManager->addTask($newTask);

// Serialize the updated task manager before storing it in the session
$serializedTaskManager = serialize($unserializedTaskManager);
$_SESSION['serialized_task_manager'] = $serializedTaskManager;

// Unserialize the task manager when retrieving it from the session
$finalUnserializedTaskManager = unserialize($_SESSION['serialized_task_manager']);

// Access and display the final tasks
$finalTasks = $finalUnserializedTaskManager->getTasks();
foreach ($finalTasks as $task) {
    echo "Task: {$task->getTitle()}, Status: {$task->getStatus()}\n<br>";
}

২. Data Transfer:

  • একটি অ্যাপ্লিকেশনের বিভিন্ন অংশ বা বিভিন্ন অ্যাপ্লিকেশনের মধ্যে জটিল ডেটা স্ট্রাকচার প্রেরণ করা।
  • HTTP রিকোয়েস্টের মাধ্যমে সিরিয়ালাইজড ডেটা পাঠানো বা পরবর্তীতে পুনরুদ্ধারের জন্য একটি ফাইলে সংরক্ষণ করা।

নিম্নের উদাহরণটি লক্ষ্য করুন :

একটি ওয়েব অ্যাপ্লিকেশনে ডেটা স্থানান্তরের জন্য অবজেক্ট সিরিয়ালাইজেশন ব্যবহারের একটি বাস্তব উদাহরণ বিবেচনা করা যাক। আমরা ইউজারের প্রোফাইল পরিচালনার জন্য একটি সহজ সিস্টেম তৈরি করব। ইউজারের ব্যক্তিগত তথ্য দিয়ে প্রোফাইল তৈরি করতে পারেন এবং অ্যাপ্লিকেশনটি স্টোরেজ এবং ট্রান্সমিশনের জন্য এই প্রোফাইলগুলিকে সিরিয়ালাইজ করবে।

UserProfile.php File Code

<?php
class UserProfile {
    private $username;
    private $email;
    private $dob;  // Date of birth

    public function __construct($username, $email, $dob) {
        $this->username = $username;
        $this->email = $email;
        $this->dob = $dob;
    }

    // Getter methods for private properties
    public function getUsername() {
        return $this->username;
    }

    public function getEmail() {
        return $this->email;
    }

    public function getDOB() {
        return $this->dob;
    }
}

UserProfileManager.php File Code

<?php
class UserProfileManager {
    private $userProfiles = [];

    public function addUserProfile(UserProfile $profile) {
        $this->userProfiles[] = $profile;
    }

    public function getUserProfiles() {
        return $this->userProfiles;
    }

    // Serialize user profiles to a file
    public function saveToFile($filename) {
        $serializedData = serialize($this->userProfiles);
        file_put_contents($filename, $serializedData);
        echo "User profiles saved to $filename.\n";
    }

    // Deserialize user profiles from a file
    public function loadFromFile($filename) {
        if (file_exists($filename)) {
            $serializedData = file_get_contents($filename);
            $this->userProfiles = unserialize($serializedData);
            echo "User profiles loaded from $filename.\n";
        } else {
            echo "File $filename not found.\n";
        }
    }
}

UserProfileUsage.php File Code

<?php
include 'UserProfile.php';
include 'UserProfileManager.php';
// Example Usage:

// Create a user profile manager
$profileManager = new UserProfileManager();

// Create user profiles
$user1 = new UserProfile('john_doe', 'john@example.com', '1990-01-15');
$user2 = new UserProfile('jane_doe', 'jane@example.com', '1988-05-22');

// Add user profiles to the manager
$profileManager->addUserProfile($user1);
$profileManager->addUserProfile($user2);

// Save user profiles to a file
$profileManager->saveToFile('user_profiles.dat');

// Load user profiles from the file
$profileManager->loadFromFile('user_profiles.dat');

// Display user profiles
$userProfiles = $profileManager->getUserProfiles();
foreach ($userProfiles as $profile) {
    echo "Username: {$profile->getUsername()}, Email: {$profile->getEmail()}, DOB: {$profile->getDOB()}\n";
}

৩. State Management:

পরবর্তীতে পুনরায় চালু করার জন্য একটি object বা application এর state সংরক্ষণ করা হচ্ছ এমন পরিস্থিতিতে দরকারী যেখানে একটি অ্যাপ্লিকেশন paused এবং resumed করতে হবে, এই ধরণের পরিস্থিতিতে Object Serialization ব্যবহার করা যেতে পারে।

নিম্নের উদাহরণটি লক্ষ্য করুন :

আসুন একটি উদাহরণ অন্বেষণ করা যাক যা state management এর উপর ফোকাস সহ সিরিয়ালাইজেশনের আরও traditional approach এর উপর ফোকাস করে। এই পরিস্থিতিতে, আসুন একটি BankAccount ক্লাস বিবেচনা করি যা ব্যবহারকারীদের অর্থ জমা এবং উত্তোলন করতে দেয়। আমরা অ্যাকাউন্টের ব্যালেন্স সহ অ্যাকাউন্টের অবস্থা সংরক্ষণ এবং লোড করার জন্য সিরিয়ালাইজেশন প্রয়োগ করব।

<?php
class BankAccount {
    private $accountNumber;
    private $accountHolder;
    private $balance;

    public function __construct($accountNumber, $accountHolder, $balance = 0) {
        $this->accountNumber = $accountNumber;
        $this->accountHolder = $accountHolder;
        $this->balance = $balance;
    }

    public function deposit($amount) {
        $this->balance += $amount;
    }

    public function withdraw($amount) {
        if ($amount <= $this->balance) {
            $this->balance -= $amount;
        } else {
            echo "Insufficient funds." . PHP_EOL;
        }
    }

    public function getBalance() {
        return $this->balance;
    }

    public function displayAccountInfo() {
        echo "Account Number: {$this->accountNumber}" . PHP_EOL;
        echo "Account Holder: {$this->accountHolder}" . PHP_EOL;
        echo "Balance: {$this->balance}" . PHP_EOL;
    }

    public function saveState($filename) {
        file_put_contents($filename, serialize($this));
    }

    public function loadState($filename) {
        $data = file_get_contents($filename);
        if ($data !== false) {
            $account = unserialize($data);
            $this->accountNumber = $account->accountNumber;
            $this->accountHolder = $account->accountHolder;
            $this->balance = $account->balance;
        } else {
            echo "Failed to load account state." . PHP_EOL;
        }
    }

    public function __sleep() {
        // Specify the properties to be serialized when saving the object state
        return ['accountNumber', 'accountHolder', 'balance'];
    }

    public function __wakeup() {
        // Any necessary reinitialization when unserializing the object
    }

    public function __serialize(): array {
        // Customize the serialization process, returning an array of serialized data
        return [
            'accountNumber' => $this->accountNumber,
            'accountHolder' => $this->accountHolder,
            'balance' => $this->balance,
        ];
    }

    public function __unserialize(array $data): void {
        // Customize the unserialization process, restoring the object state from the serialized data
        $this->accountNumber = $data['accountNumber'];
        $this->accountHolder = $data['accountHolder'];
        $this->balance = $data['balance'];
    }
}

// Example Usage
$account = new BankAccount('123456', 'John Doe');
$account->deposit(1000);
$account->withdraw(500);

// Save the state
$account->saveState('account_state.txt');

// Display account information
$account->displayAccountInfo();

// Load the state
$loadedAccount = new BankAccount('', '');
$loadedAccount->loadState('account_state.txt');

// Display loaded account information
echo "Loaded Account Information:" . PHP_EOL;
$loadedAccount->displayAccountInfo();

৪. Configuration Persistence:

একটি অ্যাপ্লিকেশনের জন্য জটিল কনফিগারেশন সেটিংস সংরক্ষণ এবং রিট্রিভ করার জন্য আপনি Object Serialization এর সুবিধা নিতে পারবেন।

আসুন একটি দৃশ্যকল্প বিবেচনা করি যেখানে আমাদের একটি WebApplication ক্লাস রয়েছে যা একটি ওয়েব অ্যাপ্লিকেশনের জন্য বিভিন্ন কনফিগারেশন সেটিংস সংরক্ষণ করে, যার মধ্যে server details, logging settings, এবং security options রয়েছে। আমরা এই কনফিগারেশন সেটিংস সংরক্ষণ এবং লোড করতে অবজেক্ট সিরিয়ালাইজেশন ব্যবহার করব।

<?php 
class ServerConfig {
    public $hostname;
    public $port;

    public function __construct($hostname, $port) {
        $this->hostname = $hostname;
        $this->port = $port;
    }
}

class LoggingConfig {
    public $logLevel;
    public $logFilePath;

    public function __construct($logLevel, $logFilePath) {
        $this->logLevel = $logLevel;
        $this->logFilePath = $logFilePath;
    }
}

class SecurityConfig {
    public $encryptionKey;
    public $csrfProtection;

    public function __construct($encryptionKey, $csrfProtection) {
        $this->encryptionKey = $encryptionKey;
        $this->csrfProtection = $csrfProtection;
    }
}

class WebApplicationConfig {
    public $appName;
    public $serverConfig;
    public $loggingConfig;
    public $securityConfig;

    public function __construct($appName, ServerConfig $serverConfig, LoggingConfig $loggingConfig, SecurityConfig $securityConfig) {
        $this->appName = $appName;
        $this->serverConfig = $serverConfig;
        $this->loggingConfig = $loggingConfig;
        $this->securityConfig = $securityConfig;
    }

    public function displayConfiguration() {
        echo "Application Name: {$this->appName}" . PHP_EOL;
        echo "Server Config:" . PHP_EOL;
        echo "\tHostname: {$this->serverConfig->hostname}" . PHP_EOL;
        echo "\tPort: {$this->serverConfig->port}" . PHP_EOL;
        echo "Logging Config:" . PHP_EOL;
        echo "\tLog Level: {$this->loggingConfig->logLevel}" . PHP_EOL;
        echo "\tLog File Path: {$this->loggingConfig->logFilePath}" . PHP_EOL;
        echo "Security Config:" . PHP_EOL;
        echo "\tEncryption Key: {$this->securityConfig->encryptionKey}" . PHP_EOL;
        echo "\tCSRF Protection: " . ($this->securityConfig->csrfProtection ? 'Enabled' : 'Disabled') . PHP_EOL;
    }

    public function saveConfiguration($filename) {
        file_put_contents($filename, serialize($this));
    }

    public function loadConfiguration($filename) {
        $data = file_get_contents($filename);
        if ($data !== false) {
            $config = unserialize($data);
            $this->appName = $config->appName;
            $this->serverConfig = $config->serverConfig;
            $this->loggingConfig = $config->loggingConfig;
            $this->securityConfig = $config->securityConfig;
        } else {
            echo "Failed to load configuration." . PHP_EOL;
        }
    }

    public function __sleep() {
        // Specify the properties to be serialized when saving the object state
        return ['appName', 'serverConfig', 'loggingConfig', 'securityConfig'];
    }

    public function __wakeup() {
        // Any necessary reinitialization when unserializing the object
    }

    public function __serialize(): array {
        // Customize the serialization process, returning an array of serialized data
        return [
            'appName' => $this->appName,
            'serverConfig' => serialize($this->serverConfig),
            'loggingConfig' => serialize($this->loggingConfig),
            'securityConfig' => serialize($this->securityConfig),
        ];
    }

    public function __unserialize(array $data): void {
        // Customize the unserialization process, restoring the object state from the serialized data
        $this->appName = $data['appName'];
        $this->serverConfig = unserialize($data['serverConfig']);
        $this->loggingConfig = unserialize($data['loggingConfig']);
        $this->securityConfig = unserialize($data['securityConfig']);
    }
}

// Example Usage
$serverConfig = new ServerConfig('localhost', 8080);
$loggingConfig = new LoggingConfig('info', 'app.log');
$securityConfig = new SecurityConfig('myEncryptionKey', true);

$initialConfig = new WebApplicationConfig('MyWebApp', $serverConfig, $loggingConfig, $securityConfig);
$initialConfig->displayConfiguration();

// Save the configuration
$initialConfig->saveConfiguration('webapp_config.txt');

// Load the configuration
$loadedConfig = new WebApplicationConfig('', new ServerConfig('', 0), new LoggingConfig('', ''), new SecurityConfig('', false));
$loadedConfig->loadConfiguration('webapp_config.txt');

// Display loaded configuration
echo "Loaded Configuration:" . PHP_EOL;
$loadedConfig->displayConfiguration();

৫. Database Storage:

  • একটি ডাটাবেসে জটিল PHP অবজেক্টগুলিকে সন্নিবেশ করার আগে সিরিয়ালাইজ করে সংরক্ষণ করা।
  • Original objects গুলিকে পুনরায় তৈরি করতে ডাটাবেস থেকে রিট্রিভ করা ডেটা আনসিরিয়ালাইজ করা।
  • নিম্নের উদাহরণটি লক্ষ্য করুন :

    প্রথমে নিম্নোক্ত SQL টি রান করুন:

    CREATE TABLE products (
        id INT AUTO_INCREMENT PRIMARY KEY,
        data TEXT NOT NULL
    );
    
    

আসুন একটি দৃশ্যকল্প বিবেচনা করি যেখানে আমাদের একটি ই-কমার্স সিস্টেমে পণ্যের প্রতিনিধিত্বকারী একটি Product class রয়েছে। আমরা একটি ডাটাবেসে product information সংরক্ষণ করতে চাই, এবং আমরা Product object কে সংরক্ষণ এবং লোড করতে অবজেক্ট সিরিয়ালাইজেশন ব্যবহার করব। ডাটাবেসের সাথে কাজ করার সময় এটি একটি সাধারণ ব্যবহারের ক্ষেত্রে, যেখানে আপনি জটিল complex objects গুলো এবং রিট্রিভ করতে চান।

<?php 
class Product {
    public $id;
    public $name;
    public $price;
    public $category;

    public function __construct($name, $price, $category) {
        $this->name = $name;
        $this->price = $price;
        $this->category = $category;
    }

    public function displayProductInfo() {
        echo "Product Information:" . PHP_EOL;
        echo "ID: {$this->id}" . PHP_EOL;
        echo "Name: {$this->name}" . PHP_EOL;
        echo "Price: {$this->price}" . PHP_EOL;
        echo "Category: {$this->category}" . PHP_EOL;
    }

    public function __sleep() {
        // Specify the properties to be serialized when saving the object state
        return ['name', 'price', 'category'];
    }

    public function __wakeup() {
        // Any necessary reinitialization when unserializing the object
        $this->id = null; // Resetting ID as it's not part of serialization
    }

    public function __serialize(): array {
        // Customize the serialization process, returning an array of serialized data
        return [
            'name' => $this->name,
            'price' => $this->price,
            'category' => $this->category,
        ];
    }

    public function __unserialize(array $data): void {
        // Customize the unserialization process, restoring the object state from the serialized data
        $this->name = $data['name'];
        $this->price = $data['price'];
        $this->category = $data['category'];
        $this->id = null; // Resetting ID as it's not part of serialization
    }
}

class DatabaseHandler {
    private $pdo;

    public function __construct(PDO $pdo) {
        $this->pdo = $pdo;
    }

    public function insertProduct(Product $product) {
        $serializedProduct = serialize($product);

        $statement = $this->pdo->prepare('INSERT INTO products (data) VALUES (:data)');
        $statement->bindParam(':data', $serializedProduct);
        $statement->execute();
    }

    public function getProductById($productId) {
        $statement = $this->pdo->prepare('SELECT data FROM products WHERE id = :id');
        $statement->bindParam(':id', $productId);
        $statement->execute();

        $result = $statement->fetch(PDO::FETCH_ASSOC);

        if ($result) {
            return unserialize($result['data']);
        }

        return null;
    }
}

// Example Usage
$pdo = new PDO('mysql:host=localhost;dbname=ecommerce', 'root', '');
$databaseHandler = new DatabaseHandler($pdo);

// Create and insert a new product
$newProduct = new Product('Laptop', 999.99, 'Electronics');
$databaseHandler->insertProduct($newProduct);

// Retrieve a product by ID
$productId = 1; // Assume this is the ID of the product just inserted
$retrievedProduct = $databaseHandler->getProductById($productId);

// Display retrieved product information
if ($retrievedProduct) {
    $retrievedProduct->displayProductInfo();
} else {
    echo "Product not found." . PHP_EOL;
}

৬. Object Copying:

  • serializing করে এবং তারপর unserializing করে objects এর deep copies তৈরি করার কাজে Object Serializing এবং Unserializing করতে পারেন।
  • এটি ঐ ধরণের পরিস্থিতিগুলির জন্য প্রয়োজন যেখানে আপনাকে একটি অবজেক্টের কপি করতে হবে এবং স্বতন্ত্রভাবে কপিটি সংশোধন করতে হবে।

নিম্নের উদাহরণটি লক্ষ্য করুন :

<?php

class Product implements Serializable {
    private $id;
    private $name;
    private $price;

    public function __construct($id, $name, $price) {
        $this->id = $id;
        $this->name = $name;
        $this->price = $price;
    }

    // Getter methods

    public function getId() {
        return $this->id;
    }

    public function getName() {
        return $this->name;
    }

    public function getPrice() {
        return $this->price;
    }

    // Setter methods (added to fix the issue)

    public function setName($name) {
        $this->name = $name;
    }

    public function setPrice($price) {
        $this->price = $price;
    }

    // Implementing Serializable interface

    public function serialize() {
        return serialize([$this->id, $this->name, $this->price]);
    }

    public function unserialize($serialized) {
        list($this->id, $this->name, $this->price) = unserialize($serialized);
    }

    // Implementing __sleep and __wakeup methods

    public function __sleep() {
        return ['id', 'name', 'price'];
    }

    public function __wakeup() {
        // Additional logic after unserialization, if needed
    }

    // Implementing __serialize and __unserialize methods

    public function __serialize() {
        return ['id' => $this->id, 'name' => $this->name, 'price' => $this->price];
    }

    public function __unserialize(array $data) {
        $this->id = $data['id'];
        $this->name = $data['name'];
        $this->price = $data['price'];
    }

    // Method for deep copying the object

    public function copy() {
        $copy = new Product($this->id, $this->name, $this->price);
        return $copy;
    }
}

// Example Usage

// Create a product
$product1 = new Product(1, 'Laptop', 999.99);

// Copy the product
$product2 = $product1->copy();

// Modify the copied product independently
$product2->setName('Desktop');
$product2->setPrice(799.99);

// Display original and copied products
echo "Original Product: {$product1->getName()} - \${$product1->getPrice()}\n";
echo "Copied Product: {$product2->getName()} - \${$product2->getPrice()}\n";

?>

৭. Data Backup and Restore:

আপনি আপনার application এর ডেটা গুলোকে নিয়মিত ব্যাকআপ নিতে Object serialization এবং unserialization এর সাহায্য নিতে পারেন।

<?php
class BackupManager
{
    private $sourceDb;
    private $backupDb;

    public function __construct($sourceDb, $backupDb)
    {
        $this->sourceDb = $sourceDb;
        $this->backupDb = $backupDb;
    }

    private function prepareAndExecute($conn, $query, $data = null)
    {
        try {
            $stmt = $conn->prepare($query);
            $stmt->execute($data);
        } catch (PDOException $e) {
            // Handle or log the exception as needed
            echo "Error: " . $e->getMessage();
        }
    }

    private function buildInsertQuery($tableName, $data)
    {
        $columns = implode(', ', array_keys($data));
        $values = ':' . implode(', :', array_keys($data));
        return "INSERT INTO $tableName ($columns) VALUES ($values)";
    }

    private function buildUpdateQuery($tableName, $primaryKey, $data)
    {
        $updateData = [];
        foreach ($data as $column => $value) {
            if ($column !== $primaryKey) {
                $updateData[] = "$column = :$column";
            }
        }
        $updateSet = implode(', ', $updateData);
        return "UPDATE $tableName SET $updateSet WHERE $primaryKey = :$primaryKey";
    }

    public function insertData($tableName, $data)
    {
        $sourceConn = $this->connectToDatabase($this->sourceDb);

        // Build the query dynamically
        $query = $this->buildInsertQuery($tableName, $data);

        // Use prepared statements for security
        $this->prepareAndExecute($sourceConn, $query, $data);
        $primaryKey = $sourceConn->lastInsertId();
        $UserId=['id'=>$primaryKey];
        $data=$UserId+$data;
        // Backup the inserted data
        $this->backupData($tableName, $primaryKey, $data);

        $sourceConn = null;
    }

    public function updateData($tableName, $primaryKey, $data)
    {
        $sourceConn = $this->connectToDatabase($this->sourceDb);

        // Build the update query dynamically
        $query = $this->buildUpdateQuery($tableName, $primaryKey, $data);

        // Use prepared statements for security
        $this->prepareAndExecute($sourceConn, $query, $data);

        // Backup the updated data
        $this->backupData($tableName,$primaryKey, $data);

        $sourceConn = null;
    }

    public function deleteData($tableName, $primaryKey, $id)
    {
        $sourceConn = $this->connectToDatabase($this->sourceDb);

        // Retrieve the data to be deleted before deletion
        $dataToDelete = $this->getDataById($tableName, $primaryKey, $id);

        // Build the delete query dynamically
        $query = "DELETE FROM $tableName WHERE $primaryKey = :id";
        $stmt = $sourceConn->prepare($query);
        $stmt->bindParam(':id', $id);
        $stmt->execute();

        // Backup the deleted data
        $this->backupData($tableName,$id, $dataToDelete);

        $sourceConn = null;
    }

    private function getDataById($tableName, $primaryKey, $id)
    {
        $sourceConn = $this->connectToDatabase($this->sourceDb);

        // Retrieve data by ID before deletion
        $query = "SELECT * FROM $tableName WHERE $primaryKey = :id";
        $stmt = $sourceConn->prepare($query);
        $stmt->bindParam(':id', $id);
        $stmt->execute();

        $dataToDelete = $stmt->fetch(PDO::FETCH_ASSOC);

        $sourceConn = null;

        return $dataToDelete;
    }

    private function backupData($tableName, $primaryKey, $data)
    {
        $backupConn = $this->connectToDatabase($this->backupDb);
        // Serialize the data
        $serializedData = serialize($data);

        // Use prepared statements for security
        $this->prepareAndExecute(
            $backupConn,
            "INSERT INTO backup_data (table_name, user_id, data) VALUES (:tableName, :user_id, :data)",
            ['tableName' => $tableName, 'user_id' => $primaryKey, 'data' => $serializedData]
        );

        $backupConn = null;
    }

    public function restoreDataByUserId($tableName, $userId)
    {
        $backupConn = $this->connectToDatabase($this->backupDb);
    
        // Ensure $userId is set and cast it to an integer
        $userId = isset($userId) ? (int)$userId : null;
    
        // Retrieve serialized data from backup_data table based on user ID
        $stmt = $backupConn->prepare("SELECT * FROM backup_data WHERE table_name = :tableName AND user_id = :userId");
        $stmt->bindParam(':tableName', $tableName);
        
        // Explicitly cast $userId to string and bind as PDO::PARAM_STR
        $userId = (string)$userId;
        $stmt->bindParam(':userId', $userId, PDO::PARAM_STR);
    
        try {
            $stmt->execute([':tableName' => $tableName, ':userId' => $userId]);
        } catch (PDOException $e) {
            // Handle or log the exception as needed
            echo "Error: " . $e->getMessage();
            $backupConn = null;
            return;
        }
    
        // Debugging
        echo "SQL Query: " . $stmt->queryString . "\n";
        echo "Bound Parameters: ";
        print_r($stmt->debugDumpParams());
    
        $backupData = $stmt->fetch(PDO::FETCH_ASSOC);
    
        if ($backupData) {
            $backupId = $backupData['id'];
            $serializedData = $backupData['data'];
    
            // Deserialize the data
            $restoredData = unserialize($serializedData);
    
            // Insert or update data back into the original table
            $primaryKey = isset($restoredData['id']) ? 'id' : null;
    
            if ($primaryKey) {
                // Build the update query dynamically
                $updateData = [];
                foreach ($restoredData as $column => $value) {
                    if ($column !== $primaryKey) {
                        $updateData[] = "$column = :$column";
                    }
                }
                $updateSet = implode(', ', $updateData);
                $updateQuery = "UPDATE $tableName SET $updateSet WHERE $primaryKey = :$primaryKey";
    
                $sourceConn = $this->connectToDatabase($this->sourceDb);
                $updateStmt = $sourceConn->prepare($updateQuery);
                $updateStmt->execute($restoredData);
            } else {
                // Build the query dynamically
                $columns = implode(', ', array_keys($restoredData));
                $values = ':' . implode(', :', array_keys($restoredData));
                $insertQuery = "INSERT INTO $tableName ($columns) VALUES ($values)";
    
                $sourceConn = $this->connectToDatabase($this->sourceDb);
                $insertStmt = $sourceConn->prepare($insertQuery);
                $insertStmt->execute($restoredData);
            }
    
            echo "Data from backup ID $backupId with user ID $userId has been restored successfully.\n";
        } else {
            echo "Backup not found for the specified user ID.\n";
        }
    
        $backupConn = null;
    }
 
    private function connectToDatabase($dbConfig)
    {
        try {
            $conn = new PDO("mysql:host={$dbConfig['servername']};dbname={$dbConfig['dbname']}", $dbConfig['username'], $dbConfig['password']);
            $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    
            return $conn;
        } catch (PDOException $e) {
            // Handle or log the exception as needed
            echo "Error: " . $e->getMessage();
            return null; // Return null to indicate connection failure
        }
    }
}

// Usage example:

$sourceDbConfig = [
    'servername' => 'localhost',
    'username' => 'root',
    'password' => '',
    'dbname' => 'main_database'
];

$backupDbConfig = [
    'servername' => 'localhost',
    'username' => 'root',
    'password' => '',
    'dbname' => 'backup_database'
];

$backupManager = new BackupManager($sourceDbConfig, $backupDbConfig);

// Example of inserting data into any table and backing it up
/* $dataToInsert = [
    'name' => 'Sorif Uddin',
    'email' => 'sorif.uddin@example.com',
    'age' => 37,
    'status' => 'active'
];
$backupManager->insertData('users', $dataToInsert); */

// Example of updating data in any table and backing it up
/* $dataToUpdate = [
    'id' => 6,
    'name' => 'Updated Name2',
    'email' => 'updated2@example.com',
    'age' => 32,
    'status' => 'active'
];
$backupManager->updateData('users', 'id', $dataToUpdate); */

// Example of deleting data from any table and backing it up
/* $deletedId = 5; // Replace with the actual ID you want to delete
$backupManager->deleteData('users', 'id', $deletedId); */



//$backupManager->restoreDataByDate('users', '2023-11-06');


/*  // Example of restoring data based on user ID
$restoredUserId = 7; // Replace with the actual user ID you want to restore
$backupManager->restoreDataByUserId('users', $restoredUserId); */

// Assuming $backupManager is an instance of your BackupManager class

আমি মাসুদ আলম, বাংলাদেশের ৩৬ তম Zend Certified Engineer । ২০০৯ সালে কম্পিউটার সাইন্স থেকে বেচেলর ডিগ্রী অর্জন করি। দীর্ঘ ১৫ বছর আমি Winux Soft, SSL Wireless, IBCS-PRIMAX, Max Group, Canadian International Development Agency (CIDA), Care Bangladesh, World Vision, Hellen Keller, Amarbebsha Ltd সহ বিভিন্ন দেশি বিদেশী কোম্পানিতে ডেটা সাইন্স, মেশিন লার্নিং, বিগ ডেটা, ওয়েব ডেভেলপমেন্ট এবং সফটওয়্যার ডেভেলপমেন্ট এর উপর বিভিন্ন লিডিং পজিশন এ চাকরি এবং প্রজেক্ট লিড করি। এছাড়াও বাংলাদেশের ১৮৫ জন জেন্ড সার্টিফাইড ইঞ্জিনিয়ার এর মধ্যে ১২০ এরও অধিক ছাত্র আমার হাতে জেন্ড সার্টিফাইড ইঞ্জিনিয়ার হয়েছেন। বর্তমানে w3programmers ট্রেনিং ইনস্টিটিউট এ PHP এর উপর Professional এবং Advance Zend Certified PHP -8.2 Engineering, Laravel Mastering Course with ReactJS, Python Beginning To Advance with Blockchain, Machine Learning and Data Science, Professional WordPress Plugin Development Beginning to Advance কোর্স করাই। আর অবসর সময়ে w3programmers.com এ ওয়েব টেকনোলজি নিয়ে লেখালেখি করি।

Leave a Reply