Πεδία διαχείρισης Filament
Το δωρεάν πακέτο rankbeam/laravel-seo-filament προσθέτει πλήρη ενότητα SEO σε κάθε φόρμα πόρου Filament — δύο γραμμές ανά πόρο. Υποστηρίζει Filament 4.x και 5.x (Livewire 3 και 4). Η επεξεργασία μεταδεδομένων είναι δωρεάν· το Pro προσθέτει σαρώσεις και τη βαθμολογία που φαίνεται στο παρακάτω παράδειγμα.
Προαπαιτούμενα
Χρησιμοποιήστε υπάρχοντα πίνακα Filament 4 ή 5 και μοντέλο με το trait HasSEO του core. Ολοκληρώστε τη Γρήγορη εκκίνηση του core, μαζί με τις μεταναστεύσεις και την απόδοση, πριν προσθέσετε τον επεξεργαστή.
Εγκατάσταση
composer require rankbeam/laravel-seo-filamentΤο μοντέλο του πόρου πρέπει να χρησιμοποιεί το trait HasSEO του core.
Προσθέστε την ενότητα σε πόρο
use Rankbeam\Seo\Filament\Concerns\HasSEOFields;
class PostResource extends Resource
{
use HasSEOFields; // 1
public static function form(Schema $schema): Schema
{
return $schema->components([
TextInput::make('title'),
// ...
static::seoSection(), // 2
]);
}
}Ελέγξτε το αποθηκευμένο αποτέλεσμα
Ανοίξτε υπάρχουσα εγγραφή. Πληκτρολογήστε περιγραφή SEO, αποθηκεύστε και φορτώστε ξανά τη φόρμα. Η τιμή πρέπει να διατηρείται, η προεπισκόπηση να την εμφανίζει και η πηγή της να αναφέρει Χειροκίνητα. Ελέγξτε το <head> της αποδομένης σελίδας για να επιβεβαιώσετε ότι η ίδια περιγραφή φτάνει στους επισκέπτες σας.

