PHP 8 - mencoba fitur baru



PHP 8 sudah pada tahap kandidat rilis, versi RC 3 dirilis pada 29 Oktober, dan rilis penuh dijadwalkan pada 26 November. Jadi inilah saatnya untuk melihat fitur-fitur baru yang menunggu kita di PHP 8. Jadwal rilisnya bisa dilihat di sini . Dan panduan resmi untuk memperbarui ke versi baru ada di sini .



Menambahkan dukungan untuk jenis serikat pekerja ( RFC )



Jenis penyatuan menerima nilai dari berbagai jenis lainnya, dan bukan hanya satu.



<?php
declare(strict_types=1);
 
class Number {
    private int|float $number;
 
    public function setNumber(int|float $number): void {
        $this->number = $number;
    }
 
    public function getNumber(): int|float {
        return $this->number;
    }
}
 
/**
 * We can pass both floats or integer values
 * to the number object. Try passing a string.
 */
$number = new Number();
 
$number->setNumber(5);
 
dump($number->getNumber());
 
$number->setNumber(11.54);
 
dump($number->getNumber());
 
exit;


Menambahkan WeakMap ( RFC )



Peta yang lemah memungkinkan Anda membuat hubungan antara objek dan nilai arbitrer (serta SplObjectStorage), sedangkan objek yang digunakan sebagai kunci tidak dilindungi dari pengumpul sampah. Jika kolektor menghancurkan objek seperti itu, itu hanya akan dihapus dari peta.


Ini adalah fitur yang sangat berguna. Ini memungkinkan kita untuk tidak terlalu memikirkan kebocoran memori dalam kode kita. Meskipun ini seharusnya tidak menjadi masalah bagi sebagian besar pengembang PHP, ada baiknya melihat saat membuat proses yang berjalan lama, misalnya menggunakan ReactPHP. Dengan WeakMaps, referensi objek secara otomatis dikumpulkan oleh pengumpul sampah saat objek tidak tersedia.



Jika Anda melakukan hal yang sama dengan larik, referensi objek akan tetap ada, yang menyebabkan kebocoran memori.



<?php
declare(strict_types=1);
 
class FooBar {
    public WeakMap $cache;
    
    public function __construct() {
      $this->cache = new WeakMap();
    }
 
    public function getSomethingWithCaching(object $obj) {
        return $this->cache[$obj] ??= $this->computeSomethingExpensive($obj);
    }
    
    public function computeSomethingExpensive(object $obj) {
    dump("I got called");
    return rand(1, 100);
    }
}
 
$cacheObject = new stdClass;
 
$obj = new FooBar;
// "I got called" only will be printed once
$obj->getSomethingWithCaching($cacheObject);
$obj->getSomethingWithCaching($cacheObject);
 
dump(count($obj->cache));
 
// When unsetting our object, the WeakMap frees up memory
unset($cacheObject);
 
dump(count($obj->cache));
 
exit;


Pengecualian baru ValueError



PHP 8 memperkenalkan kelas pengecualian bawaan baru ValueError. Itu melengkapi dirinya sendiri \Exception. PHP melontarkan pengecualian ini setiap kali Anda meneruskan nilai dengan tipe yang benar ke suatu fungsi, tetapi tidak dapat digunakan dalam operasi ini. Sebelumnya, peringatan telah dikeluarkan untuk kasus-kasus seperti itu. Contoh:



<?php
declare(strict_types=1);
 
/**
 * We pass an array to array_rand,
 * which is of the correct type. But
 * array_rand expects non-empty arrays.
 *
 * This throws a ValueError exception.
 */
array_rand([], 0);
 
/**
 * The depth argument for json_decode is a
 * valid integer, but it must be greater than 0
 */
json_decode('{}', true, -1);


Saat menentukan fungsi, Anda bisa menggunakan argumen variadic



Sejumlah parameter fungsi sekarang dapat diganti dengan argumen variadic jika tipenya kompatibel. Misalnya, kode berikut ini salah:


