Tìm kiếm bài viết

Sự phát triển của PHP từ 5.6 đến 8.0

01.08.2020

5.0/5 (1 Reviews)

Cùng nhau xem qua về sự phát triển và những thay đổi của các phiên bản php từ php5.6 đến php8.0 mới nhất. Có nhiều thứ được bỏ đi, tối ưu, và thêm vào

    Một đánh giá cô đọng về các thay đổi trong PHP v7.x trong vòng dưới 15 phút.

    Khi phiên bản PHP 7.3 được phát hành, tôi quyết định xem xét chi tiết về phát triển PHP: điều gì đang được phát triển và hướng nào để hiểu rõ hơn tiềm năng mới và tối ưu hóa của ngôn ngữ lập trình phổ biến rộng rãi này.

    Sau khi tìm kiếm một danh sách các tính năng cô đọng mà PHP đã triển khai trong quá trình phát triển PHP v7.x, tôi đã quyết định tự mình biên dịch danh sách này - một cách bắt kịp công nghệ mà tôi tin rằng ai đó cũng có thể thấy nó hữu ích.

    Chúng ta sẽ bắt đầu với PHP 5.6 như một đường cơ sở và sẽ xem xét những gì đã được thêm vào, thay đổi. Tôi cũng đã thêm các liên kết đến tài liệu chính thức cho từng điều được đề cập, vì vậy nếu bạn quan tâm đến việc đọc sâu hơn - hãy tự nhiên.

    PHP 7.0

    Một anonymous class có thể được sử dụng trên một class được đặt tên:

    • Khi class không cần phải được ghi lại.
    • Khi class chỉ được sử dụng một lần trong khi thực thi.
    new class($i) {
        public function __construct($i) {
            $this->i = $i;
        }
    }
    

     

    Hàm chia số nguyên -- cách an toàn để chia (thậm chí cho 0). Nó trả về phép chia số nguyên của toán hạng thứ nhất cho toán hạng thứ hai. Nếu số chia (toán hạng thứ hai) bằng 0, nó sẽ ném E_WARNING và trả về FALSE.

    intdiv(int $numerator, int $divisor)
    

     

    -- là ??

    $x = NULL;
    $y = NULL;
    $z = 3;
    var_dump($x ?? $y ?? $z); // int(3)
     
    $x = ["c" => "meaningful_value"];
    var_dump($x["a"] ?? $x["b"] ?? $x["c"]); // string(16) "meaningful_value"
    

     

     

    Được sử dụng để tối ưu hóa và đơn giản hóa các phép so sánh.

    // Before
    function order_func($a, $b) {
        return ($a < $b) ? -1 : (($a > $b) ? 1 : 0);
    }
    // Using <=> operator
    function order_func($a, $b) {
        return $a <=> $b;
    }
    

     

     

    Đây chỉ là bước đầu để đạt được ngôn ngữ lập trình mạnh mẽ hơn trong PHP - v0.5.

    function add(float $a, float $b): float {
        return $a + $b;
    }
     
    add(1, 2); // float(3)
    

     

     

    Đã thêm khả năng trả về các type ngoài scalar - các class bao gồm cả thừa kế. Vẫn bằng cách nào đó hoàn toàn bỏ lỡ khả năng làm cho nó tùy chọn (được giới thiệu trong v7.1 )

    interface A {
        static function make(): A;
    }
    class B implements A {
        static function make(): A {
            return new B();
        }
    }
    

     

     

    // Explicit use syntax:
     
    use FooLibrary\Bar\Baz\ClassA;
    use FooLibrary\Bar\Baz\ClassB;
    use FooLibrary\Bar\Baz\ClassC;
    use FooLibrary\Bar\Baz\ClassD as Fizbo;
    // Grouped use syntax:
     
    use FooLibrary\Bar\Baz\{ ClassA, ClassB, ClassC, ClassD as Fizbo };
    

     

    Cú pháp mới sau đây được cho phép trong phần thân của các hàm generator:

    yield from <expr>
    

     

    Cải thiện hiệu suất

    PHP7 nhanh gấp đôi so với PHP5.6

     

    Sử dụng bộ nhớ giảm đáng kể

    Như bạn có thể thấy từ các biểu đồ, PHP 7.0 là một cải tiến lớn về hiệu suất và việc sử dụng bộ nhớ. Đối với trang có các truy vấn cơ sở dữ liệu, phiên bản 7.0.0 nhanh hơn 3 lần so với 5.6 với opcache được bật và nhanh hơn 2,7 lần mà không cần opcache! Về mặt sử dụng bộ nhớ, sự khác biệt cũng rất đáng kể!

     

     

    Tái cấu trúc các exception class để có một naming scheme không trực quan và sẽ dẫn đến ít nhầm lẫn hơn, đặc biệt là đối với người dùng mới hơn.

    ErrorsException bây giờ được implement Throwable

    Đây là hệ thống cấp bậc của Throwable

    interface Throwable
      |- Error implements Throwable
          |- ArithmeticError extends Error
              |- DivisionByZeroError extends ArithmeticError
          |- AssertionError extends Error
          |- ParseError extends Error
          |- TypeError extends Error
              |- ArgumentCountError extends TypeError
      |- Exception implements Throwable
          |- ClosedGeneratorException extends Exception
          |- DOMException extends Exception
          |- ErrorException extends Exception
          |- IntlException extends Exception
          |- LogicException extends Exception
              |- BadFunctionCallException extends LogicException
                  |- BadMethodCallException extends BadFunctionCallException
              |- DomainException extends LogicException
              |- InvalidArgumentException extends LogicException
              |- LengthException extends LogicException
              |- OutOfRangeException extends LogicException
          |- PharException extends Exception
          |- ReflectionException extends Exception
          |- RuntimeException extends Exception
              |- OutOfBoundsException extends RuntimeException
              |- OverflowException extends RuntimeException
              |- PDOException extends RuntimeException
              |- RangeException extends RuntimeException
              |- UnderflowException extends RuntimeException
              |- UnexpectedValueException extends RuntimeException
    

    Chú ý:bạn chỉ có thể implement Throwable thông qua ErrorException.

     

    — “\u{xxxxx}”

    echo "\u{202E}Reversed text"; // outputs ‮Reversed text
    echo "mañana"; // "ma\u{00F1}ana"
    echo "mañana"; // "man\u{0303}ana" "n" with combining ~ character (U+0303)
    

     

    Với những từ globally reserved nay đã trở thành semi-reserved:

    callable  class  trait  extends  implements  static  abstract  final  public  protected  private  const
    enddeclare  endfor  endforeach  endif  endwhile  and  global  goto  instanceof  insteadof  interface
    namespace  new  or  xor  try  use  var  exit  list  clone  include  include_once  throw  array
    print  echo  require  require_once  return  else  elseif  default  break  continue  switch  yield
    function  if  endswitch  finally  for  foreach  declare  case  do  while  as  catch  die  self parent
    

     

     

     

    PHP 7.1

     

    function answer(): ?int  {
        return null; //ok
    }
    
    function answer(): ?int  {
        return 42; // ok
    }
    
    function answer(): ?int {
        return new stdclass(); // error
    }
    function say(?string $msg) {
        if ($msg) {
            echo $msg;
        }
    }
    
    say('hello'); // ok -- prints hello
    say(null); // ok -- does not print
    say(); // error -- missing parameter
    say(new stdclass); //error -- bad type
    

     

     

    function should_return_nothing(): void {
        return 1; // Fatal error: A void function must not return a value
    }
    

    Không giống như các kiểu trả về khác được thi hành khi hàm được gọi, loại này được kiểm tra tại thời gian biên dịch, điều đó có nghĩa là một lỗi được tạo ra mà không cần gọi hàm.

    Một hàm có kiểu trả về là void hoặc hàm void, có thể trả về ngầm hoặc có câu lệnh return mà không có giá trị:

    function lacks_return(): void {
        // valid
    }
    

     

     

    Thông thường, một hàm chấp nhận hoặc trả về một array hoặc một object implementing Traversable sẽ được sử dụng với foreach. Tuy nhiên, vì mảng là kiểu nguyên thủy và Traversable là một interface, hiện tại không có cách nào để sử dụng khai báo kiểu trên tham số hoặc kiểu trả về để chỉ ra rằng giá trị có thể lặp lại được.

    function foo(iterable $iterable) {
        foreach ($iterable as $value) {
            // ...
        }
    }
    

    iterable cũng có thể được sử dụng như một kiểu trả về để chỉ ra một hàm sẽ trả về một giá trị lặp. Nếu giá trị được trả về không phải là một mảng hoặc instance của Traversable, TypeError sẽ được throw.

    function bar(): iterable {
        return [1, 2, 3];
    }
    

    Các tham số được khai báo với iterable có thể sử dụng null hoặc một mảng làm giá trị mặc định.

    function foo(iterable $iterable = []) {
        // ...
    }
    

     

     

    class Closure {
        ...
        public static function fromCallable(callable $callable) : Closure {...}
        ...
    }
    

     

     

    $array = [1, 2, 3];
    // Assigns to $a, $b and $c the values of their respective array elements in $array with keys numbered from zero
    [$a, $b, $c] = $array;
     
    // Assigns to $a, $b and $c the values of the array elements in $array with the keys "a", "b" and "c", respectively
    ["a" => $a, "b" => $b, "c" => $c] = $array;
    

    Cú pháp dấu ngoặc vuông cho danh list()

    $powersOfTwo = [1 => 2, 2 => 4, 3 => 8];
    list(1 => $oneBit, 2 => $twoBit, 3 => $threeBit) = $powersOfTwo;
    

     

     

    class Token {
    	// Constants default to public
    	const PUBLIC_CONST = 0;
     
            // Constants then also can have a defined visibility
            private const PRIVATE_CONST = 0;
            protected const PROTECTED_CONST = 0;
            public const PUBLIC_CONST_TWO = 0;
     
            //Constants can only have one visibility declaration list
            private const FOO = 1, BAR = 2;
    }
    

     

    try {
       // Some code...
    } catch (ExceptionType1 | ExceptionType2 $e) {
       // Code to handle the exception
    } catch (\Exception $e) {
       // ...
    }
    

    PHP 7.2

     

    <?php
     
    class ArrayClass {
      public function foo(array $foo) { /* ... */ }
    }
     
     
    // This RFC proposes allowing the type to be widened to be untyped aka any
    // type can be passed as the parameter.
    // Any type restrictions can be done via user code in the method body.
    class EverythingClass extends ArrayClass {
      public function foo($foo) { /* ... */ }
    }
    

     

     

    Gọi count() trên một scalar hoặc object không implement trả về 1 (phi logic).

    Trong phiên bản này đã thêm một cảnh báo khi gọi count() với tham số là scalar, null hoặc một object không implement Countable.

     

    được sử dụng trong namespace

    use Foo\Bar\{ Foo, Bar, Baz, };
    

     

     

    Các hàm password_ * hiện có cung cấp interface đơn giản để băm mật khẩu. RFC này đề xuất triển khai Argon2i (v1.3) trong các hàm password_ * để sử dụng thay thế an toàn cho bcrypt.

     

     

    $db = new PDO(...);
     
    // works with statements without bound values
    $stmt = $db->query('SELECT 1');
    var_dump($stmt->activeQueryString()); // => string(8) "SELECT 1"
     
    $stmt = $db->prepare('SELECT :string');
    $stmt->bindValue(':string', 'foo');
     
    // returns unparsed query before execution
    var_dump($stmt->activeQueryString()); // => string(14) "SELECT :string"
     
    // returns parsed query after execution
    $stmt->execute();
    var_dump($stmt->activeQueryString()); // => string(11) "SELECT 'foo'"
    

    PHP 7.4 (In development)

     

    class User {
        public int $id;
        public string $name;
     
        public function __construct(int $id, string $name) {
            $this->id = $id;
            $this->name = $name;
        }
    }
    

     

     

    FFI là một trong những tính năng giúp PythonLuaJIT rất hữu ích cho việc tạo mẫu nhanh. Nó cho phép gọi các hàm C và sử dụng các kiểu dữ liệu C từ ngôn ngữ kịch bản thuần túy và do đó phát triển "system code" hiệu quả hơn. Đối với PHP, FFI mở ra một cách để viết các phần mở rộng và ràng buộc PHP vào các thư viện C trong PHP thuần.

     

     

    // The folloving lines are doing the same
    $this->request->data['comments']['user_id'] = $this->request->data['comments']['user_id'] ?? 'value';
    // Instead of repeating variables with long names, the equal coalesce operator is used
    $this->request->data['comments']['user_id'] ??= 'value';
    

     

     

    PHP đã sử dụng opcode caches từ lâu (APC, Turck MMCache, Zend OpCache). Họ đạt được hiệu suất tăng đáng kể bằng cách GẦN NHƯ loại bỏ hoàn toàn overhead của biên dịch lại PHP code. Preloading sẽ được kiểm soát chỉ bằng một chỉ thị php.ini mới - opcache.preload. Sử dụng chỉ thị này, chúng ta sẽ chỉ định một file PHP - sẽ thực hiện nhiệm vụ tải trước. Sau khi tải, file này sau đó được thực thi đầy đủ - và có thể tải trước các file khác, bằng cách including chúng hoặc bằng cách sử dụng hàm opcache_compile_file().

     

     

    Điều này sẽ làm cho hash extension (`ext / hash`) luôn có sẵn, tương tự như `date`. Phần hash extension cung cấp một tiện ích rất phong phú với nhiều thuật toán băm cực kỳ hữu ích trong các ứng dụng hiện đại, không chỉ trong code người dùng mà còn rất nhiều trong nội bộ.

    On the way to PHP 8.0

     

    Nói ngắn gọn. Khi bạn khởi động một chương trình PHP, Zend Engine sẽ phân tích code thành một cây cú pháp trừu tượng (AST) và dịch nó sang opcodes. Các opcodes là các đơn vị thực thi cho Máy ảo Zend (Zend VM). Opcode là mức độ khá thấp, do đó dịch code sang máy nhanh hơn nhiều so với code PHP gốc. PHP có một phần mở rộng có tên OPcache trong lõi, để lưu trữ các opcodes này.

    “JIT” is a technique that will compile parts of the code at runtime, so that the compiled version can be used instead.

     

    Đây là một trong những chiến lược tối ưu hóa PHP cuối cùng và lớn nhất vẫn còn trên bàn. Các PHP engineers đang tìm kiếm để xem cách tiếp cận mới này có thể vượt qua các ứng dụng của họ. Thực sự quan tâm đến điều này.

     

     

    Làm cho các API phân tích tham số nội bộ luôn tạo ra TypeError nếu parameter parsing không thành công. Cần lưu ý rằng điều này cũng bao gồm ArgumentCountError (con của TypeError) cho các trường hợp có quá ít/nhiều đối số được thông qua.

    So sánh hiệu suất

    Tôi đã soạn một bài test đơn giản để giúp dễ dàng so sánh hiệu suất của các phiên bản PHP khác nhau (sử dụng Docker). Điều này thậm chí sẽ cho phép dễ dàng kiểm tra hiệu năng của các phiên bản PHP mới chỉ bằng cách thêm tên container mới.

    Chạy trên Macbook pro, 2,5 GHz Intel Core i7.

    PHP version : 5.6.40
    --------------------------------------
    test_math                 : 1.101 sec.
    test_stringmanipulation   : 1.144 sec.
    test_loops                : 1.736 sec.
    test_ifelse               : 1.122 sec.
    Mem: 429.4609375 kb Peak mem: 687.65625 kb
    --------------------------------------
    Total time:               : 5.103
    
    PHP version : 7.0.33
    --------------------------------------
    test_math                 : 0.344 sec.
    test_stringmanipulation   : 0.516 sec.
    test_loops                : 0.477 sec.
    test_ifelse               : 0.373 sec.
    Mem: 421.0859375 kb Peak mem: 422.2109375 kb
    --------------------------------------
    Total time:               : 1.71
    
    PHP version : 7.1.28
    --------------------------------------
    test_math                 : 0.389 sec.
    test_stringmanipulation   : 0.514 sec.
    test_loops                : 0.501 sec.
    test_ifelse               : 0.464 sec.
    Mem: 420.9375 kb Peak mem: 421.3828125 kb
    --------------------------------------
    Total time:               : 1.868
    
    PHP version : 7.2.17
    --------------------------------------
    test_math                 : 0.264 sec.
    test_stringmanipulation   : 0.391 sec.
    test_loops                : 0.182 sec.
    test_ifelse               : 0.252 sec.
    Mem: 456.578125 kb Peak mem: 457.0234375 kb
    --------------------------------------
    Total time:               : 1.089
    
    PHP version : 7.3.4
    --------------------------------------
    test_math                 : 0.233 sec.
    test_stringmanipulation   : 0.317 sec.
    test_loops                : 0.171 sec.
    test_ifelse               : 0.263 sec.
    Mem: 459.953125 kb Peak mem: 460.3984375 kb
    --------------------------------------
    Total time:               : 0.984
    
    PHP version : 7.4.0-dev
    --------------------------------------
    test_math                 : 0.212 sec.
    test_stringmanipulation   : 0.358 sec.
    test_loops                : 0.205 sec.
    test_ifelse               : 0.228 sec.
    Mem: 459.6640625 kb Peak mem: 460.109375 kb
    --------------------------------------
    Total time:               : 1.003
    

    Nếu muốn tự kiểm tra, bạn có thể tìm source code trong này.

    Benchmarks từ PHP 5.6 trở lên

    Tôi thực sự thích phần tổng hợp hiệu năng trực quan từ của tất cả các phiên bản chính từ 5.6 trở lên. Xem kết quả trong các bảng dưới đây.

    Tóm lược hiệu năng

    PHP 7.0.0 là một cột mốc quan trọng với hiệu suất được cải thiện đáng kể và sử dụng bộ nhớ thấp hơn nhưng các PHP maintainers chỉ đơn giản là hết ý tưởng để cải thiện nó. Một trong những điểm còn lại là biên dịch JIT (Just in time). Và nó đi kèm với PHP 8.0.

    Hướng phát triển

    Trong suốt các phiên bản PHP 7.x, có một path có thể nhìn thấy được nhắc tới nhiều hơn (và khách quan hơn một chút) và ngôn ngữ lập trình hiện đại. Tuy nhiên, PHP thích áp dụng các tính năng hữu ích và gọn gàng từ các ngôn ngữ lập trình khác.

    Chúng ta sẽ sớm thấy một số tính năng hay hơn, như:

    Với những điều này, PHP developers sẽ tham gia nhóm những người áp dụng ngôn ngữ hiện đại. Không có ngôn ngữ nào là hoàn hảo, nhưng PHP đang mở đường cho tương lai.

    CÓ THỂ BẠN QUAN TÂM

    Bài Viết Cùng Chuyên Mục

    XEM THÊM
    thumbnail

    Kubernetes bài 6 - Vận hành k8s Day-Two Operations và Quản trị bằng GitOps

    22.05.2026

    Khi cụm Kubernetes của bạn đã được bảo mật cấu hình, tối ưu tài nguyên và thiết lập tự phục hồi, câu hỏi đặt ra là làm sao để duy trì sự ổn định đó trong nhiều năm tiếp theo mà không bị phụ thuộc

    thumbnail

    Kubernetes bài 5 - bảo mật Cloud Native và chuẩn DevSecOps cho K8s

    22.05.2026

    Việc siết chặt an ninh (Hardening) không phải là cấu hình một vài thông số rồi bỏ đó, mà là một tư duy phòng thủ chiều sâu.

    thumbnail

    Kubernetes bài 4 - Tối ưu Resource Auto-Healing và Scale Zero-Downtime

    22.05.2026

    Bài viết này sẽ đi sâu vào các cơ chế ở tầng Kernel giúp hệ thống tự phục hồi, chống lại các đợt tấn công cạn kiệt tài nguyên và cập nhật phiên bản mới mà người dùng không hề hay biết.

    thumbnail

    Kubernetes bài 3 - Bảo mật cấu hình k8s và config Security trên Production

    22.05.2026

    Kubernetes giải quyết bài toán này bằng hai đối tượng chuyên biệt nhưng nếu không hiểu rõ bản chất bảo mật ở tầng dưới, bạn đang tự tay dâng toàn bộ chìa khóa hệ thống cho hacker.

    thumbnail

    Kubernetes bài 2 - Mạng lưới k8s và luồng Traffic ở Packet Level

    22.05.2026

    Pod không chỉ là một container: Rất nhiều người nhầm lẫn Pod 1-1 với Container. Thực chất, Pod là đơn vị triển khai nhỏ nhất, có thể chứa một hoặc nhiều container

    Mục lục bài viết