It’s about vanilla PHP, here is documentation PHP: Traits – Manual, here is an example.
1trait Taggable2{3 public function slug()4 {5 return Str::slug($this->slug, '-');6 }7}
For now, I don’t want to make a string slugging for the slug, I would like changing to the snake, in the past, I would like to do the following:
1class Post2{3 use Taggable;45 /** overwritten */6 public function slug()7 {8 return Str::snake($this->slug);9 }10}
But here is a problem, if I have a ton of classes used the trait, I need to remember all of this to add the method, and I cannot be overwritten by the other trait, it caused an error:
1PHP Fatal error:2Trait method slug has not been applied, because there are collisions with other trait methods on Post
So how to do it correctly? use as
and insteadof
if you want to overwrite
1class Post2{3 use Taggable {4 Taggable::slug as snakeSlug;5 }67 public function snakeSlug($slug)8 {9 return Str::snake($slug);10 }11}
If snakeSlug
does not exist, it will call to slug
. Also, you can change the visibility.
1class Post2{3 use Taggable {4 Taggable::slug as protected snakeSlug;5 }67 protected function snakeSlug($slug)8 {9 return Str::snake($slug);10 }11}
If you put the method on Snakeable
, you need to use insteadof
1class Post2{3 use Snakeable;4 use Taggable {5 Snakeable::slug insteadof Taggable;6 }7}
If you’re having multiple methods, you should specific each.
1trait Taggable2{3 public function slug($slug)4 {5 return Str::slug($slug, '-');6 }78 public function title($title)9 {10 return Str::limit($title, 200);11 }12}1314trait Snakeable15{16 public function slug($slug)17 {18 return Str::snake($slug);19 }2021 public function title($title)22 {23 return Str::limit($title, 1);24 }25}2627class Post28{29 use Snakeable;30 use Taggable {31 Snakeable::slug insteadof Taggable;32 Taggable::title insteadof Snakeable;33 Snakeable::title as public title;34 }3536 public function title($title)37 {38 return Str::of($title)->start('');39 }40}
When do I need to do this?
Here is my situation, I need to overwrite a method in the package trait, in the past I need to copy all of the methods to the upper class.
1// the package trait.2trait Taggable3{4 public function transform()5 {6 // do something...7 }8}910class Post11{12 use Taggable;13}
But I have a lots classes using it, so I want to capsule to trait.
1// the package trait.2trait Taggable3{4 public function transform()5 {6 // do something...7 }89 public function slug()10 {11 // do something...12 }13}1415// my customize trait.16trait TaggableWithTransform17{18 // needs to over writen.19 public function transform()20 {21 // do something...22 }23}242526class Post27{28 use TaggableWithTransform;29 use Taggable {30 TaggableWithTransform::transform insteadof Taggable;31 }32}