Trait trong PHP là một cơ chế cho phép tái sử dụng code giữa nhiều class mà không cần dùng kế thừa (inheritance). Nó giống như một “bộ phương thức dùng chung” có thể được nhúng vào nhiều class khác nhau.
Trait được giới thiệu từ PHP 5.4 để giải quyết vấn đề PHP không hỗ trợ multiple inheritance (kế thừa nhiều lớp).
Nói đơn giản
Trait = một tập hợp method có thể import vào class bằng từ khóa use.
Trong OOP truyền thống của PHP
Một class chỉ được kế thừa 1 class cha
class A {}
class B extends A {}
Nhưng nếu bạn muốn dùng lại logic từ nhiều nơi khác nhau thì sẽ gặp vấn đề.
Ví dụ
PostUserProductCả 3 đều cần chức năng:
Bạn không thể viết
class Post extends Logger, Timestamp
Vì PHP không hỗ trợ multiple inheritance.
Trait ra đời để giải quyết vấn đề này.
trait LoggerTrait
{
public function log($message)
{
echo "[LOG] " . $message;
}
}
Trait giống class nhưng dùng từ khóa trait.
class User
{
use LoggerTrait;
}$user = new User();
$user->log("User created");
Kết quả
[LOG] User created
Trait được copy method vào class tại compile time.
Hiểu đơn giản:
Khi PHP compile code
class User {
use LoggerTrait;
}
PHP sẽ inject code của trait vào class.
Giống như viết thẳng trong class
class User
{
public function log($message)
{
echo "[LOG] " . $message;
}
}
Vì vậy trait không phải object riêng.
trait LoggerTrait
{
public function log($msg)
{
echo $msg;
}
}trait TimeTrait
{
public function now()
{
return date("Y-m-d H:i:s");
}
}class Post
{
use LoggerTrait, TimeTrait;
}
Sử dụng
$post = new Post();echo $post->now();
$post->log("created");
Trait có thể chứa
trait A {
public function test() {}
}
trait A {
public $name;
}
trait A {
public static function hello() {}
}
Nếu 2 trait có cùng method.
trait A {
public function hello() {}
}trait B {
public function hello() {}
}
Class
class Test {
use A, B;
}
PHP sẽ lỗi
Trait method hello has not been applied
insteadofclass Test
{
use A, B {
A::hello insteadof B;
}
}
Nghĩa là
dùng hello của A thay vì B
class Test
{
use A, B {
A::hello insteadof B;
B::hello as helloB;
}
}
Lúc này
$test->hello(); // từ A $test->helloB(); // từ B
| Feature | Trait | Abstract Class | Interface |
|---|---|---|---|
| Có code | ✔ | ✔ | ✖ |
| Có property | ✔ | ✔ | ✖ |
| Multiple use | ✔ | ✖ | ✔ |
| Kế thừa | ✖ | ✔ | ✖ |
Ví dụ trait SoftDeletes
trait SoftDeletes
{
public function delete()
{
$this->deleted_at = now();
}
}
Model
class Post extends Model
{
use SoftDeletes;
}
Trait phù hợp khi
Ví dụ
Ví dụ
User Admin Customer
Cùng cần
generateSlug()
Giống kiểu
class User + Notifiable + Loggable + Sluggable
trait SlugTrait
{
public function slug($text)
{
return strtolower(str_replace(" ", "-", $text));
}
}class Post
{
use SlugTrait;
}$post = new Post();echo $post->slug("Hello World");
Output
hello-world
Trait là cơ chế tái sử dụng code trong PHP cho phép một class dùng nhiều nhóm method mà không cần kế thừa nhiều class.
Hiểu ngắn gọn
Trait = reusable methods
Class chỉ cần
use TraitName;
Nếu bạn chuẩn bị phỏng vấn PHP Senior, tôi có thể giải thích thêm những thứ rất hay bị hỏi về Trait như