Διαμόρφωση του DI Container

Επισκόπηση των επιλογών διαμόρφωσης για το Nette DI Container.

Αρχείο διαμόρφωσης

Το Nette DI Container ελέγχεται εύκολα μέσω αρχείων διαμόρφωσης. Αυτά συνήθως γράφονται σε μορφή NEON. Για την επεξεργασία, συνιστούμε editors με υποστήριξη αυτής της μορφής.

 decorator: 	Decorator
di: DI container
extensions: Εγκατάσταση πρόσθετων επεκτάσεων DI
includes: Εισαγωγή αρχείων
parameters: Παράμετροι
search: Αυτόματη καταχώρηση υπηρεσιών
services: Υπηρεσίες

Για να γράψετε μια συμβολοσειρά που περιέχει τον χαρακτήρα %, πρέπει να τον διαφύγετε διπλασιάζοντάς τον σε %%.

Παράμετροι

Στη διαμόρφωση, μπορείτε να ορίσετε παραμέτρους που μπορούν στη συνέχεια να χρησιμοποιηθούν ως μέρος των ορισμών υπηρεσιών. Με αυτόν τον τρόπο, μπορείτε να κάνετε τη διαμόρφωση πιο σαφή ή να ενοποιήσετε και να απομονώσετε τιμές που θα αλλάξουν.

parameters:
	dsn: 'mysql:host=127.0.0.1;dbname=test'
	user: root
	password: secret

Αναφερόμαστε στην παράμετρο dsn οπουδήποτε στη διαμόρφωση γράφοντας %dsn%. Οι παράμετροι μπορούν να χρησιμοποιηθούν και μέσα σε συμβολοσειρές όπως '%wwwDir%/images'.

Οι παράμετροι δεν χρειάζεται να είναι μόνο συμβολοσειρές ή αριθμοί, μπορούν επίσης να περιέχουν πίνακες:

parameters:
	mailer:
		host: smtp.example.com
		secure: ssl
		user: franta@gmail.com
	languages: [cs, en, de]

Αναφερόμαστε σε ένα συγκεκριμένο κλειδί ως %mailer.user%.

Εάν χρειάζεστε στον κώδικά σας, για παράδειγμα σε μια κλάση, να μάθετε την τιμή οποιασδήποτε παραμέτρου, τότε περάστε την σε αυτήν την κλάση. Για παράδειγμα, στον κατασκευαστή. Δεν υπάρχει κανένα καθολικό αντικείμενο που να αντιπροσωπεύει τη διαμόρφωση, το οποίο οι κλάσεις θα ρωτούσαν για τις τιμές των παραμέτρων. Αυτό θα παραβίαζε την αρχή του dependency injection.

Υπηρεσίες

Βλ. ξεχωριστό κεφάλαιο.

Decorator

Πώς να τροποποιήσετε μαζικά όλες τις υπηρεσίες ενός συγκεκριμένου τύπου; Για παράδειγμα, να καλέσετε μια συγκεκριμένη μέθοδο σε όλους τους presenters που κληρονομούν από έναν συγκεκριμένο κοινό πρόγονο? Γι' αυτό υπάρχει ο decorator.

decorator:
	# για όλες τις υπηρεσίες που είναι παρουσίες αυτής της κλάσης ή interface
	App\Presentation\BasePresenter:
		setup:
			- setProjectId(10)       # καλέστε αυτή τη μέθοδο
			- $absoluteUrls = true   # και ορίστε τη μεταβλητή

Ο decorator μπορεί επίσης να χρησιμοποιηθεί για τον ορισμό tags ή την ενεργοποίηση της λειτουργίας inject.

decorator:
	InjectableInterface:
		tags: [mytag: 1]
		inject: true

DI

Τεχνικές ρυθμίσεις του DI container.

di:
	# εμφάνιση του DIC στο Tracy Bar;
	debugger: ...        # (bool) η προεπιλογή είναι true

	# τύποι παραμέτρων που δεν γίνονται ποτέ autowired
	excluded: ...        # (string[])

	# επιτρέπεται η lazy δημιουργία υπηρεσιών;
	lazy: ...            # (bool) η προεπιλογή είναι false

	# κλάση από την οποία κληρονομεί το DI container
	parentClass: ...     # (string) η προεπιλογή είναι Nette\DI\Container

Lazy υπηρεσίες

Η ρύθμιση lazy: true ενεργοποιεί τη lazy (καθυστερημένη) δημιουργία υπηρεσιών. Αυτό σημαίνει ότι οι υπηρεσίες δεν δημιουργούνται πραγματικά τη στιγμή που τις ζητάμε από το DI container, αλλά τη στιγμή της πρώτης τους χρήσης. Αυτό μπορεί να επιταχύνει την εκκίνηση της εφαρμογής και να μειώσει τις απαιτήσεις μνήμης, καθώς δημιουργούνται μόνο οι υπηρεσίες που είναι πραγματικά απαραίτητες στο συγκεκριμένο request.

Για μια συγκεκριμένη υπηρεσία, η lazy δημιουργία μπορεί να αλλάξει.

Τα lazy αντικείμενα μπορούν να χρησιμοποιηθούν μόνο για κλάσεις χρήστη, όχι για εσωτερικές κλάσεις PHP. Απαιτεί PHP 8.4 ή νεότερη έκδοση.

Εξαγωγή μεταδεδομένων

Η κλάση του DI container περιέχει επίσης πολλά μεταδεδομένα. Μπορείτε να τη μειώσετε περιορίζοντας την εξαγωγή μεταδεδομένων.

