Book Image

Mastering PHP 7

By : Branko Ajzele
Book Image

Mastering PHP 7

By: Branko Ajzele

Overview of this book

PHP is a server-side scripting language that is widely used for web development. With this book, you will get a deep understanding of the advanced programming concepts in PHP and how to apply it practically The book starts by unveiling the new features of PHP 7 and walks you through several important standards set by PHP Framework Interop Group (PHP-FIG). You’ll see, in detail, the working of all magic methods, and the importance of effective PHP OOP concepts, which will enable you to write effective PHP code. You will find out how to implement design patterns and resolve dependencies to make your code base more elegant and readable. You will also build web services alongside microservices architecture, interact with databases, and work around third-party packages to enrich applications. This book delves into the details of PHP performance optimization. You will learn about serverless architecture and the reactive programming paradigm that found its way in the PHP ecosystem. The book also explores the best ways of testing your code, debugging, tracing, profiling, and deploying your PHP application. By the end of the book, you will be able to create readable, reliable, and robust applications in PHP to meet modern day requirements in the software industry.
Table of Contents (24 chapters)
Title Page
Credits
About the Author
About the Reviewers
www.PacktPub.com
Customer Feedback
Preface
16
Debugging, Tracing, and Profiling

Anonymous classes


Instantiating objects from classes is a pretty straightforward action. We use the new keyword, followed by a class name and possible constructor parameters. The class name part implies the existence of a previously defined class. Though rare, there are cases where classes are only used during execution. These rare cases make it verbose to force a class definition separately when we know that the class is only being used once. To address this verbosity challenge, PHP introduced a new functionality called anonymous classes. While the concept of anonymous classes has been around for quite some time in other languages, PHP only got to it in the PHP 7 release.

The syntax of anonymous classes is pretty straightforward, which is as follows:

$obj = new class() {};
$obj2 = new class($a, $b) {
   private $a;
   private $b;
   public function __construct($a, $b) {
     $this->a = $a;
     $this->b = $b;
   }
};

We use the new keyword , followed by the class keyword, followed by optional constructor parameters, and finally the body of the class packed in curly braces. Both objects are instantiated as a class@anonymous type. The functionality of objects instantiated through anonymous classes is no different from those instantiated via named classes.

Compared to named classes, anonymous classes are pretty much equal, in that, they can pass contractor parameters, extend other classes, implement interfaces, and use traits. However, anonymous classes cannot be serialized. Trying to serialize an instance of an anonymous class, as shown in the following code snippet, throws a fatal Serialization of class@anonymous is not allowed… error.

There are few other caveats to keep in mind when using anonymous classes. Nesting an anonymous class within another class hides the private and protected methods or properties of that outer class. To circumvent the limitation, we can pass the outer class' private and protected properties into an anonymous class constructor, as follows:

interface Salary {
      public function pay();
   }

   trait Util {
      public function format(float $number) {
         return number_format($number, 2);
      }
   }

   class User {
      private $IBAN;
      protected $salary;
      public function __construct($IBAN, $salary) {
         $this->IBAN = $IBAN;
         $this->salary = $salary;
      }

      function salary() {
       return new class($this->IBAN, $this->salary) implements Salary {
         use Util;
         private $_IBAN;
         protected $_salary;

         public function __construct($IBAN, $salary) {
            $this->_IBAN = $IBAN;
            $this->_salary = $salary;
         }

        public function pay() {
           echo $this->_IBAN . ' ' . $this->format($this->_salary);
        }
     };
   } 
 }
 $user = new User('GB29NWBK60161331926819', 4500.00);
 $user->salary()->pay();

In this strip down User class example, we have a salary method that returns an anonymous class. To showcase the more robust use of anonymous classes, we make it implement the Salary interface and use the Util trait. The Salary interface forces the anonymous class to implement the pay method. Our implementation of pay method requires IBAN and salary member values from the outer class. Since an anonymous class does not allow access to private and protected members of the outer class, we pass those through anonymous class constructors. While the overall example certainly does not reflect notions of a good class design, it does showcase how to bypass the member visibility limitation.

There is also an option for an anonymous class to fetch the private and protected members of the outer class by extending the outer class itself. However, this requires the anonymous class constructor to properly instantiate the outer class; otherwise, we might end up with a warning, such as a missing argument, for User::__construct().

Even though they are namelessly defined, anonymous classes still get an internal name. Using the core PHP get_class method on an instance of an anonymous class, gets us that name, as shown in the following examples:

class User {}
class Salary {}

function gen() {
  return new class() {};
}

$obj = new class() {};
$obj2 = new class() {};
$obj3 = new class() extends User {};
$obj4 = new class() extends Salary {};
$obj5 = gen();
$obj6 = gen();

echo get_class($obj); // class@anonymous/var/www/index.php0x27fe03a
echo get_class($obj2); // class@anonymous/var/www/index.php0x27fe052
echo get_class($obj3); // class@anonymous/var/www/index.php0x27fe077
echo get_class($obj4); // class@anonymous/var/www/index.php0x27fe09e
echo get_class($obj5); // class@anonymous/var/www/index.php0x27fe04f
echo get_class($obj6); // class@anonymous/var/www/index.php0x27fe04f

for ($i=0; $i<=5; $i++) {
  echo get_class(new class() {}); // 5 x   
    class@anonymous/var/www/index.php0x27fe2d3
}

Observing these outputs, we see that the anonymous classes created in the same position (function or a loop) will yield the same internal name. Those with the same name return true for the equal (==) operator and false for the identity operator (===), an important consideration in order to avoid potential bugs.

Support for an anonymous classes opens a door to some interesting use cases, such as mocking tests and doing the inline class overrides, both of which, when used wisely, can improve code quality and readability.