How to call an overridden trait function
Traits are a wonderful thing in PHP. You can use them to reduce code duplication by putting common functions in a trait and apply them to all classes where those functions are needed. I also sometimes use traits to break up a large function in multiple single-use traits.
In this post, I'd like to show you how you can override a trait function and call it from the overriding function.
Overriding a trait function
Let's create a simple trait and use it in a class.
trait MyTrait
{
public function sayHi()
{
echo 'trait says hi';
}
}
class MyClass
{
use MyTrait;
}
Executing (new MyClass)->sayHi();
will output "trait says hi".
The trait function can be overridden simply by defining a function with the same name in the class.
class MyClass
{
use MyTrait;
public function sayHi()
{
echo 'class says hi';
}
}
Now (new MyClass)->sayHi();
will output "class says hi".
Calling the trait implementation from inside the overridden function
You probably don't need this every day, but here's how you can call the sayHi
implementation from the trait inside the sayHi
function from the class.
class MyClass
{
use MyTrait {
sayHi as protected sayHiFromTrait;
}
public function sayHi()
{
$this->sayHiFromTrait();
echo ' and class says hi';
}
}
Now (new MyClass)->sayHi();
will output "trait says hi and class says hi".
An example where I needed this
I'm currently working on Media Library Pro. This package will provide, next to Vue and React components, a couple Livewire powered components that make it easy to upload files to the media library.
Under the hood it will use Livewire's upload capabilities. To use Livewire's upload functionalities, you need to apply a trait called WithFileUploads
. Out of the box, Livewire handles upload errors too. This is done inside the uploadErrored
function of the trait.
The collection component of media library pro can be used to administer files inside a media library collection.
Here's how the collection component looks like by default.
If you try to add a file to the collection that is too big, an error message is displayed at the top.
If you want to replace a file in the collection, you can drag a file on top of a row. If the file isn't accepted, an error message is displayed on the row.
To achieve this, the component still relies on the uploadErrored
implementation inside of the Livewire's WithFileUploads
trait. The implementation will try a ValidationException
. In our component, we catch that exception and perform the necessary logic to display the error message at the right place. Here's the relevant code inside our component.
namespace Spatie\MediaLibraryPro\Http\Livewire;
use Illuminate\Validation\ValidationException;
use Livewire\Component;
use Livewire\WithFileUploads;
class LivewireUploaderComponent extends Component
{
use WithFileUploads {
uploadErrored as protected uploadErroredTrait;
}
// ...
public function uploadErrored($name, $errorsInJson, $isMultiple)
{
try {
$this->uploadErroredTrait($name, $errorsInJson, $isMultiple);
} catch (ValidationException $exception) {
$uploadError = $exception->validator->errors()->first();
$this->replacingMedia()
? $this->emit('showItemUploadError', $this->uuid, $uploadError)
: $this->emitUp('showListErrorMessage', $uploadError);
}
}
}
Closing thoughts
I hope you enjoyed this little explanation of how you can call overridden trait methods. To stay in the loop of media library pro, subscribe to the mailing list at medialibrary.pro
What are your thoughts on "How to call an overridden trait function"?