নতুন কি থাকছে পিএইচপি ৮ এ?
PHP

নতুন কি থাকছে পিএইচপি ৮ এ?

Stack Learner
Stack Learner

পিএইচপি বেঁচে আছে না মরে গেছে, বাঁচবে না মরবে এই নিয়ে যখন ডেভেলপাররা দুই ভাগে বিভক্ত হয়ে সোশ্যাল মিডিয়ায় খুনাখুনির পর্যায়ে যায় যায় ভাব, ঠিক সেই মুহুর্তেই শোনা গেলো পিএইচপি ৮ আসছে। শুধু আসছে না নতুন রূপে নতুন সাজে JIT Compiler সাথে নিয়ে আসছে। এই খবর শোনা মাত্রই পিএইচপি কমিউনিটি আবার চাঙ্গা হয়ে উঠলো। কারণ পিএইচপি এর দাবী এবার সে আগের থেকে দুই গুণ বেশি পার্ফরমেন্স দিবে। সেই থেকে অপেক্ষার শুরু, অপেক্ষা যেন শেষই হচ্ছিল না। অবশেষে ২৬ নভেম্বর ২০২০ তারিখে পিএইচপি অফিশিয়ালি রিলিজ করে দিলো version 8। আজকের এই আর্টিকেলে আমরা এইটাই জানার চেষ্টা করবো পিএইচপি ৮ এ নতুন কি কি বিষয় যুক্ত হয়েছে। কোনটা ভালো, কোনটা খারাপ সেই বিষয় নিয়ে আজকে কোনো আলোচনায় যাবো না। সেগুলো নিয়ে আলোচনা করার জন্য Stack Learner এর চ্যানেলে আজকে থেকেই শুরু হতে যাচ্ছে PHP: All You Need to Know প্রিমিয়াম কোর্স।

মুখ্য পরিবর্তন

Just in Time Compilation - JIT

আমার কাছে পিএইচপি ৮ এর সব থেকে ইন্টারেস্টিং এবং প্রধান পরিবর্তনই হচ্ছে JIT কম্পাইলার। JIT কম্পাইলারের কাজ হচ্ছে যখন যেই কোডটুকু দরকার তখন সেই কোডটা কম্পাইল করে এক্সিকিউট করা। অনেকটা ক্যাশ করে রাখার মতো। আগে পিএইচপি ছিল ইন্টারপ্রেটেড। ইন্টারপ্রেটারের থেকে JIT কম্পাইলার অনেক বেশি ফাস্ট। তাই এটা ভেবে নেওয়া ভুল কিছু হবে না যে এখন পিএইচপি আগের থেকে অনেক বেশি ফাস্ট কাজ করবে। পিএইচপি ৮ আমাদেরকে দুইটা ভিন্ন ভিন্ন JIT ইঞ্জিনের সাথে পরিচয় করিয়ে দিচ্ছে। একটা হচ্ছে Tracing JIT আর একটা হচ্ছে Function JIT। পিএইচপি এর অফিশিয়াল ওয়েবসাইট দাবী করছে সিনথেটিক বেঞ্চমার্কিং এ এটা ৩ গুণ বেশি পার্ফরমেন্স দিচ্ছে আর লং রানিং অ্যাপলিকেশনের ক্ষেত্রে দেড় থেকে দুই গুণ পার্ফরমেন্স বেশি দিচ্ছে।

এবার কিছু নতুন ফিচারের দিকে তাকানো যাক।

# Stack Learner Nano Camp Registration is Going On
# Don't Be Late, Confirm Your Seat
# As Early As Possible
Starts From 15 Dec 2020, Registration Going On. Learn More

Named Arguments

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

/* PHP 8 Named Arguments */
function foo(string $a, int $b, ?float $c=1.0) 
{
  /* function body */
}

foo(
	b: 100,
  a: 'named arguments'
);

Attibutes

