Δημιουργία συνδέσμων URL

Η δημιουργία συνδέσμων στο Nette είναι τόσο απλή όσο το να δείχνεις με το δάχτυλο. Απλά στοχεύστε και το framework θα κάνει όλη τη δουλειά για εσάς. Θα δείξουμε:

  • πώς να δημιουργείτε συνδέσμους σε templates και αλλού
  • πώς να διακρίνετε έναν σύνδεσμο προς την τρέχουσα σελίδα
  • τι να κάνετε με τους μη έγκυρους συνδέσμους

Χάρη στην αμφίδρομη δρομολόγηση, δεν θα χρειαστεί ποτέ να γράψετε σκληρά κωδικοποιημένες διευθύνσεις URL της εφαρμογής σας σε templates ή κώδικα, οι οποίες μπορεί να αλλάξουν αργότερα, ή να τις συνθέσετε πολύπλοκα. Στον σύνδεσμο, αρκεί να καθορίσετε τον presenter και την action, να περάσετε τυχόν παραμέτρους και το framework θα δημιουργήσει το URL μόνο του. Στην πραγματικότητα, είναι πολύ παρόμοιο με την κλήση μιας συνάρτησης. Αυτό θα σας αρέσει.

Στο Πρότυπο του Presenter

Τις περισσότερες φορές δημιουργούμε συνδέσμους σε templates και ένα εξαιρετικό βοήθημα είναι το attribute n:href:

<a n:href="Product:show">λεπτομέρεια</a>

Παρατηρήστε ότι αντί για το HTML attribute href, χρησιμοποιήσαμε το n:attribute n:href. Η τιμή του δεν είναι ένα URL, όπως θα ήταν στην περίπτωση του attribute href, αλλά το όνομα του presenter και της action.

Το κλικ σε έναν σύνδεσμο είναι, απλοποιημένα, κάτι σαν την κλήση της μεθόδου ProductPresenter::renderShow(). Και αν έχει παραμέτρους στην υπογραφή της, μπορούμε να την καλέσουμε με ορίσματα:

<a n:href="Product:show $product->id, $product->slug">λεπτομέρεια προϊόντος</a>

Είναι επίσης δυνατό να περάσετε ονομασμένες παραμέτρους. Ο παρακάτω σύνδεσμος περνάει την παράμετρο lang με την τιμή cs:

<a n:href="Product:show $product->id, lang: cs">λεπτομέρεια προϊόντος</a>

Αν η μέθοδος ProductPresenter::renderShow() δεν έχει το $lang στην υπογραφή της, μπορεί να λάβει την τιμή της παραμέτρου χρησιμοποιώντας το $lang = $this->getParameter('lang') ή από την property.

Αν οι παράμετροι είναι αποθηκευμένες σε έναν πίνακα, μπορούν να επεκταθούν με τον τελεστή ... (στο Latte 2.x με τον τελεστή (expand)):

{var $args = [$product->id, lang => cs]}
<a n:href="Product:show ...$args">λεπτομέρεια προϊόντος</a>

Στους συνδέσμους, μεταβιβάζονται επίσης αυτόματα οι λεγόμενες persistent παράμετροι.

Το attribute n:href είναι πολύ χρήσιμο για τις ετικέτες HTML <a>. Αν θέλουμε να εμφανίσουμε έναν σύνδεσμο αλλού, για παράδειγμα σε κείμενο, χρησιμοποιούμε το {link}:

Η διεύθυνση είναι: {link Home:default}

Στον Κώδικα

Για τη δημιουργία ενός συνδέσμου στον presenter, χρησιμοποιείται η μέθοδος link():

$url = $this->link('Product:show', $product->id);

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

$url = $this->link('Product:show', [$product->id, 'lang' => 'cs']);

Οι σύνδεσμοι μπορούν επίσης να δημιουργηθούν χωρίς presenter, γι' αυτό υπάρχει το LinkGenerator και η μέθοδός του link().

