While looking at the Laravel source, I noticed a lot of stuff like this:
A controller class:
class Controller extends BaseController
{
use AuthorizesRequests, AuthorizesResources, DispatchesJobs, ValidatesRequests;
}
One of its component traits:
trait AuthorizesRequests {
/**
* Authorize a given action against a set of arguments.
*
* @param mixed $ability
* @param mixed|array $arguments
*
* @return \Illuminate\Auth\Access\Response
*
* @throws \Illuminate\Auth\Access\AuthorizationException
*/
public function authorize($ability, $arguments = []) {
list($ability, $arguments) = $this->parseAbilityAndArguments($ability, $arguments);
return app(Gate::class)->authorize($ability, $arguments);
}
// ...
}
I have a couple of questions about this:
app()
, in this case)?I'm considering using this approach in my code to share some general functionality between a couple of my classes - I'm considering creating a ChecksBarcodes
trait, which will work with a repository of stock information, and sharing that trait between a few similar but unrelated product management process classes, which all need to check barcodes.
Traits, being introduced with PHP 5.4, in general solving one big problem of PHP: single inheritance. A rough guess from me: if PHP would support multi inheritance (inherit from more than one class) there wouldn't be traits.
Nevertheless, traits are a good thing to reduce duplications of code and furthermore provide same fuctionality to multiple classes.
Traits are similar to extending classes, but with a few differences
They're similar to mixins in other languages. I guess you could say its an easy way to use the DRY principle.
Since traits don't have constructors, any dependencies they have would need to exist on the class they're used on. I think depending on the class to have something other than the trait would be a bad design pattern. So you would have to use a service locator to pull in dependencies.
If you would rather not use a service locator, I would recommend using a class rather than a trait. You could have a BarcodeChecker
class that you could inject into the constructor of the classes you want to use it. Then instead of $this->checkBarcode()
you would use $this->barcodeChecker->check()
. I think that would be a better design pattern if the trait requires dependencies.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With