আমরা সাধারণত একে Annotation নামেই চিনি। প্রতিটা অবজেক্ট অরিয়েন্টেড প্রোগ্রামিং ল্যাংগুয়েজেই এই Annotation কে দেখা যায় ক্লাসের কাছে কিছু এক্সট্রা ইনফরমেশন বা মেটা ডেটা পাস করতে। পিএইচপি ৭ এ PHPDoc Annotation ব্যবহার করতে হতো, এটা দেখতে অনেকটা কমেন্টের মতো।

/* PHP 7 Annotation Example */

/**
* @Route("/api/posts/{id}", methods={"GET", "HEAD"})
*/
class User {}

পিএইচপি ৮ এ Annotation যুক্ত করার জন্য আমরা নতুন সিনট্যাক্স পেয়েছি।

/* PHP 8 Annotation Example */

#[Route("/api/posts/{id}", methods: ["GET", "HEAD"])]
class User {}

Constructor Property Promotion

পিএইচপি ৭ এ ক্লাস প্রোপার্টি এর ভ্যালু যুক্ত করার জন্য আমাদের অনেক বেশি বয়লারপ্লেট কোড লিখতে হতো। প্রথমে প্রোপার্টি ডিক্লেয়ার করতে হতো, কন্সট্রাক্টরের প্যারামিটারে প্রোপার্টি গুলো ডিফাইন করতে হতো, তারপরে সে গুলোকে ক্লাস প্রোপার্টির সাথে অ্যাসাইন করতে হতো।

/* PHP 7 Constructor */

class Point {
  public float $x;
  public float $y;
  public float $z;

  public function __construct(
    float $x = 0.0,
    float $y = 0.0,
    float $z = 0.0,
  ) {
    $this->x = $x;
    $this->y = $y;
    $this->z = $z;
  }
}

পিএইচপি ৮ এ এখন আর এত বয়লারপ্লেট কোড লেখার দরকার নেই। অল্প কোড লিখবো কিন্তু কাজ বেশি হবে।

/* PHP 8 Constructor */

class Point {
  public function __construct(
    public float $x = 0.0,
    public float $y = 0.0,
    public float $z = 0.0,
  ) {}
}

Union Types

পিএইচপি ৮ এর অন্যতম একটা ভালো ফিচার হচ্ছে Union Types। আমরা এখন একটা ভ্যারিয়েবল ডিক্লেয়ার করার সময়েই বলে দিতে পারবো যে এই ভ্যারিয়েবল সম্ভাব্য কোন কোন টাইপের ডেটা ধারণ করতে পারে। যদি আমাদের বলে দেওয়া টাইপের বাইরে কোনো ডেটা প্রোভাইড করা হয় তাহলেই ইরোর থ্রো করবে।

/* PHP 7 Union Types */

class Number {
  /** @var int|float */
  private $number;

  /**
   * @param float|int $number
   */
  public function __construct($number) {
    $this->number = $number;
  }
}

new Number('NaN'); // Ok
/* PHP 7 Union Types */

class Number {
  public function __construct(
    private int|float $number
  ) {}
}

new Number('NaN'); // TypeError

Match Expression

এটা পিএইচপি ৮ এর ব্রান্ড নিউ একটা এক্সপ্রেশন। অনেকটা switch স্টেটমেন্টের মতো কাজ করে এই স্টেটমেন্ট। তবে এটাকে আমি স্টেটমেন্ট বলতে পারছি না কারণ এটা এক্সপ্রেশন ম্যাচ করে একটা ভ্যালু রিটার্ন করে। আর আমরা জানি স্টেটমেন্ট কোনো ভ্যালু রিটার্ন করতে পারে না। যেহেতু এটা একটা এক্সপ্রেশন আমরা চাইলেই এর থেকে প্রাপ্ত রেসাল্ট একটা ভ্যারিয়েবলের মধ্যে স্টোর করে রাখতে পারি। switch স্টেটমেন্টের মতো এর কোনো break স্টেটমেন্টের দরকার পরে না। তবে এখানে আপনি মাল্টিপল স্টেটমেন্ট বা এক্সপ্রেশন ব্যবহার করতে পারবেন না। আপনাকে সিঙ্গেল এক্সপ্রেশন নিয়েই কাজ করতে হবে।

