Μέθοδοι και attributes inject
Σε αυτό το άρθρο, θα επικεντρωθούμε στους διάφορους τρόπους
περάσματος εξαρτήσεων στους presenters στο Nette framework. Θα συγκρίνουμε τον
προτιμώμενο τρόπο, που είναι ο constructor, με άλλες επιλογές, όπως οι
μέθοδοι και τα attributes inject
.
Και για τους presenters ισχύει ότι το πέρασμα εξαρτήσεων μέσω του constructor είναι
ο προτιμώμενος δρόμος. Αν όμως δημιουργείτε έναν κοινό πρόγονο από τον
οποίο κληρονομούν άλλοι presenters (π.χ. BasePresenter
), και αυτός ο πρόγονος
έχει επίσης εξαρτήσεις, προκύπτει ένα πρόβλημα που ονομάζουμε constructor hell. Αυτό
μπορεί να παρακαμφθεί χρησιμοποιώντας εναλλακτικούς δρόμους, που
αντιπροσωπεύουν οι μέθοδοι και τα attributes (annotations) inject
.
Μέθοδοι inject*()
Πρόκειται για μια μορφή περάσματος εξάρτησης με setter. Το όνομα
αυτών των setters ξεκινά με το πρόθεμα inject
. Το Nette DI καλεί αυτόματα
τις μεθόδους με αυτό το όνομα αμέσως μετά τη δημιουργία της παρουσίας
του presenter και τους περνά όλες τις απαιτούμενες εξαρτήσεις. Πρέπει
επομένως να δηλώνονται ως public.
Οι μέθοδοι inject*()
μπορούν να θεωρηθούν ως ένα είδος επέκτασης
του constructor σε περισσότερες μεθόδους. Χάρη σε αυτό, ο BasePresenter
μπορεί να λάβει εξαρτήσεις μέσω μιας άλλης μεθόδου και να αφήσει τον
constructor ελεύθερο για τους απογόνους του:
abstract class BasePresenter extends Nette\Application\UI\Presenter
{
private Foo $foo;
public function injectBase(Foo $foo): void
{
$this->foo = $foo;
}
}
class MyPresenter extends BasePresenter
{
private Bar $bar;
public function __construct(Bar $bar)
{
$this->bar = $bar;
}
}
Ο presenter μπορεί να περιέχει οποιονδήποτε αριθμό μεθόδων inject*()
και καθεμία μπορεί να έχει οποιονδήποτε αριθμό παραμέτρων. Ταιριάζουν
εξαιρετικά επίσης σε περιπτώσεις όπου ο presenter αποτελείται από traits και καθεμία
από αυτές απαιτεί τη δική της εξάρτηση.
Attributes Inject
Πρόκειται για μια μορφή injection στην ιδιότητα. Αρκεί να επισημάνετε σε ποιες μεταβλητές πρέπει να γίνει inject, και το Nette DI περνά αυτόματα τις εξαρτήσεις αμέσως μετά τη δημιουργία της παρουσίας του presenter. Για να μπορέσει να τις εισαγάγει, είναι απαραίτητο να δηλώνονται ως public.
Επισημαίνουμε τις properties με το attribute: (παλαιότερα χρησιμοποιούνταν η
annotation /** @inject */
)
use Nette\DI\Attributes\Inject; // αυτή η γραμμή είναι σημαντική
class MyPresenter extends Nette\Application\UI\Presenter
{
#[Inject]
public Cache $cache;
}
Το πλεονέκτημα αυτού του τρόπου περάσματος εξαρτήσεων ήταν η πολύ οικονομική μορφή γραφής. Ωστόσο, με την έλευση του constructor property promotion, φαίνεται ευκολότερο να χρησιμοποιηθεί ο constructor.
Αντίθετα, αυτός ο τρόπος πάσχει από τις ίδιες αδυναμίες με το πέρασμα εξαρτήσεων σε properties γενικά: δεν έχουμε έλεγχο στις αλλαγές στη μεταβλητή και ταυτόχρονα η μεταβλητή γίνεται μέρος του δημόσιου interface της κλάσης, πράγμα που είναι ανεπιθύμητο.