Σύνδεσμοι προς Presenter

Αν ο στόχος του συνδέσμου είναι ένας presenter και μια action, έχει αυτή τη σύνταξη:

[//] [[[[:]module:]presenter:]action | this] [#fragment]

Η μορφή υποστηρίζεται από όλες τις ετικέτες Latte και όλες τις μεθόδους του presenter που λειτουργούν με συνδέσμους, δηλαδή n:href, {link}, {plink}, link(), lazyLink(), isLinkCurrent(), redirect(), redirectPermanent(), forward(), canonicalize() και επίσης το LinkGenerator. Έτσι, ακόμα κι αν χρησιμοποιείται το n:href στα παραδείγματα, θα μπορούσε να είναι οποιαδήποτε από τις συναρτήσεις.

Η βασική μορφή είναι επομένως Presenter:action:

<a n:href="Home:default">αρχική σελίδα</a>

Αν συνδέουμε σε μια action του τρέχοντος presenter, μπορούμε να παραλείψουμε το όνομά του:

<a n:href="default">αρχική σελίδα</a>

Αν ο στόχος είναι η action default, μπορούμε να την παραλείψουμε, αλλά η άνω και κάτω τελεία πρέπει να παραμείνει:

<a n:href="Home:">αρχική σελίδα</a>

Οι σύνδεσμοι μπορούν επίσης να οδηγούν σε άλλα modules. Εδώ, οι σύνδεσμοι διακρίνονται σε σχετικούς προς ένα ένθετο sub-module, ή απόλυτους. Η αρχή είναι ανάλογη με τις διαδρομές στο δίσκο, μόνο που αντί για κάθετες χρησιμοποιούνται άνω και κάτω τελείες. Ας υποθέσουμε ότι ο τρέχων presenter είναι μέρος του module Front, τότε γράφουμε:

<a n:href="Shop:Product:show">σύνδεσμος προς Front:Shop:Product:show</a>
<a n:href=":Admin:Product:show">σύνδεσμος προς Admin:Product:show</a>

Μια ειδική περίπτωση είναι ένας σύνδεσμος προς τον εαυτό του, όπου καθορίζουμε το this ως στόχο.

<a n:href="this">ανανέωση</a>

Μπορούμε να συνδέσουμε σε ένα συγκεκριμένο τμήμα της σελίδας μέσω ενός λεγόμενου fragment μετά το σύμβολο δίεσης #:

<a n:href="Home:#main">σύνδεσμος προς Home:default και fragment #main</a>

Απόλυτες Διαδρομές

Οι σύνδεσμοι που δημιουργούνται χρησιμοποιώντας το link() ή το n:href είναι πάντα απόλυτες διαδρομές (δηλαδή ξεκινούν με το σύμβολο /), αλλά όχι απόλυτες διευθύνσεις URL με πρωτόκολλο και domain όπως https://domain.

Για να δημιουργήσετε μια απόλυτη διεύθυνση URL, προσθέστε δύο κάθετες στην αρχή (π.χ. n:href="//Home:"). Ή μπορείτε να αλλάξετε τον presenter ώστε να δημιουργεί μόνο απόλυτους συνδέσμους ορίζοντας $this->absoluteUrls = true.

Σύνδεσμος προς την Τρέχουσα Σελίδα

Ο στόχος this δημιουργεί έναν σύνδεσμο προς την τρέχουσα σελίδα:

<a n:href="this">ανανέωση</a>

Ταυτόχρονα, μεταβιβάζονται όλες οι παράμετροι που καθορίζονται στην υπογραφή της μεθόδου action<Action>() ή render<View>(), αν η action<Action>() δεν έχει οριστεί. Έτσι, αν βρισκόμαστε στη σελίδα Product:show και id: 123, ο σύνδεσμος προς το this θα μεταβιβάσει και αυτή την παράμετρο.

Φυσικά, είναι δυνατό να καθορίσετε τις παραμέτρους απευθείας:

<a n:href="this refresh: 1">ανανέωση</a>

Η συνάρτηση isLinkCurrent() ελέγχει εάν ο στόχος του συνδέσμου είναι ο ίδιος με την τρέχουσα σελίδα. Αυτό μπορεί να χρησιμοποιηθεί, για παράδειγμα, σε ένα template για τη διάκριση συνδέσμων κ.λπ.

Οι παράμετροι είναι ίδιες με αυτές της μεθόδου link(), αλλά επιπλέον είναι δυνατό να καθορίσετε έναν χαρακτήρα μπαλαντέρ * αντί για μια συγκεκριμένη action, ο οποίος σημαίνει οποιαδήποτε action του συγκεκριμένου presenter.

{if !isLinkCurrent('Admin:login')}
	<a n:href="Admin:login">Σύνδεση</a>
{/if}

<li n:class="isLinkCurrent('Product:*') ? active">
	<a n:href="Product:">...</a>
</li>

Σε συνδυασμό με το n:href σε ένα στοιχείο, μπορεί να χρησιμοποιηθεί μια συντομευμένη μορφή:

<a n:class="isLinkCurrent() ? active" n:href="Home:">...</a>

Ο χαρακτήρας μπαλαντέρ * μπορεί να χρησιμοποιηθεί μόνο αντί για την action, όχι για τον presenter.

Για να ελέγξουμε εάν βρισκόμαστε σε ένα συγκεκριμένο module ή το sub-module του, χρησιμοποιούμε τη μέθοδο isModuleCurrent(moduleName).

<li n:class="isModuleCurrent('Forum:Users') ? active">
	<a n:href="Product:">...</a>
</li>

Σύνδεσμοι προς Σήμα

Ο στόχος ενός συνδέσμου δεν χρειάζεται να είναι μόνο ένας presenter και μια action, αλλά μπορεί επίσης να είναι ένα signal (καλούν τη μέθοδο handle<Signal>()). Τότε η σύνταξη είναι η εξής:

[//] [sub-component:]signal! [#fragment]

Το signal διακρίνεται λοιπόν από το θαυμαστικό:

<a n:href="click!">signal</a>

Μπορείτε επίσης να δημιουργήσετε έναν σύνδεσμο προς το signal ενός sub-component (ή sub-sub-component):

<a n:href="componentName:click!">signal</a>

Σύνδεσμοι σε Component

Επειδή τα components είναι ανεξάρτητες, επαναχρησιμοποιήσιμες μονάδες που δεν θα πρέπει να έχουν καμία σύνδεση με τους γύρω presenters, οι σύνδεσμοι λειτουργούν λίγο διαφορετικά εδώ. Το attribute Latte n:href και η ετικέτα {link} καθώς και οι μέθοδοι του component όπως το link() και άλλες θεωρούν τον στόχο του συνδέσμου πάντα ως το όνομα του signal. Επομένως, δεν είναι καν απαραίτητο να συμπεριλάβετε το θαυμαστικό:

<a n:href="click">signal, όχι action</a>

Αν θέλαμε να συνδέσουμε σε presenters στο template του component, θα χρησιμοποιούσαμε την ετικέτα {plink}:

<a href={plink Home:default}>αρχική</a>

ή στον κώδικα

$this->getPresenter()->link('Home:default')

Ψευδώνυμα

Μερικές φορές μπορεί να είναι χρήσιμο να αντιστοιχίσετε ένα εύκολα απομνημονεύσιμο ψευδώνυμο σε ένα ζεύγος Presenter:action. Για παράδειγμα, να ονομάσετε την αρχική σελίδα Front:Home:default απλά ως home ή το Admin:Dashboard:default ως admin.

Τα ψευδώνυμα ορίζονται στη διαμόρφωση κάτω από το κλειδί application › aliases:

application:
    aliases:
        home: Front:Home:default
        admin: Admin:Dashboard:default
        sign: Front:Sign:in

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

<a n:href="@admin">διαχείριση</a>

Υποστηρίζονται επίσης σε όλες τις μεθόδους που λειτουργούν με συνδέσμους, όπως το redirect() και παρόμοιες.

Μη Έγκυροι Σύνδεσμοι

Μπορεί να συμβεί να δημιουργήσουμε έναν μη έγκυρο σύνδεσμο – είτε επειδή οδηγεί σε έναν ανύπαρκτο presenter, είτε επειδή περνάει περισσότερες παραμέτρους από όσες δέχεται η μέθοδος προορισμού στην υπογραφή της, είτε όταν δεν μπορεί να δημιουργηθεί URL για την action προορισμού. Ο τρόπος χειρισμού των μη έγκυρων συνδέσμων καθορίζεται από τη στατική μεταβλητή Presenter::$invalidLinkMode. Αυτή μπορεί να πάρει έναν συνδυασμό αυτών των τιμών (σταθερών):

  • Presenter::InvalidLinkSilent – σιωπηλή λειτουργία, το σύμβολο # επιστρέφεται ως URL
  • Presenter::InvalidLinkWarning – δημιουργείται μια προειδοποίηση E_USER_WARNING, η οποία θα καταγραφεί στη λειτουργία παραγωγής, αλλά δεν θα προκαλέσει διακοπή της εκτέλεσης του σεναρίου
  • Presenter::InvalidLinkTextual – οπτική προειδοποίηση, εμφανίζει το σφάλμα απευθείας στον σύνδεσμο
  • Presenter::InvalidLinkException – δημιουργείται η εξαίρεση InvalidLinkException

Η προεπιλεγμένη ρύθμιση είναι InvalidLinkWarning στη λειτουργία παραγωγής και InvalidLinkWarning | InvalidLinkTextual στη λειτουργία ανάπτυξης. Το InvalidLinkWarning στο περιβάλλον παραγωγής δεν προκαλεί διακοπή του σεναρίου, αλλά η προειδοποίηση θα καταγραφεί. Στο περιβάλλον ανάπτυξης, το Tracy το συλλαμβάνει και εμφανίζει ένα bluescreen. Το InvalidLinkTextual λειτουργεί επιστρέφοντας ένα μήνυμα σφάλματος ως URL, το οποίο ξεκινά με τους χαρακτήρες #error:. Για να κάνουμε τέτοιους συνδέσμους ορατούς με την πρώτη ματιά, προσθέτουμε στο CSS μας:

a[href^="#error:"] {
	background: red;
	color: white;
}

Αν δεν θέλουμε να δημιουργούνται προειδοποιήσεις στο περιβάλλον ανάπτυξης, μπορούμε να ορίσουμε τη σιωπηλή λειτουργία απευθείας στη διαμόρφωση.

application:
	silentLinks: true

LinkGenerator

Πώς να δημιουργήσετε συνδέσμους με παρόμοια άνεση όπως η μέθοδος link(), αλλά χωρίς την παρουσία ενός presenter; Γι' αυτό υπάρχει το Nette\Application\LinkGenerator.

Το LinkGenerator είναι μια υπηρεσία που μπορείτε να ζητήσετε να σας περάσει μέσω του constructor και στη συνέχεια να δημιουργήσετε συνδέσμους χρησιμοποιώντας τη μέθοδό του link().

Υπάρχει μια διαφορά σε σύγκριση με τους presenters. Το LinkGenerator δημιουργεί όλους τους συνδέσμους απευθείας ως απόλυτες διευθύνσεις URL. Επιπλέον, δεν υπάρχει “τρέχων presenter”, οπότε δεν μπορείτε να καθορίσετε μόνο το όνομα της action ως στόχο link('default') ή να καθορίσετε σχετικές διαδρομές προς τα modules.

Οι μη έγκυροι σύνδεσμοι δημιουργούν πάντα την εξαίρεση Nette\Application\UI\InvalidLinkException.

έκδοση: 4.0