2016-06-22 62 views
5

Mentre guardando il sorgente laravel, ho notato un sacco di cose come questa:Qual è lo schema del tratto Laravel?

Una classe controller:

class Controller extends BaseController 
{ 
    use AuthorizesRequests, AuthorizesResources, DispatchesJobs, ValidatesRequests; 
} 

Uno dei suoi tratti componenti:

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); 
    } 

    // ... 

} 

Ho un paio di domande a riguardo:

  • Questo modello (l'astrazione di funzionalità riutilizzabili in tratti) ha un nome?
  • Questo pattern è utilizzato con buoni risultati in altri progetti?
  • Se un tratto richiede dipendenze, esiste un modo migliore per iniettarle, invece di utilizzare un localizzatore di servizio (come app(), in questo caso)?

Sto pensando di utilizzare questo approccio nel mio codice per condividere alcune funzionalità generale tra un paio delle mie classi - che sto pensando di creare un tratto ChecksBarcodes, che lavorerà con un repository di informazioni di borsa, e condivisione che tratto tra alcune classi di processo di gestione prodotto simili ma non correlate, che devono tutte controllare i codici a barre.

risposta

1

Tratti, introdotti con PHP 5.4, in generale risoluzione di un grande problema di PHP: ereditarietà singola. Un'ipotesi approssimativa da parte mia: se PHP supportasse l'ereditarietà multipla (ereditata da più di una classe) non ci sarebbero tratti.

Tuttavia, i tratti sono una buona cosa per ridurre le duplicazioni di codice e inoltre forniscono la stessa funzionalità a più classi.

  • Per quanto posso vedere, non esiste un nome reale (modello) per l'utilizzo dei tratti.
  • Non è un modello di per sé, rispetto ad altri design pattern, lo chiamano semplicemente tratti;)
  • laravel e forse più in particolare il pacchetto di Cassa sono buoni esempi di utilizzo di tratti. Se qualcuno trova altri buoni esempi, per favore menzionalo.
  • I tratti possono essere estesi con altri tratti. Questo naturalmente crea sempre più complessità. Per estenderli probabilmente dovresti prendere in considerazione altri metodi per portare una funzionalità alla tua classe. Il "concatenarsi" dei tratti aggiunge un carico di complessità.
2

Tratti sono simili a estendere le classi, ma con alcune differenze

  • Tratti non dispone di un costruttore
  • Le classi possono estendere una sola classe, ma hanno più tratti

Sono simili ai mixin in altre lingue. Immagino si possa dire che è un modo semplice per usare lo DRY principle.

Poiché i tratti non hanno costruttori, eventuali dipendenze devono esistere nella classe in cui sono utilizzati. Penso che dipendere dalla classe per avere qualcosa di diverso dal tratto sarebbe un cattivo modello di design. Quindi dovresti usare un localizzatore di servizi per tirare le dipendenze.

Se preferisci non utilizzare un localizzatore di servizi, ti consiglio di utilizzare una classe piuttosto che un tratto. Potresti avere una classe BarcodeChecker che potresti iniettare nel costruttore delle classi che vuoi usare. Quindi invece di $this->checkBarcode() useresti $this->barcodeChecker->check(). Penso che sarebbe un modello di design migliore se il tratto richiede dipendenze.

+0

Cosa ne pensi di passare una dipendenza dalla classe alla caratteristica attraverso la funzione chiamata stessa? '$ this-> checkBarcode ($ dependency, $ barcode);' Sembra un'altra possibilità, ma piuttosto sfacciata. Sei d'accordo? – Alex

+1

Sì, mi sembra meno utile. Se lo fai in questo modo, ogni classe che eredita il tratto deve comunque avere la dipendenza iniettata manualmente, vanificando lo scopo di estrarre comportamenti ripetuti. – Jeff

+0

Grazie mille per i tuoi pensieri Jeff. @codedge e hai entrambi risposto a parti separate della domanda, quindi se potessi accettare entrambe le risposte lo farei! Hanno scelto di accettare l'altra risposta in quanto si riferisce più strettamente al titolo generale della domanda rispetto alla discussione sulla dipendenza. – Alex