<?php
declare(strict_types=1);
 
class A {
    public function method(int $many, string $parameters, $here) {
 
    }
}
class B extends A {
    public function method(...$everything) {
        dd($everything);
    }
}
 
$b = new B();
$b->method('i can be overwritten!');
exit;


Jenis pengembalian statis ( RFC )



Jenis pengembalian statis sekarang dapat digunakan untuk menentukan apakah suatu metode mengembalikan kelas yang dipanggil metode tersebut, bahkan jika itu diwariskan (pengikatan statis terlambat).



<?php
declare(strict_types=1);
 
class Test {
    public function doWhatever(): static {
        // Do whatever.
        return $this;
    }
}
 
exit;


Object Class Name Literal ( RFC )



Sekarang Anda dapat mengambil nama kelas dari suatu objek menggunakan $object::class. Hasilnya akan sama dengan get_class($object).



<?php
declare(strict_types=1);
 
auth()->loginUsingId(1);
 
dump(auth()->user()::class);
 
// Or with a temporary variable
$user = auth()->user();
 
dump($user::class);
exit;


Variable Syntax Settings ( RFC )



Newdan instanceofsekarang dapat digunakan dengan ekspresi arbitrer: new ()(...$args)dan $obj instanceof ().



<?php
declare(strict_types=1);
 
class Foo {}
class Bar {}
 
 
$class = new (collect(['Foo', 'Bar'])->random());
 
dd($class);
 
exit;


Antarmuka Stringable ( RFC )



PHP 8 memperkenalkan antarmuka baru Stringableyang ditambahkan secara otomatis segera setelah kelas menerapkan metode __toString. Anda tidak perlu mengimplementasikan antarmuka ini secara eksplisit.



<?php
declare(strict_types=1);
 
class Foo {
    public function __toString() {
        return 'I am a class';
    }
}
 
$obj = new Foo;
dump($obj instanceof Stringable);
 
exit;


Sifat sekarang dapat mendefinisikan metode privat abstrak ( RFC )



<?php
declare(strict_types=1);
 
 
trait MyTrait {
    abstract private function neededByTheTrait(): string;
 
    public function doSomething() {
        return strlen($this->neededByTheTrait());
    }
}
 
class TraitUser {
    use MyTrait;
 
    // This is allowed:
    private function neededByTheTrait(): string { }
 
    // This is forbidden (incorrect return type)
    // private function neededByTheTrait(): stdClass { }
 
    // This is forbidden (non-static changed to static)
    // private static function neededByTheTrait(): string { }
}
 
exit;


lemparan sekarang dapat digunakan sebagai ekspresi ( RFC )



Ekspresi throwsekarang dapat digunakan di mana hanya ekspresi yang diperbolehkan: dalam fungsi panah, operator penggabungan, operator bersyarat terner (terner / elvis).



<?php
declare(strict_types=1);
 
$callable = fn() => throw new Exception();
 
$nullableValue = null;
 
// $value is non-nullable.
$value = $nullableValue ?? throw new \InvalidArgumentException();
 
 
exit;


Koma gantung opsional ( RFC ) sekarang diizinkan dalam parameter daftar



Dengan analogi dengan koma gantung dalam array, sekarang Anda dapat mendefinisikannya dalam parameter daftar.



<?php
declare(strict_types=1);
 
function method_with_many_arguments(
    $a, 
    $b,
    $c,
    $d,
) {
    dump("this is valid syntax");
}
 
method_with_many_arguments(
    1,
    2,
    3,
    4,
);
 
exit;


Menangkap Pengecualian Tanpa Menyimpan dalam Variabel ( RFC )



Sekarang Anda dapat menulis catch ()untuk menangkap pengecualian tanpa menyimpannya dalam variabel.



<?php
declare(strict_types=1);
 
$nullableValue = null;
 
try {
    $value = $nullableValue ?? throw new \InvalidArgumentException();
} catch (\InvalidArgumentException) {
    dump("Something went wrong");
}
 
 
exit;