Παράδειγμα από την επίδειξη Merchant. Τα πεδία χρησιμοποιούν το θέμα του πίνακά σας· τα διαθέσιμα στοιχεία ελέγχου και τα όρια χαρακτήρων εξαρτώνται από την εγκατεστημένη έκδοση και τις ρυθμίσεις σας.
Η ενότητα περιλαμβάνει:
- Τίτλο και περιγραφή με ζωντανούς μετρητές χαρακτήρων — το όριο προέρχεται από την πολιτική μήκους του core για τη γραφή που πληκτρολογείται (60/160 για λατινικό κείμενο, περίπου 30/80 για CJK, με καταμέτρηση σε γραφήματα).
- Λέξεις-κλειδιά εστίασης — πεδίο ετικετών. Πληκτρολογείτε απλές λέξεις-κλειδιά· αποθηκεύονται στη δομημένη μορφή
[{keyword, is_primary}]του core (η πρώτη είναι κύρια), ώστε ταgetPrimaryKeyword()καιSEODataνα τις διαβάζουν αμετάβλητες. Ενεργοποιήστε τοseo.keywords.enabledώστε η εντολήseo:auditκαι η σάρωση Pro να επισημαίνουν σελίδες που ακόμη δεν έχουν λέξη-κλειδί (ανενεργό από προεπιλογή — ένας διακόπτης, δείτε Ρυθμίσεις). - Κανονική διεύθυνση URL (κενό = αυτόματη, με αφαίρεση του query string).
- Επιλογή Robots (κενό = προεπιλογή ιστοτόπου).
- Μεταφόρτωση εικόνας κοινωνικής κοινοποίησης (og:image / twitter:image), που αποθηκεύεται στον προεπιλεγμένο δίσκο του Filament, στο
seo/. - Προεπισκόπηση αποσπάσματος αναζήτησης που ακολουθεί ζωντανά την αλυσίδα εναλλακτικών τιμών του resolver όσο πληκτρολογείτε.
- Ενδείξεις πηγής — για κάθε πεδίο, ποιο επίπεδο του resolver παρήγαγε την τελική τιμή: Χειροκίνητα, Εναλλακτικά από το περιεχόμενο, Προεπιλογή τύπου μοντέλου, Καθολική προεπιλογή, Ρυθμίσεις ιστότοπου ή Προκύπτει από το URL.
Περιορισμός πεδίων
static::seoSection(['title', 'description'])Δέχεται οποιοδήποτε υποσύνολο των title, description, focus_keywords, canonical, robots, og_image.
Χωρίς το trait, το SEOFields::make(?array $only) επιστρέφει την ίδια ενότητα απευθείας.
Πώς αποθηκεύονται οι τιμές
Η ενότητα συνδέεται με ομάδα κατάστασης seo_meta και αποθηκεύει μέσω της σχέσης seoMeta() του core (ενημέρωση ή δημιουργία) — χωρίς στήλες στους δικούς σας πίνακες, και οι τιμές γίνονται αμέσως επίπεδο 6 (ρητές) στον resolver.
Πολλές γλώσσες
Το core κρατά μία γραμμή seo_meta ανά (μοντέλο, γλώσσα). Δώστε τις γλώσσες στις οποίες δημοσιεύεται μια σελίδα και η ενότητα αποδίδει μία καρτέλα ανά γλώσσα (Filament 1.9):
static::seoSection(locales: ['en', 'it', 'ja']);
// or, without the trait
SEOFields::make(locales: ['en', 'it', 'ja']);Ή μία φορά για κάθε πόρο, στις ρυθμίσεις του πακέτου:
php artisan vendor:publish --tag=seo-filament-config// config/seo-filament.php
'locales' => ['en', 'it', 'ja'],Κάθε καρτέλα επεξεργάζεται τη δική της γραμμή και έχει δικούς της:
- μετρητές — την πολιτική μήκους για τη γραφή της γλώσσας, ώστε ένας κενός ιαπωνικός τίτλος να εμφανίζει
0 / 30ενώ η αγγλική καρτέλα εμφανίζει0 / 60στην ίδια σελίδα· - προεπισκόπηση (SERP / κοινωνική κάρτα) από τις επιλυμένες τιμές αυτής της γλώσσας·
- ενδείξεις εναλλακτικών τιμών που περιγράφουν τη γραμμή αυτής της γλώσσας·
- σήμα με το πλήθος συμπληρωμένων πεδίων σε αυτή την έκδοση, ώστε οι κενές μεταφράσεις να ξεχωρίζουν.
Η καρτέλα φέρει το όνομα της γλώσσας στη γλώσσα του πίνακα (Italiano / Italian) όταν είναι φορτωμένο το ext-intl, αλλιώς τον κωδικό. Όλες οι καρτέλες επικυρώνονται και αποθηκεύονται μαζί· μια γλώσσα στην οποία δεν συμπληρώθηκε τίποτε δεν λαμβάνει ποτέ κενή γραμμή κράτησης θέσης.
Προσαρμοσμένες συνδέσεις κατάστασης φόρμας
Με πολλές γλώσσες, η διαδρομή κατάστασης είναι seo_meta.{locale}.title· με μία παραμένει seo_meta.title. Χρησιμοποιήστε την αντίστοιχη διαδρομή στις προσαρμοσμένες ενέργειες φόρμας.