/* PHP 7 Switch Statement */

switch (8.0) {
  case '8.0':
    $result = "Oh no!";
    break;
  case 8.0:
    $result = "This is what I expected";
    break;
}
echo $result;
//> Oh no!
/* PHP 8 Match Expression */

echo match (8.0) {
  '8.0' => "Oh no!",
  8.0 => "This is what I expected",
};
//> This is what I expected

বিশেষ দ্রষ্টব্যঃ ম্যাচ এক্সপ্রেশন স্ট্রিক্ট কম্প্যারিসন করে থাকে


Nullsafe Operator

Nullsafe অপারেটর যুক্ত করা হচ্ছে সময়োপযোগী একটা সিদ্ধান্ত। এই অপারেটর না থাকার কারণে আমাদের কন্ডিশন চেক করে করে সেফ থাকতে হয়। অনেকটা নিচের কোডের মতো -

/* PHP 7 Null Check */

$country =  null;

if ($session !== null) {
  $user = $session->user;

  if ($user !== null) {
    $address = $user->getAddress();
  
    if ($address !== null) {
      $country = $address->country;
    }
  }
}

Nullsafe অপারেটর আসার ফলে এই এত গুলো লাইনের কোড মাত্র এক লাইনে রিপ্লেস করা পসিবল, অনেকটা নিচের মতো -

/* PHP 8 Nullsafe Operator */

$country = $session?->user?->getAddress()?->country;

?  এই কোশ্চেন মার্ক চিহ্নটাই হচ্ছে Nullsafe অপারেটর।


Saner String to Number Comparisons

পিএইচপি ৮ এ স্ট্রিং যদি নিউমেরিক হয় শুধুমাত্র সেই ক্ষেত্রেই নাম্বার কম্পেরিসন হবে। বাকি সব ক্ষেত্রে নাম্বারকে স্ট্রিং এ কনভার্ট করে স্ট্রিং কম্পেরিসন হবে।

/* PHP 7 */
0 == 'foobar' // true

/* PHP 8 */
0 == 'foobar' // false

Consistent Type Errors for Internal Functions

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

/* PHP 7 shows warning */
strlen([]); // Warning: strlen() expects parameter 1 to be string, array given

array_chunk([], -1); // Warning: array_chunk(): Size parameter expected to be greater than 0

/* PHP 8 throws error */
strlen([]); // TypeError: strlen(): Argument #1 ($str) must be of type string, array given

array_chunk([], -1); // ValueError: array_chunk(): Argument #2 ($length) must be greater than 0

Type System and Error Handling Improvements

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

  • পিএইচপি ৮ এর পূর্বে অ্যারিথমেটিক এবং বিটওয়াইস অপারেটর গুলো অ্যারে, অবজেক্ট এবং রিসোর্সেস এর ওপরেও কাজ করতো। কিন্তু বর্তমানে এটা আর সম্ভব না।
  • পিএইচপি ৮ এ Trait এ abstract মেথড ভ্যালিডেশন যুক্ত করা হয়েছে। এখন Trait এ কোনো abstract মেথড ডিফাইন করলে ক্লাসে প্রোপার সিগনেচার ব্যবহার করেই ইমপ্লিমেন্ট করতে হবে।
  • ম্যাজিক মেথডের ক্ষেত্রেও এখন প্রোপার সিগনেচার ফলো করা বাধ্যতামূলক, নাহলে কম্পাইলার ইরোর থ্রো করবে।