Menambahkan dukungan untuk jenis campuran ( RFC )



PHP 8 memperkenalkan tipe baru yang disebut campuran. Ini bisa setara dengan tipe array, bool, callable, int, float, null, object, resource, string.



<?php
declare(strict_types=1);
 
function debug_function(mixed ...$data) {
    dump($data);
}
 
debug_function(1, 'string', []);
 
exit;


Menambahkan dukungan untuk atribut



Ada beberapa saran untuk mengimplementasikan atribut di PHP 8:





Ini adalah salah satu perubahan terbesar dalam PHP 8. Mungkin tidak mudah untuk memahaminya pada awalnya. Singkatnya, atribut memungkinkan Anda menambahkan metadata ke fungsi PHP, parameter, kelas, dll. Metadata ini kemudian dapat diambil secara terprogram. Jika di PHP 7 atau lebih rendah Anda perlu mengurai doclocks, atribut akan membantu Anda mengakses informasi ini, terintegrasi secara mendalam ke dalam PHP itu sendiri.



Untuk membuatnya lebih jelas, bayangkan Anda ingin pengguna Anda dapat menambahkan middleware ke kelas atau pengontrol metode dengan menggunakan atribut.



<?php
declare(strict_types=1);
// First, we need to define the attribute. An Attribute itself is just a plain PHP class, that is annotated as an Attribute itself.
 
#[Attribute]
class ApplyMiddleware
{
    public array $middleware = [];
 
    public function __construct(...$middleware) {
        $this->middleware = $middleware;
    }
}
 
// This adds the attribute to the MyController class, with the "auth" middleware as an argument.
 
#[ApplyMiddleware('auth')]
class MyController
{
    public function index() {}
}
 
// We can then retrieve all ApplyMiddleware attributes on our class using reflection
// And read the given middleware arguments.
 
$reflectionClass = new ReflectionClass(MyController::class);
 
$attributes = $reflectionClass->getAttributes(ApplyMiddleware::class);
 
foreach ($attributes as $attribute) {
    $middlewareAttribute = $attribute->newInstance();
    dump($middlewareAttribute->middleware);
}
 
exit;


Menambahkan dukungan untuk meneruskan properti konstruktor ( RFC )



Diusulkan untuk menambahkan sintaks sederhana yang memungkinkan Anda menggabungkan konstruktor dengan definisi properti:



<?php
declare(strict_types=1);
 
class User {
    public function __construct(
        public int $id,
        public string $name,
    ) {}
}
 
$user = new User(1, 'Marcel');
 
dump($user->id);
dump($user->name);
 
exit;


Menambahkan dukungan untuk ekspresi pertandingan ( RFC )



Diusulkan untuk menambahkan ekspresi baru matchyang serupa switch, hanya dengan semantik yang lebih aman dan kemampuan untuk mengembalikan nilai.



<?php
declare(strict_types=1);
 
echo match (1) {
    0 => 'Foo',
    1 => 'Bar',
    2 => 'Baz',
};
 
exit;


Menambahkan dukungan untuk operator nullsafe (? ->) ( RFC )



Jika hasil dari sisi kiri operator adalah null, eksekusi seluruh rantai dihentikan, dan hasilnya disetel ke null. Jika tidak, rantai akan berperilaku seperti operator biasa ->.


<?php
declare(strict_types=1);
 
class User {
    public function getAddress() {}
}
 
$user = new User();
 
$country = $user?->getAddress()?->country?->iso_code;
 
dump($country);
 
exit;


Menambahkan dukungan untuk argumen bernama ( RFC )



Penamaan memungkinkan Anda meneruskan argumen ke fungsi berdasarkan nama parameter, bukan posisinya. Artinya, nilai argumen menjadi terdokumentasi sendiri, dan argumen tidak lagi bergantung pada urutan pencacahan, sehingga Anda dapat mengabaikan nilai default secara sewenang-wenang.


<?php
declare(strict_types=1);
 
array_fill(start_index: 0, num: 100, value: 50);
 
exit;



All Articles