senenhermida.docs
  • Design Patterns
  • SOLID
  • PHP History
    • Late static binding
  • PHP Questions
  • Symfony
    • Service container
    • Event dispatcher
    • Security
    • Validation
    • Serializer
    • Http Kernel Component
    • Cache component
    • Symfony history
  • Algorithms
  • Leetcode
    • Codility
  • My CV
Powered by GitBook
On this page

PHP History

PHP history

PHP 5.0 (2004):

  • try catch: is important to handle undexpected situations (external dependencies), handle exceptions to give meaningful error messages

  • pdo (php data objects): way to access databases.

  • autoloading: eliminating the need for manual require or include statements for each class.

    • You define an "autoload" function that specifies how to locate and load class files.

    • Use spl_autoload_register() to register the autoload function.

  • namespaces: avoiding name colission, organazing the code

    • more

      • autoloading: With PSR-4, the directory structure of your project mirrors the namespace of your classes. When a class is referenced in the code, the autoloader can derive the file path from its namespace and automatically include the right file.

        • with composer:

          • composer creates autoload.php

          • the project includes: require 'vendor/autoload.php'; in its entry file

          • when. $userController = new App\Http\Controllers\UserController(); autoloader finds the class in the folder

  • traits: provide a mechanism to share methods among multiple classes as php doesn't allow multiple inheritance.

  • generatos: provide an easy way to implement iterators without needing to define a class that implements the Iterator interface. Allow us to iterate over data without creating an array in memory.

    function keyValueGenerator() {
        for ($i = 0; $i < 3; $i++) {
            yield "key$i" => "value$i";
        }
    }
    
    foreach (keyValueGenerator() as $key => $value) {
        echo "$key: $value" . PHP_EOL;  // Outputs key-value pairs
    }
  • variadic functions: function that accepts a variable number of parameters

    • more

      function sum() {
          $args = func_get_args();
          return array_sum($args);
      }
      
      echo sum(1, 2, 3, 4); // Outputs 10
      
      function sum(...$numbers) {
          return array_sum($numbers);
      }
      
      echo sum(1, 2, 3, 4, 5); // Outputs 15
  • Lambda functions and closures

    • more

      • lambda (anonymous) function

        $add = function ($a, $b) {
         return $a + $b;
        };
      • A closure is a lambda/anonymous function that may also inherit variables from the parent scope.

        • array map

          $numbers = [1, 2, 3, 4];
          $squared = array_map(function ($n) {
              return $n * $n;
          }, $numbers);
          
        • callbacks

        usort($array, function ($a, $b) {
            return $a <=> $b;
        });

PHP 7.0 (2015):

  • Throwable interface

    PHP 7 introduced the Throwable interface and error classes, allowing developers to catch both traditional exceptions and critical errors in a unified way, thereby enhancing error handling and application robustness.

  • Return Type Declarations.

  • Scalar Type Hints: For function arguments (like int, string, bool, and float).

  • Null Coalescing Operator (??)

$id = $_GET['id'] ?? null; ⇒ $id = isset($_GET['id']) ? $_GET['id'] : null;

  • Anonymous Classes.

    • more

      $pusher->setLogger(new class {
        public function log($msg) {
          print_r($msg . "\\n");
        }
      });
      

      Anonymous classes are useful in unit testing, particularly in mocking test objects and services. This helps us avoid heavy mocking libraries and frameworks by creating a simple object that provides the interface we want to mock.

  • Performance: Up to 2x faster than PHP 5.6.