পিএইচপি ৮ এর পূর্বে অনেক রকম ইরোর ছিল যা সিম্পলি ওয়ার্নিং থ্রো করতো। এখন সেগুলো প্রোপার ইরোর থ্রো করবে। যেমন -

  • Undefined variable: Error exception instead of notice
  • Undefined array index: warning instead of notice
  • Division by zero: DivisionByZeroError exception instead of warning
  • Attempt to increment/decrement property '%s' of non-object: Error exception instead of warning
  • Attempt to modify property '%s' of non-object: Errorexception instead of warning
  • Attempt to assign property '%s' of non-object: Error exception instead of warning
  • Creating default object from empty value: Error exception instead of warning
  • Trying to get property '%s' of non-object: warning instead of notice
  • Undefined property: %s::$%s: warning instead of notice
  • Cannot add element to the array as the next element is already occupied: Error exception instead of warning
  • Cannot unset offset in a non-array variable: Error exception instead of warning
  • Cannot use a scalar value as an array: Error exception instead of warning
  • Only arrays and Traversables can be unpacked: TypeError exception instead of warning
  • Invalid argument supplied for foreach(): TypeError exception instead of warning
  • Illegal offset type: TypeError exception instead of warning
  • Illegal offset type in isset or empty: TypeError exception instead of warning
  • Illegal offset type in unset: TypeError exception instead of warning
  • Array to string conversion: warning instead of notice
  • Resource ID#%d used as offset, casting to integer (%d): warning instead of notice
  • String offset cast occurred: warning instead of notice
  • Uninitialized string offset: %d: warning instead of notice
  • Cannot assign an empty string to a string offset: Errorexception instead of warning
  • Supplied resource is not a valid stream resource: TypeErrorexception instead of warning
  • ইনহেরিটেন্সের ক্ষেত্রে যদি কোনো মেথড ইনকম্পিটিবল হয় সেই ক্ষেত্রে Fatal ইরোর শো করবে।
  • @ অপারেটর এখন Fatal ইরোরকে আটকাবে না।
  • পিএইচপি ৮ এর পূর্বে প্রাইভেট মেথড চেক পাবলিক বা প্রোটেক্টেডের মতোই হতো যার কোনো অর্থ ছিল না। কারণ প্রাইভেট মেথডের এক্সেস চাইল্ড ক্লাসের পাওয়া সম্ভব না। পিএইচপি ৮ এ নতুন করে এই চেক বসানো হয়েছে।
  • পিএইচপি ৮ এ mixed নামের নতুন একটা টাইপ যুক্ত করা হয়েছে। mixed মানে এর মধ্যে যে কোনো টাইপের ডেটাই থাকতে পারে।
  • পিএইচপি ৮ এ একটা ফাংশন থেকে static টাইপ রিটার্ন করা যাবে।
# Join Stack Learner Life Changing Program
# Do Some Real Project with Professionals
Starts From 15 Dec 2020, Registration Going On. Learn More

New Classes, Interfaces & Functions

Weak Map

Weak map একধরনের ডেটা স্ট্রাকচার যা অবজেক্টের রেফারেন্স ধরে রাখে এবং ওই অবজেক্টকে গার্বেজ কালেক্টরের হাত থেকে রক্ষা করে।

class Foo 
{
    private WeakMap $cache;
 
    public function getSomethingWithCaching(object $obj): object
    {
        return $this->cache[$obj]
           ??= $this->computeSomethingExpensive($obj);
    }
}

Stringable Interface

এটা পিএইচপি ৮ এর নতুন একটি ইন্টারফেস। যে কোনো কিছু যা `__toString()` মেথডকে ইমপ্লিমেন্ট করে সেটাই বিহাইন্ড দ্যা সিন Stringable ইন্টারফেস ব্যবহার করে।

class Foo
{
    public function __toString(): string
    {
        return 'foo';
    }
}

function bar(string|Stringable $stringable) {}

bar(new Foo()); // Stringable
bar('abc');

New str_contains(), str_starts_with() & str_ends_with()

// str_contains() check if the substring contains in the given string
str_contains('Stack Learner Nano Camp is Running', 'Nano Camp') // true

str_starts_with('Stack Learner', 'Stack'); // true
str_ends_with('Stack Learner', 'Learner'); // true  

New fdiv() Function

যখন 0 দিয়ে কোনো কিছু ভাগ করা হয় তখন ইরোর থ্রো করার বদলে এই ফাংশনটা INF, -INF অথবা NAN রিটার্ন করবে।

