Tuesday, 13 July 2021

PHP 8 Features & Anonamus classes using php

PHP 8 Execution : 

    


As of PHP 5.5, the Zend OPcache extension is available by default,

The PHP execution is a 4 stage process:

  • Compilation: The interpreter traverses the tree and translates AST nodes into low-level Zend opcodes, which are numeric identifiers determining the type of instruction performed by the Zend VM.
  • Interpretation: Opcodes are interpreted and run on the Zend VM.


PHP 8 Features :- 

1.Constructor Property Promotion
2.Validation for Abstract Trait Methods
3.Incompatible Method Signatures
4.Arrays Starting With a Negative Index
5.Union Types 2.0
6.Consistent Type Errors for Internal Functions 7.Throw Expression
8.Weak Maps
9.Trailing Comma in Parameter List
10.Allow ::class syntax on objects
11.Attributes v2
12.Named Arguments
13.Nullsafe Operator
14.Saner String to Number Comparisons
15.Saner Numeric Strings
16.Match Expression v2
17.Stricter Type Checks for Arithmetic/Bitwise Operators


1.Constructor Property Promotion

   Ex: PHP 7

     
class Point {
 public int $x;
 public int $y;
 public int $z;
  public function __construct( int $x = 0,int $y = 0,int $z = 0 ) {
         $this->x = $x;
         $this->y = $y;
         $this->z = $z;
 }
}

========After PHP 8.0 ===================

   class Point {

    public function __construct(

       public int $x = 0,
       public int $y = 0,
       public int $z = 0,    ) {
                }

}

2.Validation for Abstract Trait Methods

 A trait can also contain abstract methods. These methods simply declare the method’s signature, but the method’s implementation must be done within the class using the trait. PHP 8  should not allow different signature.   

trait T {
                    abstract public function test(int $x);  
            }
class C { 
  use T; // Allowed, but shouldn't be due to invalid type.
 public function test(string $x) {

    }
}

/Fatal error: Declaration of C::test(string $x) must be compatible with T::test(int $x)

Above code gives fattal  error in PHP8 version. It executes in php 7.4

3.Incompatible Method Signatures

The class implementing the interface must use a method signature which is compatible with LSP (Liskov Substitution Principle). Not doing so will result in a fatal error. Below code executes in PHP7.4 with an warning but its not in PHP8

  class C1 { 
        public function method(array $a) {} 
}
class C2 extends C1 {
 public function method(int $a) {}
}

4.Arrays Starting With a Negative Index

  With PHP 8, arrays starting with a negative index.

   $a = array_fill(-5, 4, true);
   print_r($a);

      PHP 8                                          

    Array
(
    [-5] => 1
    [-4] => 1
    [-3] => 1
    [-2] => 1
)
PHP 7.4 

Array
(
    [-5] => 1
    [0] => 1
    [1] => 1
    [2] => 1
)

5.Union Types 2.0
class Number {
    private int|float $number;
 
    public function setNumber(int|float $number): void {
        $this->number = $number;
    }
 
    public function getNumber(): int|float {
        return $this->number;
    }
}

6.Consistent Type Errors for Internal Functions
var_dump
(strlen(new stdClass));

In PHP 8, the code above throws the following error

Fatal error: Uncaught TypeError: strlen(): Argument #1 ($str) must be of type string, object given in

7.Throw Expression
$callable
= fn() => throw new Exception();
// $value is non-nullable.
$value = $nullableValue ?? throw new InvalidArgumentException();
// $value is truthy.
$value = $falsableValue ?: throw new InvalidArgumentException();

8.Weak Maps

9.Trailing Comma allowed in Parameter List

 function foo(string $foo, string $bar,) {

echo " Variables -  $foo - $bar ";

}

foo('foo','bar');


10.Allow ::class syntax on objects
$object
= new stdClass;
var_dump($object::class); // "stdClass"

$object
= null;
var_dump($object::class); // TypeError


We can access object class name with  ::class  in  PHP8. If the object is null then its returns Type Error.

11.Attributes v2

12.Named Arguments
    
Named arguments allow passing arguments to a function based on the parameter name, rather than the parameter position.

 
array_fill(start_index: 0, num: 100, value: 50);

Named arguments are order-independent. This means that we are not forced to pass arguments to a function in the same order as the function signature:

array_fill
(value: 50, num: 100, start_index: 0);

Ex:

function calculateTotal($price, $quantity, $discount = 0) {
    $total = $price * $quantity * (1 - $discount);
    return $total;
}