Επίδειξη Merchant, 9 Σεπτεμβρίου 2026, με locales: ['en', 'it', 'ja']. Η κενή ιαπωνική καρτέλα χρησιμοποιεί δικούς της μετρητές. Ο αγγλικός τίτλος εδώ προέρχεται από την εναλλακτική τιμή περιεχομένου του μοντέλου επίδειξης: η προσθήκη καρτέλας γλώσσας δεν μεταφράζει το περιεχόμενό σας. Η βαθμολογία Pro πάνω από τα πεδία είναι το αποτέλεσμα της τελευταίας σάρωσης της εγγραφής, όχι ξεχωριστή βαθμολογία για κάθε καρτέλα γλώσσας.
Με πρόσθετο μεταφράσεων
Με το lara-zeus/spatie-translatable 1.x σε Filament 4 ή 2.x σε Filament 5, χρησιμοποιήστε τους προσαρμογείς σελίδων Rankbeam για Edit και Create. Αντικαταστήστε μόνο τα imports των traits σελίδας· κρατήστε τα traits πόρου/λίστας του πρόσθετου, το πρόσθετο πίνακα και την ενέργεια LocaleSwitcher:
// In your EditPost page:
use Rankbeam\Seo\Filament\Resources\Pages\EditRecord\Concerns\Translatable;
// In your CreatePost page (a separate file):
use Rankbeam\Seo\Filament\Resources\Pages\CreateRecord\Concerns\Translatable;Κάθε σελίδα εξακολουθεί να δηλώνει use Translatable; μέσα στην κλάση της. Το πρόσθετο παραμένει προαιρετική εξάρτηση εφαρμογής. Χρησιμοποιήστε την πιο πρόσφατη διορθωμένη έκδοσή του· το τοπικό fixture ενσωμάτωσης καλύπτει πρόσθετο 1.0.4 / Filament 4.13.1 και πρόσθετο 2.0.1 / Filament 5.8.1.
Η εναλλαγή κρατά στον επεξεργαστή το μη αποθηκευμένο περιεχόμενο της γονικής εγγραφής, τα μεταδεδομένα SEO και τα προσχέδια δομημένων δεδομένων. Η αποθήκευση επικυρώνει κάθε γλώσσα που επισκεφθήκατε και τις αποθηκεύει μαζί σε συναλλαγή βάσης δεδομένων. Ένα σφάλμα επικύρωσης ανοίγει τη γλώσσα που χρειάζεται προσοχή. Τα μεταφορτωμένα αρχεία αποθηκεύονται κατά την αποθήκευση· η αποχώρηση ή επαναφόρτωση της σελίδας απορρίπτει μη αποθηκευμένα προσχέδια. Η αποθήκευση προσχεδίου δεν μεταφράζει για εσάς περιεχόμενο που λείπει.
Οι προσαρμογείς διατηρούν τα συνηθισμένα hooks πριν/μετά και τους μετασχηματιστές δεδομένων φόρμας. Αν η σελίδα σας παρακάμπτει τα handleRecordCreation(), handleRecordUpdate(), callHook() ή μεθόδους συναλλαγής, ενσωματώστε τη συμπεριφορά του προσαρμογέα σε αυτή την προσαρμογή και δοκιμάστε τη ροή αποθήκευσης. Οι συναλλαγές βάσης δεδομένων δεν αναιρούν εγγραφές στο σύστημα αρχείων· οι εφαρμογές πρέπει να διατηρούν τον συνηθισμένο καθαρισμό ορφανών αρχείων.
Για προσαρμοσμένα ζωντανά πεδία κειμένου στο Livewire 3, προτιμήστε ->live() ή ->live(onBlur: true) αντί για ρητό debounce: το ρητό debounce καθυστερεί την τοπική κατάσταση μοντέλου και μπορεί να χάσει τις τελευταίες πληκτρολογήσεις σε γρήγορη εναλλαγή γλώσσας. Τα πεδία τίτλου και περιγραφής του Rankbeam χρησιμοποιούν το προεπιλεγμένο debounce αιτημάτων.
Τα upstream traits σελίδας από μόνα τους ξαναγεμίζουν τις φόρμες κατά την εναλλαγή. Το Rankbeam προστατεύει από τις ακούσιες εγγραφές μεταδεδομένων τους, αλλά αυτά τα traits δεν διατηρούν προσχέδια SEO· μεταφέρετε τις σελίδες Edit/Create στους προσαρμογείς. Οι ρητές καρτέλες locales: παραμένουν κοινός επεξεργαστής και προηγούνται του επιλογέα γλώσσας σελίδας.
Χωρίς ρητή λίστα γλωσσών ή γλώσσα σελίδας, η ενότητα επεξεργάζεται τη γλώσσα εφαρμογής.
Δομημένα δεδομένα (schema.org)
Μια προαιρετική ενότητα Δομημένα δεδομένα επιτρέπει στους συντάκτες να προσθέτουν schema JSON-LD για εμπλουτισμένα αποτελέσματα χωρίς να γράφουν κώδικα. Προσθέστε τη δίπλα στην ενότητα SEO:
public static function form(Schema $schema): Schema
{
return $schema->components([
// ... your fields ...
static::seoSection(),
static::seoSchemaSection(), // optional
]);
}(ή απευθείας SEOSchemaFields::make(), χωρίς το trait).
Γράφει στη στήλη seo_meta.schema_jsonld του core — την ίδια τιμή που αποδίδει ο renderer schema — και είναι μόνο σύνδεση περιβάλλοντος εργασίας: κάθε έγγραφο παράγεται από builder schema του core και επικυρώνεται από τον SchemaValidator του core πριν μπορέσει να αποθηκευτεί. Δεν προσθέτει δική της λογική schema.
Η ενότητα προσφέρει:
- Αυτόματο breadcrumb — ένας διακόπτης, ως πρώτη δυνατότητα χωρίς ρυθμίσεις. Παράγει
BreadcrumbListαπό την αλυσίδα γονικών εγγραφών μέσωBreadcrumbSchema::fromModelAncestors(). Τίποτε να συμπληρώσετε — ακολουθεί τους προγόνους του μοντέλου. - Μπλοκ schema — επαναλαμβανόμενα πεδία. Κάθε τμήμα είναι είτε FAQ (ζεύγη ερώτησης / απάντησης →
FAQPage) είτε Product (όνομα, περιγραφή, εικόνα, επωνυμία, SKU, τιμή και νόμισμα, διαθεσιμότητα →Product), κατασκευασμένο από τους buildersFAQSchema/ProductSchemaτου core.
Επικύρωση
Τμήμα που θα παρήγαγε κακοσχηματισμένο JSON-LD απορρίπτεται κατά την αποθήκευση με το μήνυμα του επικυρωτή core — π.χ. εγγραφή FAQ χωρίς απάντηση ή Product χωρίς εικόνα ή προσφορά (αυτός ο builder απαιτεί αυτά τα πεδία· δεν είναι πλήρης δήλωση των απαιτήσεων Google για κάθε λειτουργία αναζήτησης Product). Τμήματα που μένουν κενά απλώς αγνοούνται.
Τι αποθηκεύει
Το schema_jsonld κρατά τα κατασκευασμένα έγγραφα: ένα αντικείμενο όταν υπάρχει ένα, πίνακα JSON όταν υπάρχουν πολλά (πρώτα η διαδρομή πλοήγησης, μετά τα τμήματά σας). Και τα δύο είναι έγκυρο JSON-LD και αποδίδονται αμετάβλητα μέσω @seo / renderSchema().
Schema που δεν διαχειρίζεται
Schema που γράψατε σε κώδικα και δεν μπορεί να αναπαραστήσει αυτός ο επεξεργαστής — χειροποίητο @graph, ασυνήθιστο @type ή Product με πεδία που δεν εκθέτει η φόρμα (κριτικές, βαθμολογίες, GTIN/MPN) — διατηρείται αυτούσιο. Το άνοιγμα και η αποθήκευση της φόρμας δεν το αντικαθιστούν ποτέ.
Αντιμετώπιση προβλημάτων
- Το αποθηκευμένο πεδίο λείπει από τη σελίδα: επιβεβαιώστε ότι το πρότυπό σας αποδίδει
@seo($model)για την ίδια εγγραφή και γλώσσα. - Ένα πεδίο χρησιμοποιεί ακόμη εναλλακτική τιμή: ελέγξτε αν έχει αποθηκευμένη παράκαμψη στην ενεργή γλώσσα. Οι ενδείξεις πηγής προσδιορίζουν το επιλυμένο επίπεδο.
- Λείπει καρτέλα γλώσσας: ελέγξτε το ρητό όρισμα
locales:, τις ρυθμίσεις πακέτου και τυχόν επιλογέα μετάφρασης σελίδας. Η προτεραιότητά τους περιγράφεται παραπάνω.
Δοκιμή προσαρμοσμένου πίνακα σε Testbench
Αν εκκινείτε το Filament μέσα σε orchestra/testbench, καταχωρίστε το SupportServiceProvider του Filament πριν από το LivewireServiceProvider — το Filament επανασυνδέει το DataStore του Livewire, και η λανθασμένη σειρά προκαλεί αποτυχία κάθε δοκιμής Livewire με ViewErrorBag::put(): ... null given. Οι πραγματικές εφαρμογές δεν επηρεάζονται (η ανακάλυψη πακέτων ταξινομεί σωστά τους providers).