PHP 7.1 - PHP 7.4

  • Typed Properties: Class properties now support type declarations.

  • Object Type: function test(object $obj) : object

  • Nullable types

  • Null Coalescing Assignment Operator (??=). $variable ??= 'default value';

  • Spread Operator in Array Expression: Allows array unpacking.

    • more

      • before

        array_merge

      • now

        $first = [1, 2, 3];
        $second = [4, 5, 6];
        
        $merged = [...$first, ...$second]; 
  • Arrow Functions: Shorter syntax for anonymous functions.

    • more

      • before

      array_map(function (User $user) { 
          return $user->id; 
      }, $users
      
      • now

      array_map(fn (User $user) => $user->id, $users)
  • Covariance contravariance updates: In PHP 7.2.0, partial contravariance was introduced by removing type restrictions on parameters in a child method (type wideding). As of PHP 7.4.0, full covariance and contravariance support was added.

    • more

      • Covariance: When it comes to return types, allows a child's method to return a more specific type

      • Contravariance: For method arguments, allows a parameter type to be less specific in a child method

      • Abstract Method Overriding(7.2): More flexible overriding of abstract methods.

      <?php
      
      abstract class A
      {
          abstract function test(string $s);
      }
      abstract class B extends A
      {
          // overridden - still maintaining contravariance for parameters and covariance for return
          abstract function test($s) : int;
      }
      • parameter type widening (7.2)

        Parameter types from overridden methods and from interface implementations may now be omitted. This is still in compliance with LSP, since parameters types are contravariant.

      interface A
      {
          public function Test(array $input);
      }
      
      class B implements A
      {
          public function Test($input){} // type omitted for $input
      }
        • you'll be able use covariant return types

          class ParentType {}
          class ChildType extends ParentType {}
          
          class A
          {
              public function covariantReturnTypes(): ParentType
              { /* … */ }
          }
          
          class B extends A
          {
              public function covariantReturnTypes(): ChildType
              { /* … */ }
          }

          and contravariant arguments.

          class A
          {
              public function contraVariantArguments(ChildType $type)
              { /* … */ }
          }
          
          class B extends A
          {
              public function contraVariantArguments(ParentType $type)
              { /* … */ }
          }
        • Consistency with the Liskov Substitution Principle (LSP):

          Allowing contravariant parameters and covariant returns maintains consistency with the LSP. An instance of a derived class should be able to replace an instance of a base class without affecting the correctness of the program.

        • Practical Benefits:

          • Flexibility: Developers can create subclasses/implementations that can handle broader scenarios (by widening parameter types) or promise more specific outcomes (by narrowing return types).

          • Clearer Contracts: By allowing more specific return types, methods can provide clearer contracts to callers, which can enhance code readability and reduce potential errors.

PHP 8.0 (2020):

  • Attributes (Annotations):

    • more

      • Offer a way to add metadata to classes, methods, properties, parameters, and functions without having to parse docblocks.

      #[Attribute]
      class ApiEndpoint {
          public function __construct(public string $route) {}
      }
      
      #[ApiEndpoint("/users")]
      class UserController {
          //...
      }
      • Features

        • Structured Metadata: Instead of relying on doc-block comments attributes provide a structured and standardized way to add metadata

        • Runtime Reflection: This metadata can be extracted and acted upon at runtime using PHP's reflection API.

        • Framework Benefits: Frameworks can greatly benefit from attributes. For example, routing, validation, ORM configurations, and dependency injection can be more intuitively handled using attributes.

      • Before: dockblocks

        /**
         * @ApiEndpoint("/users")
         */
        class UserController {
            //...
        }
        • problems:

          1. Parsing Overhead: Parsing doc-blocks introduces some overhead, as they are not natively supported for metadata extraction.

          2. Error-Prone: Since doc-block annotations aren't natively supported, typos or mistakes wouldn't be caught at compile-time. Errors would often only be identified at runtime or possibly even missed entirely.

          3. The key difference between this approach and attributes is that with doc-blocks, the annotations were part of the comments, meaning they weren't part of PHP's syntax. This required external tools to provide functionality similar to what the PHP native reflection API offers for attributes

  • JIT Compiler: Significant performance improvements.

  • Constructor Property Promotion: Simplifies class property definition and constructor assignments.

  • Union Types: Allows a parameter or return type to accept multiple types.

  • Named Arguments: Pass arguments to a function based on parameter name.

  • Nullsafe Operator (?->): null coalescing doesn't work on method calls

    • more

      • before

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

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

PHP 8.1 (2021):

  • Enumerations (Enums): A way to define a list of named values.

    • more

      enum UserStatus: string {
          case PENDING = 'pending';
          case ACTIVE = 'active';
          case SUSPENDED = 'suspended';
          case DELETED = 'deleted';
      }
      
      function welcomeUser(UserStatus $status): void {
          if ($status === UserStatus::ACTIVE) {
              echo "Welcome back, active user!";
          } elseif ($status === UserStatus::PENDING) {
              echo "Your account is still pending approval.";
          }
          // ... handle other statuses
      }
      
      // Usage:
      $status = UserStatus::ACTIVE;
      welcomeUser($status);
      • before

      class UserStatus {
          const PENDING = 'pending';
          const ACTIVE = 'active';
          const SUSPENDED = 'suspended';
          const DELETED = 'deleted';
      }
  • Read-Only Properties: Class properties that can't be changed after initialization.

  • Fibers: Allow for more elegant async programming. You probably won't use them directly in your applications, but frameworks like Amphp and ReactPHP will make extensive use of them.

  • intersection types

    function generateSlug(HasTitle&HasId $post) {
        return strtolower($post->getTitle()) . $post->getId();
    }
  • New in Initializer:

    • more

      • before

        class MyStateMachine
        {
            public function __construct(
                private ?State $state = null,
            ) {
                $this->state ??= new InitialState();
            }
        }
      • after

        class MyStateMachine
        {
            public function __construct(
                private State $state = new InitialState(),
            ) {
            }
        }
  • Array unpacking with string keys.

PHP 8.2 (2022):

  • readonly classes

    • more

      • before

        class Post
        {
            public function __construct(
                public readonly string $title, 
                public readonly Author $author,
                public readonly string $body,
                public readonly DateTime $publishedAt,
            ) {}
        }
      • after

        readonly class Post
        {
            public function __construct(
                public string $title, 
                public Author $author,
                public string $body,
                public DateTime $publishedAt,
            ) {}
        }
  • Constants in traits

  • (HasTitle&HasId)|null

PHP 8.3 (2023):

  • Typed class constants

    class Foo
    {
        const string BAR = 'baz'; 
    }
  • #[Override] attribute

    • more

      abstract class Parent
      {
          public function methodWithDefaultImplementation(): int
          {
              return 1;
          }
      }
      
      final class Child extends Parent
      {
          #[Override]
          public function methodWithDefaultImplementation(): int
          {
              return 2; // The overridden method
          }
      }

      Now, let's imagine at one point the parent method changes its method name:

      abstract class Parent
      {
          public function methodWithNewImplementation(): int
          {
              return 1;
          }
      }

      Thanks to the #[Override] attribute, PHP will be able to detect that Child::methodWithDefaultImplementation() doesn't override anything anymore, and it will throw an error.

PHP 8.4 (2023):

  • porperty hooks

    class BookViewModel
    {
        public function __construct(
            private array $authors,
        ) {}
    
        public string $credits {
            get {
                return implode(', ', array_map(
                    fn (Author $author) => $author->name, 
                    $this->authors,
                ));
            }
        }
        
        public Author $mainAuthor {
            set (Author $mainAuthor) {
                $this->authors[] = $mainAuthor;
                $this->mainAuthor = $mainAuthor;
            }
            
            get => $this->mainAuthor;
        }
    }
    interface HasAuthors
    {
        public string $credits { get; }
        public Author $mainAuthor { get; set; }
    }

new without paranthesis

$name = new ReflectionClass($objectOrClass)->getShortName();

PHP features

  • Ways to specify a string literal:

    • more

      • single quoted

      echo 'You can also have embedded newlines in
      strings this way as it is
      okay to do';
      // Outputs: Variables do not $expand $either
      echo 'Variables do not $expand $either';
      • double cuoted

      // Using curly braces to embed a complex expression within a double-quoted string
      $greeting = "Hello {$user->getFullName()}!";
      echo $greeting;  // Outputs: Hello John Doe!
      • Heredoc/Nowdoc: Heredoc and Nowdoc are both string syntaxes in PHP used for creating strings. We also don’t need to worry about escaping quote marks when using heredoc and nowdoc.

      • Heredoc

        $name = "John";
        $str = <<<EOD
        Hello, $name!
        This is a multi-line string.
        EOD;
      • Nowdoc: used to embed php code and big text withouth escaping them

        $name = "John";
        $str = <<<'EOD'
        Hello, $name!
        This is a multi-line string.
        EOD;

        Even though $name appears in the string, it won't be parsed and replaced with "John". The output will literally include .

  • PHPdoc: PHPDoc is an adaptation of Javadoc for PHP. It is an informal standard for commenting PHP code, It allows external document generators like phpDocumentor, to generate documentation of APIs and helps some IDEs to interpret variable types and other ambiguities in the loosely typed language and to provide improved code completion, type hinting and debugging.

/**
 * Get all image nodes.
 *
 * @param \\DOMNode     $node       The \\DOMDocument instance
 * @param boolean      $strict     If the document has to be valid
 *
 * @return \\DOMNode
 */
  • phpstan: PHP in its most recent versions can express a lot of things in the native typehints, but it still leaves a lot of room for PHPDocs to augment the information.

  • shorthand operators

    • ternary operator: (expr1) ? (expr2) : (expr3)

    • shorthand ternary operator (elvis operator) (if true): $displayName = $name ?: 'Guest';

    • null coalescing operator:

      $id = $_GET['id'] ?? null; ⇒ $id = isset($_GET['id']) ? $_GET['id'] : null;

    • Null Coalescing Assignment Operator (??=). $variable ??= 'default value';

  • Generics

    Feature in typed systems that allows a particular method or class to operate over various types of data without sacrificing type safety.

    A good example here are collections of various types. If we want to be sure that a collection consists of a given data type, we can either create a separate class to store each type, use various types of assertions, or just use generic types.

    In the PHP world, even without native generics support, there has been a workaround using doc-block annotations.

    /**
     * @template T
     */
    class Box {
        /** @var T */
        private $item;
    
        /**
         * @param T $item
         */
        public function __construct($item) {
            $this->item = $item;
        }
    
        /**
         * @return T
         */
        public function getItem() {
            return $this->item;
        }
    }
    
    /** @var Box<int> */
    $intBox = new Box(123);
    
    /** @var Box<string> */
    $stringBox = new Box("Hello");
  • Lazy loading: Lazy loading is a design pattern commonly used in computer programming to defer the initialization of an object or some data until the point at which it's needed.

  • Overloading php

    Overloading in PHP provides means to dynamically create properties and methods.

    • Property overloading: in PHP is a feature provided by the magic methods __get(), __set(), __isset(), and __unset(). These methods allow you to access properties of an object that aren't explicitly defined in the class

    • Method overloading, using the magic method call

      $sampleObject = new SampleClass;
      echo $sampleObject->add(12, 12) . PHP_EOL; // Outputs 24
      echo $sampleObject->add(12, 2, 6) . PHP_EOL; // Outputs 10

      Example: The same method can be used to handle different payment processors. And these processors often need a different number of inputs to work well

DTO

Used to transfer data between layer

between the web app and the database

define the structure of a response in an api

PreviousSOLIDNextLate static binding

Last updated 2 months ago

Covariant Returns and Contravariant Parameters (7.4, ):

main difference between service,provide them with additional functionality.

Late static binding
here
https://dev.to/andrewsavetchuk/the-difference-between-service-classes-and-traits-in-php-41jm#:~:text=The
https://medium.com/@prevailexcellent/actions-services-events-listeners-observers-traits-and-jobs-in-laravel-9-the-difference-6da73c24c43a
https://stackoverflow.com/questions/60771156/when-to-use-a-trait-or-a-service
https://stackoverflow.com/questions/53744359/why-should-i-use-both-traits-and-services-in-laravel
Late static binding
exceptions