di:
	export:
		# εξαγωγή παραμέτρων;
		parameters: false   # (bool) η προεπιλογή είναι true

		# εξαγωγή tags και ποια;
		tags:               # (string[]|bool) η προεπιλογή είναι όλα
			- event.subscriber

		# εξαγωγή δεδομένων για autowiring και ποια;
		types:              # (string[]|bool) η προεπιλογή είναι όλα
			- Nette\Database\Connection
			- Symfony\Component\Console\Application

Εάν δεν χρησιμοποιείτε τον πίνακα $container->getParameters(), μπορείτε να απενεργοποιήσετε την εξαγωγή παραμέτρων. Επιπλέον, μπορείτε να εξάγετε μόνο τα tags μέσω των οποίων λαμβάνετε υπηρεσίες με τη μέθοδο $container->findByTag(...). Εάν δεν καλείτε καθόλου τη μέθοδο, μπορείτε να απενεργοποιήσετε εντελώς την εξαγωγή tags χρησιμοποιώντας false.

Μπορείτε να μειώσετε σημαντικά τα μεταδεδομένα για autowiring αναφέροντας τις κλάσεις που χρησιμοποιείτε ως παράμετρο της μεθόδου $container->getByType(). Και πάλι, εάν δεν καλείτε καθόλου τη μέθοδο (ή μόνο στο bootstrap για να λάβετε το Nette\Application\Application), μπορείτε να απενεργοποιήσετε εντελώς την εξαγωγή χρησιμοποιώντας false.

Επεκτάσεις

Καταχώρηση πρόσθετων επεκτάσεων DI. Με αυτόν τον τρόπο προσθέτουμε, για παράδειγμα, την επέκταση DI Dibi\Bridges\Nette\DibiExtension22 με το όνομα dibi

extensions:
	dibi: Dibi\Bridges\Nette\DibiExtension22

Στη συνέχεια, τη διαμορφώνουμε στην ενότητα dibi:

dibi:
	host: localhost

Ως επέκταση μπορεί να προστεθεί και μια κλάση που έχει παραμέτρους:

extensions:
	application: Nette\Bridges\ApplicationDI\ApplicationExtension(%debugMode%, %appDir%, %tempDir%/cache)

Εισαγωγή αρχείων

Μπορούμε να εισάγουμε άλλα αρχεία διαμόρφωσης στην ενότητα includes:

includes:
	- parameters.php
	- services.neon
	- presenters.neon

Το όνομα parameters.php δεν είναι τυπογραφικό λάθος, η διαμόρφωση μπορεί επίσης να γραφτεί σε ένα αρχείο PHP, το οποίο την επιστρέφει ως πίνακα:

<?php
return [
	'database' => [
		'main' => [
			'dsn' => 'sqlite::memory:',
		],
	],
];

Εάν εμφανιστούν στοιχεία με τα ίδια κλειδιά σε αρχεία διαμόρφωσης, θα αντικατασταθούν ή, στην περίπτωση πινάκων, θα συγχωνευθούν. Το αρχείο που εισάγεται αργότερα έχει υψηλότερη προτεραιότητα από το προηγούμενο. Το αρχείο στο οποίο αναφέρεται η ενότητα includes έχει υψηλότερη προτεραιότητα από τα αρχεία που εισάγονται σε αυτό.

Αναζήτηση

Η αυτόματη προσθήκη υπηρεσιών στο DI container διευκολύνει εξαιρετικά την εργασία. Το Nette προσθέτει αυτόματα presenters στο container, αλλά μπορεί εύκολα να προσθέσει και οποιεσδήποτε άλλες κλάσεις.

Αρκεί να αναφέρετε σε ποιους καταλόγους (και υποκαταλόγους) πρέπει να αναζητήσει κλάσεις:

search:
	-	in: %appDir%/Forms
	-	in: %appDir%/Model

Συνήθως, όμως, δεν θέλουμε να προσθέσουμε απολύτως όλες τις κλάσεις και τα interfaces, γι' αυτό μπορούμε να τα φιλτράρουμε:

search:
	-	in: %appDir%/Forms

		# φιλτράρισμα με βάση το όνομα αρχείου (string|string[])
		files:
			- *Factory.php

		# φιλτράρισμα με βάση το όνομα κλάσης (string|string[])
		classes:
			- *Factory

Ή μπορούμε να επιλέξουμε κλάσεις που κληρονομούν ή υλοποιούν τουλάχιστον μία από τις αναφερόμενες κλάσεις:

search:
	-	in: %appDir%
		extends:
			- App\*Form
		implements:
			- App\*FormInterface

Μπορούν επίσης να οριστούν κανόνες εξαίρεσης, δηλ. μάσκες ονόματος κλάσης ή κληρονομικοί πρόγονοι, που εάν ταιριάζουν, η υπηρεσία δεν προστίθεται στο DI container:

search:
	-	in: %appDir%
		exclude:
			files: ...
			classes: ...
			extends: ...
			implements: ...

Σε όλες τις υπηρεσίες μπορούν να οριστούν tags:

search:
	-	in: %appDir%
		tags: ...

Συγχώνευση

Εάν εμφανιστούν στοιχεία με τα ίδια κλειδιά σε περισσότερα αρχεία διαμόρφωσης, θα αντικατασταθούν ή, στην περίπτωση πινάκων, θα συγχωνευθούν. Το αρχείο που εισάγεται αργότερα έχει υψηλότερη προτεραιότητα από το προηγούμενο.

config1.neon config2.neon αποτέλεσμα
items:
	- 1
	- 2
items:
	- 3
items:
	- 1
	- 2
	- 3

Στους πίνακες, η συγχώνευση μπορεί να αποτραπεί αναφέροντας ένα θαυμαστικό μετά το όνομα του κλειδιού:

config1.neon config2.neon αποτέλεσμα
items:
	- 1
	- 2
items!:
	- 3
items:
	- 3
έκδοση: 3.x