New get_debug_type() Function

এই ফাংশনটা অনেকটা gettype() ফাংশনের মতো, তবে get_debug_type() ফাংশনটা অনেক বেশি ইনফরমেশন রিটার্ন করে।

New get_resource_id() Function

পিএইচপি তে রিসোর্স একটা স্পেশিয়াল ভ্যারিয়েবল, যেমন MySQL Connection অথবা ফাইল হ্যান্ডেল। পিএইচপি ৭ এ রিসোর্সের আইডি পাওয়ার জন্য টাইপ কাস্টিং এর প্রয়োজন হতো। এখন সেই আইডি পাওয়ার কাজটাই করবে get_resource_id() ফাংশন।

$resourceId = (int) $resource; // PHP 7
$resourceId = get_resource_id($resource); // PHP 8

New token_get_all() Function

এই ফাংশনটা অবজেক্টের জন্য তৈরি করা একটা স্পেশিয়াল ফাংশন যার কাজ হচ্ছে অবজেক্টের ভ্যালু গুলোকে একটা অ্যারেতে রিটার্ন করা। এই ফাংশনটা শুধুমাত্র অবজেক্টের জন্যই নতুন করে অপাটিমাইজড করে ইমপ্লিমেন্ট করা হয়েছে।

Other Syntax Tweaks & Improvements

Allow Trailing Comma in Parameters

এতদিন ফাংশন ইনভোকিং বা কলিং এর সময়ে আমরা ট্রেইলিং কমা ব্যবহার করতে পারতাম। পিএইচপি ৮ থেকে আমরা ফাংশন ডিফাইন করার সময়ে প্যারামিটারেও ট্রেইলিং কমা ব্যবহার করতে পারবো।

public function(
    string $parameterA,
    int $parameterB,
    Foo $objectfoo, // trailing comma
) {}

Non Capaturing Catches

পিএইচপি ৮ এর পূর্বে যখন আমরা ইরোর হ্যান্ডেল করতাম তখন প্রয়োজন না হলেও ইরোরকে একটা ভ্যারিয়েবলের মধ্যে স্টোর করতে হতো। কিন্তু এখন আর সেটা করার দরকার নেই।

/* PHP 7 */
try {
  // DO Something
} catch (Exception $e) {
  Log::error("Error");
}

/* PHP 8 */
try {
  // Do Something
} catch {
  Log::error("Error");
}

Now Throw is An Expression

$triggerError = fn () => throw new MyError();

$foo = $bar['offset'] ?? throw new OffsetDoesNotExist('offset');

Allowing ::class on Objects

get_class() ফাংশনের পরিবর্তে আমরা এখন সরাসরি অবজেক্টের সাথে ::class প্রোপার্টি ব্যবহার করতে পারবো এবং দুইটাই একই রেসাল্ট দিবে।

$foo = new Foo();

var_dump($foo::class);
Starts From 15 Dec 2020, Registration Going On. Learn More
Starts From 15 Dec 2020, Registration Going On. Learn More

এগুলো ছাড়াও আরও ছোটোখাটো অসংখ্য পরিবর্তন পিএইচপি ৮ নিয়ে এসেছে। আমার কাছে মনে হয়েছে এগুলো খুবই ইন্টারেস্টিং এবং সবার জানা দরকার তাই এগুলোই শেয়ার করলাম। যদি আপনাদের পিএইচপি ৮ এর সম্পূর্ণ আপডেট সম্পর্কে জানতে ইচ্ছে করে তাহলে নিচের লিংকে ভিসিট করে আপনি আপনার মনের ইচ্ছে পূরণ করে ফেলতে পারবেন। এত লম্বা সময় নিয়ে আর্টিকেলটা পড়ার জন্য আপনাদের সবাইকে ধন্যবাদ।

Breaking Changes: https://github.com/php/php-src/blob/PHP-8.0/UPGRADING

Official Change Docs: https://www.php.net/releases/8.0/en.php