// Mix positional and named arguments
$subtotal = calculateTotal(10, quantity: 5, discount: 0.2);


13.Nullsafe Operator

    
PHP 7


$country =  null;

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

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

PHP 8 :

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


14.Saner String to Number Comparisons

  Comparison | Before     | After
   --------------------------------------
       0 == "0"        | true      | true
      0 == "0.0"      | true      | true
    0 == "foo"   | true   | false
   0 == ""         | true   | false
 42 == " 42"         | true      | true
42 == "42foo" | true  | false


16.Match Expression v2

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

The new match is similar to switch and has the following features:

  • Match is an expression, meaning its result can be stored in a variable or returned.
  • Match branches only support single-line expressions and do not need a break; statement.
  • Match does strict comparisons.

17.Stricter Type Checks for Arithmetic/Bitwise Operators


18.New String Functions Added

PHP 8 brings several new functions to the language:


Anonymous classes 


In PHP7, 
Anonymous classes are those classes that don’t have any name. These anonymous classes are defined using the new class. It can replace full-class definition. When simple, one-off objects are created then anonymous classes are useful. They are internally generated names so we don’t have to give names to these classes. Objects created by same anonymous class are instances of that class

Below three examples describe anonymous class with very simple and basic but quite understandable example


<?php
// First way - anonymous class assigned directly to variable
$ano_class_obj = new class{
    public 
$prop1 'hello';
    public 
$prop2 754;
    const 
SETT 'some config';

    public function 
getValue()
    {
        
// do some operation
        
return 'some returned value';
    }

    public function 
getValueWithArgu($str)
    {
        
// do some operation
        
return 'returned value is '.$str;
    }
};

echo 
"\n";

var_dump($ano_class_obj);
echo 
"\n";

echo 
$ano_class_obj->prop1;
echo 
"\n";

echo 
$ano_class_obj->prop2;
echo 
"\n";

echo 
$ano_class_obj::SETT;
echo 
"\n";

echo 
$ano_class_obj->getValue();
echo 
"\n";

echo 
$ano_class_obj->getValueWithArgu('OOP');
echo 
"\n";

echo 
"\n";

// Second way - anonymous class assigned to variable via defined function
$ano_class_obj_with_func ano_func();

function 
ano_func()
{
    return new class {
        public 
$prop1 'hello';
        public 
$prop2 754;
        const 
SETT 'some config';

        public function 
getValue()
        {
            
// do some operation
            
return 'some returned value';
        }

        public function 
getValueWithArgu($str)
        {
            
// do some operation
            
return 'returned value is '.$str;
        }
    };
}

echo 
"\n";

var_dump($ano_class_obj_with_func);
echo 
"\n";

echo 
$ano_class_obj_with_func->prop1;
echo 
"\n";

echo 
$ano_class_obj_with_func->prop2;
echo 
"\n";

echo 
$ano_class_obj_with_func::SETT;
echo 
"\n";

echo 
$ano_class_obj_with_func->getValue();
echo 
"\n";

echo 
$ano_class_obj_with_func->getValueWithArgu('OOP');
echo 
"\n";

echo 
"\n";

// Third way - passing argument to anonymous class via constructors
$arg 1// we got it by some operation
$config = [2false]; // we got it by some operation
$ano_class_obj_with_arg ano_func_with_arg($arg$config);

function 
ano_func_with_arg($arg$config)
{
    return new class(
$arg$config) {
        public 
$prop1 'hello';
        public 
$prop2 754;
        public 
$prop3$config;
        const 
SETT 'some config';

        public function 
__construct($arg$config)
        {
            
$this->prop3 $arg;
            
$this->config =$config;
        }

        public function 
getValue()
        {
            
// do some operation
            
return 'some returned value';
        }

        public function 
getValueWithArgu($str)
        {
            
// do some operation
            
return 'returned value is '.$str;
        }
    };
}

echo 
"\n";

var_dump($ano_class_obj_with_arg);
echo 
"\n";

echo 
$ano_class_obj_with_arg->prop1;
echo 
"\n";

echo 
$ano_class_obj_with_arg->prop2;
echo 
"\n";

echo 
$ano_class_obj_with_arg::SETT;
echo 
"\n";

echo 
$ano_class_obj_with_arg->getValue();
echo 
"\n";

echo 
$ano_class_obj_with_arg->getValueWithArgu('OOP');
echo 
"\n";

echo 
"\n";

No comments:

Post a Comment