Een veelvoorkomend verzoek, vooral voor degenen die aangepaste berichttypen hebben gemaakt, zoals 'Nieuws' of 'Evenementen', is om een link toe te voegen aan de archiefpagina van hun berichttype in hun navigatiemenu. Momenteel kan dit echter alleen worden gedaan door de archief-URL van het posttype handmatig in te voeren. Behalve dat het nogal onelegant is, heeft deze oplossing een paar nadelen: het wordt niet altijd als 'actueel' weergegeven, als u uw permalink-structuur wijzigt, kan het de koppeling verbreken, het handmatig toevoegen van de URL's is vervelend en de link wordt niet weergegeven als ' current 'in een bericht van dat berichttype.
In deze zelfstudie laat ik je zien hoe je een plug-in maakt die een meta-box maakt op je Uiterlijk -> Menupagina waarmee je posttypearchearchiekoppelingen kunt toevoegen. Deze schakels lijden niet aan de hierboven genoemde nadelen.
Deze plug-in heet 'My Post Type Archive Links' en maakt daartoe eerst een map genaamd mijn post-type-archive-koppelingen onder jouw / Wp-content / plugins / map en binnen die een bestand maken mijn post-type-archive-links.php. Dit bestand is het belangrijkste plugin-bestand. We gaan het in een klas verpakken - dit is eenvoudig, dus we hoeven ons geen zorgen te maken dat onze functienamen botsen met WordPress of andere plug-ins: we moeten gewoon ervoor zorgen dat onze klassennaam uniek is. Voeg het volgende toe aan mijn post-type-archive-links.php
Menupagina om posttype archiefkoppelingen toe te voegen Auteur: Stephen Harris Auteur URI: http://profiles.wordpress.org/users/stephenh1988/ * / class My_Post_Type_Archive_Link // Alles zal hier naartoe gaan My_Post_Type_Archive_Link :: load (); ?>
Alles in deze tutorial zal in die klas zitten.
Wanneer het plugin-bestand is geladen, wordt de klassemethode geactiveerd laden()
. Deze methode is verantwoordelijk voor het toevoegen van acties en filters aan verschillende WordPress-hooks. We zullen ze in de volgende stappen doornemen, maar het biedt ook een nuttige samenvatting. Voeg de volgende methode toe aan onze klas:
openbare functie laden () // Hook-functie om de metabox toe te voegen aan de menupagina add_action ('admin_init', array (__ CLASS __, 'add_meta_box')); // Javascript voor de metabox add_action ('admin_enqueue_scripts', array (__ CLASS __, 'metabox_script')); // Ajax callback om een menu-item te maken en toe te voegen aan het menu add_action ('wp_ajax_my-add-post-type-archive-links', array (__CLASS__, 'ajax_add_post_type')); // Wijs menu-item toe de juiste url add_filter ('wp_setup_nav_menu_item', array (__ CLASS __, 'setup_archive_item')); // Maak berichttype archieflink 'current' add_filter ('wp_nav_menu_objects', array (__ CLASS __, 'maybe_make_current'));
Laten we samenvatten wat elk van deze onderdelen aan het doen zijn:
admin_enqueue_scripts
haak om ons JavaScript-bestand in te huren. Ons JavaScript, wanneer op 'toevoegen aan menu' wordt geklikt, activeert een AJAX-verzoek.huidige menubestanddeel
'is toegevoegd aan de juiste berichttypekoppeling.Eerst definiëren we onze add_meta_box
methode, die gewoon de WordPress-functie aanroept add_meta_box ()
. De details van deze functie zijn al vele malen eerder behandeld, maar als u het niet zeker weet, kunt u dit lezen op de Codex-pagina's.
openbare functie add_meta_box () add_meta_box ('post-type-archieven', __ ('Berichttypen', 'my-post-type-archive-links'), array (__ CLASS __, 'metabox'), 'nav-menus' , 'side', 'laag');
Vervolgens definiëren we de meta-box callback-functie die verantwoordelijk is voor het weergeven van de binnenkant van de metabox:
openbare functie metabox () global $ nav_menu_selected_id; // Ontvang berichttypen $ post_types = get_post_types (array ('public' => true, '_ builtin' => false), 'object');?>
value =""name =" add-post-type-menu-item "/>
Deze methode krijgt gewoon alle openbare aangepaste berichttypen met get_post_types ()
en loopt er vervolgens doorheen om een lijst met selectievakjes te maken. Elk selectievakje heeft de naam van het berichttype als waarde. In de volgende stap voegen we een JavaScript toe dat wordt geactiveerd wanneer een gebruiker op de knop 'Toevoegen aan menu' klikt.
We willen alleen ons JavaScript in de wacht slepen op de pagina Uiterlijk -> Menubeheerder. We hebben de admin_enqueue_scripts
hook die alleen op admin-pagina's vuurt en de haak van de pagina als argument doorgeeft. De haak voor de verschijning -> menupagina is nav-menus.php. Na het inruilen van ons script gebruiken we wp_localize_script
om de nonce beschikbaar te maken in onze JavaScript. We nemen deze op in het AJAX-verzoek om te helpen verifiëren dat de actie was bedoeld.
openbare functie metabox_script ($ hook) if ('nav-menus.php'! = $ hook) return; // Op uiterlijk> Menupagina, script in wachtrij: wp_enqueue_script ('my-post-type-archive-links_metabox', plugins_url ('/ metabox.js', __FILE__), array ('jQuery')); // Voeg nonce variabele toe wp_localize_script ('my-post-type-archive-links_metabox', 'MyPostTypeArchiveLinks', array ('nonce' => wp_create_nonce ('my-add-post-type-archive-links')));
In de vorige stap kreeg de knop 'Toevoegen aan menu' de ID submit-na-type-archieven
. We gebruiken nu jQuery om die knop te targeten en, wanneer erop wordt geklikt, een AJAX-aanvraag te verzenden om het menu-item te maken en toe te voegen aan het menu. Het volgende is het enige deel van deze zelfstudie die buiten onze klas leeft. Het zou moeten gaan in een bestand genaamd metabox.js, in onze plug-in map.
jQuery (document) .ready (functie ($) $ ('# submit-post-type-archieven'). klik (functie (gebeurtenis) event.preventDefault (); / * Schakel selectievakjes in * / var postTypes = [ ]; $ ('# post-type-archief-checklist li: checked'). each (function () postTypes.push ($ (this) .val ());); / * Stuur aangevinkte berichttypes met onze actie en nonce * / $ .post (ajaxurl, action: "my-add-post-type-archive-links", posttypearchive_nonce: MyPostTypeArchiveLinks.nonce, post_types: postTypes, / * AJAX retourneert html om toe te voegen aan het menu * / functie (antwoord) $ ('# -menu om te bewerken'). toevoegen (antwoord););));
Let op de URL waarnaar we het verzoek sturen: ajaxurl
. We hebben het nergens gedefinieerd. Het is een globale variabele ingesteld door WordPress alleen aan de admin kant die verwijst naar de pagina die WordPress gebruikt om AJAX-verzoeken af te handelen. Wanneer op de knop Verzenden wordt geklikt, worden de namen van de aangevinkte berichttypen, een unieke actie en nonce allemaal naar deze URL verzonden. Wanneer WordPress de aanvraag ontvangt, activeert het de wp_ajax_my-add-na-type-archive-koppelingen
haak. De nonce is een veiligheidsmaatregel om te helpen verifiëren dat de actie was bedoeld.
We definiëren nu de AJAX-callback-functie ajax_add_post_type
.
public function ajax_add_post_type () if (! current_user_can ('edit_theme_options')) die ('- 1'); check_ajax_referer ('my-add-post-type-archive-links', 'posttypearchive_nonce'); vereist ABSATH. 'Wp-admin / includes / nav-menu.php'; if (empty ($ _ POST ['post_types'])) exit; // Maak menu-items en winkel-ID's in matrix $ item_ids = array (); foreach ((array) $ _POST ['post_types'] als $ post_type) $ post_type_obj = get_post_type_object ($ post_type); als (! $ post_type_obj) doorgaan; $ menu_item_data = array ('menu-item-title' => esc_attr ($ post_type_obj-> labels-> naam), 'menu-item-type' => 'post_type_archive', 'menu-item-object' => esc_attr ( $ post_type), 'menu-item-url' => get_post_type_archive_link ($ post_type)); // Verzamel de id's van de items. $ item_ids [] = wp_update_nav_menu_item (0, 0, $ menu_item_data); // Als hier een foutdiemas was als (is_wp_error ($ item_ids)) doodgaat ('- 1'); // Stel menu-items in voor ea ((array) $ item_ids als $ menu_item_id) $ menu_obj = get_post ($ menu_item_id); if (! empty ($ menu_obj-> ID)) $ menu_obj = wp_setup_nav_menu_item ($ menu_obj); $ menu_obj-> label = $ menu_obj-> titel; // laat niet zien "(in behandeling)" in ajax-toegevoegde items $ menu_items [] = $ menu_obj; // Hiermee wordt de HTML-code teruggestuurd naar het menu als (! Empty ($ menu_items)) $ args = array ('after' => ", 'before' =>", 'link_after' => ", 'link_before' => ", 'walker' => nieuwe Walker_Nav_Menu_Edit); echo walk_nav_menu_tree ($ menu_items, 0, (object) $ args); // Vergeet tenslotte niet om exit te verlaten;
Laten we dit terugbellen beetje bij beetje doornemen. Eerst controleren we de permissies van de gebruiker, controleren we de nonce en laden we de nav-menu.php pagina (we hebben enkele functies nodig).
if (! current_user_can ('edit_theme_options')) sterven ('- 1'); check_ajax_referer ( 'my-add-na-type-archive-verbindingen', 'posttypearchive_nonce'); vereist ABSATH. 'Wp-admin / includes / nav-menu.php'; if (empty ($ _ POST ['post_types'])) exit;
Vervolgens maken we een menu-item voor elk geselecteerd berichttype. We controleren eerst of het berichttype dat we hebben ontvangen bestaat door de geretourneerde waarde te controleren get_post_type_object ()
. We kunnen de archieflink met de functie verkrijgen get_post_type_archive_link ()
Menu-items zijn in feite posts van het berichttype 'nav_menu_item
'met ingebouwde post-meta, inclusief velden die betrekking hebben op'url
','type
'en'voorwerp
'. De artikelen 'type
'is normaal'gewoonte
','post_type
'of'taxonomie
'- maar we zullen de waarde ervan bepalen'post_type_archive
'. De artikelen 'voorwerp
'meta-waarde wordt normaal alleen gebruikt voor items van'post_type
'of'taxonomie
'type en verwijst naar het type of de taxonomie waarnaar de link verwijst. We gebruiken dit om het berichttype van de archieflink op te slaan.
// Maak menu-items en winkel-ID's in matrix $ item_ids = array (); foreach ((array) $ _POST ['post_types'] als $ post_type) $ post_type_obj = get_post_type_object ($ post_type); als (! $ post_type_obj) doorgaan; $ menu_item_data = array ('menu-item-title' => esc_attr ($ post_type_obj-> labels-> naam), 'menu-item-type' => 'post_type_archive', 'menu-item-object' => esc_attr ( $ post_type), 'menu-item-url' => get_post_type_archive_link ($ post_type)); // Verzamel de id's van de items. $ item_ids [] = wp_update_nav_menu_item (0, 0, $ menu_item_data); // Als hier een foutdiemas was als (is_wp_error ($ item_ids)) doodgaat ('- 1');
Vervolgens genereren we eenvoudig de HTML die aan het menu wordt toegevoegd. Wij gebruiken de $ item_ids
array om een reeks menu-items te krijgen en deze door te geven aan een WordPress walker-klasse om het harde werk voor ons te doen.
// Stel menu-items in voor ea ((array) $ item_ids als $ menu_item_id) $ menu_obj = get_post ($ menu_item_id); if (! empty ($ menu_obj-> ID)) $ menu_obj = wp_setup_nav_menu_item ($ menu_obj); $ menu_obj-> label = $ menu_obj-> titel; // laat niet zien "(in behandeling)" in ajax-toegevoegde items $ menu_items [] = $ menu_obj; // Hiermee wordt de HTML-code teruggestuurd naar het menu als (! Empty ($ menu_items)) $ args = array ('after' => ", 'before' =>", 'link_after' => ", 'link_before' => ", 'walker' => nieuwe Walker_Nav_Menu_Edit); echo walk_nav_menu_tree ($ menu_items, 0, (object) $ args); // Vergeet tenslotte niet om exit te verlaten;
Helaas, vanwege een bug bij WordPress, als het type van je item niet 'taxonomie
','gewoonte
'of'post_type
'de URL wordt verwijderd. Om dit tegen te gaan, wanneer een 'post_type_archive
'link wordt gebruikt in een menu, we voegen de URL handmatig opnieuw toe. Dit zorgt er ook voor dat de archieflink 'up-to-date' is (voor het geval uw permalink-structuur is gewijzigd).
openbare functie setup_archive_item ($ menu_item) if ($ menu_item-> type! = 'post_type_archive') return $ menu_item; $ post_type = $ menu_item-> object; $ menu_item-> url = get_post_type_archive_link ($ post_type); return $ menu_item;
Ten slotte moeten we het item 'actueel' maken wanneer we op de juiste pagina staan. Ik wil dat de archieflink van het posttype wordt gemarkeerd als actueel als we op die archiefpagina staan of dat we één bericht van dat type bekijken. Om dit te doen controleer ik:
is_post_type_archive ()
is_singular ()
Om het item actueel te houden, hoeven we alleen maar toe te voegen huidige menubestanddeel
naar de klassen van het item die zijn opgeslagen in $ Item-> klassen
. We moeten dan de ouders doorlopen in het menu en de klassen toevoegen current_item_parent
en current_item_ancestor
. Laten we elk bit afzonderlijk bekijken:
We doorlopen elk van de items in het menu:
openbare functie maybe_make_current ($ items) foreach ($ items als $ item) // Dit is waar we het item controleren return $ items;
Als het artikel niet van 'post_type_archive
'of, als het zo is, maar we willen niet dat het' actueel 'wordt, gaan we gewoon door naar het volgende item. Bedenk dat voor onze archiefkoppelingen het berichttype is opgeslagen als het object van het item. Dus binnen de foreach
lus:
if ('post_type_archive'! = $ item-> type) ga verder; $ post_type = $ item-> object; als (! is_post_type_archive ($ post_type) &&! is_singular ($ post_type)) verdergaat;
Als we het wel actueel willen maken, geven we het de juiste klas en nemen dan de ouders mee in het menu. Het bovenliggende item van een menu-item wordt opgeslagen als post-meta met metasleutel _menu_item_menu_item_parent
.
// Maak item actueel $ item-> current = true; $ item-> classes [] = 'current-menu-item'; // Krijg de voorouders van het menu-item: $ _anc_id = (int) $ item-> db_id; $ Active_ancestor_item_ids = array (); while (($ _anc_id = get_post_meta ($ _anc_id, '_menu_item_menu_item_parent', true)) &&! in_array ($ _anc_id, $ active_ancestor_item_ids)) $ active_ancestor_item_ids [] = $ _anc_id;
Vervolgens doorlopen we de menu-items en geven de ouders en voorouders van het 'huidige' item de juiste klassen.
// Loop door de items en geef voorouders en ouders de juiste class foreach ($ items als $ key => $ parent_item) $ classes = (array) $ parent_item-> classes; // Als het menu-item het bovenliggende element is ($ parent_item-> db_id == $ item-> menu_item_parent) $ classes [] = 'current-menu-parent'; $ items [$ key] -> current_item_parent = true; // Als het menu-item een voorouder is als (in_array (intval ($ parent_item-> db_id), $ active_ancestor_item_ids)) $ classes [] = 'current-menu-ancestor'; $ items [$ key] -> current_item_ancestor = true; $ items [$ key] -> classes = array_unique ($ classes);
Die functie samenvoegen:
openbare functie maybe_make_current ($ items) foreach ($ items als $ item) if ('post_type_archive'! = $ item-> type) ga verder; $ post_type = $ item-> object; als (! is_post_type_archive ($ post_type) &&! is_singular ($ post_type)) verdergaat; // Maak item actueel $ item-> current = true; $ item-> classes [] = 'current-menu-item'; // Krijg de voorouders van het menu-item: $ _anc_id = (int) $ item-> db_id; $ Active_ancestor_item_ids = array (); while (($ _anc_id = get_post_meta ($ _anc_id, '_menu_item_menu_item_parent', true)) &&! in_array ($ _anc_id, $ active_ancestor_item_ids)) $ active_ancestor_item_ids [] = $ _anc_id; // Loop door voorouders en geef ze 'voorouder' of 'bovenliggende' class foreach ($ items als $ key => $ parent_item) $ classes = (array) $ parent_item-> klassen; // Als het menu-item het bovenliggende element is ($ parent_item-> db_id == $ item-> menu_item_parent) $ classes [] = 'current-menu-parent'; $ items [$ key] -> current_item_parent = true; // Als het menu-item een voorouder is als (in_array (intval ($ parent_item-> db_id), $ active_ancestor_item_ids)) $ classes [] = 'current-menu-ancestor'; $ items [$ key] -> current_item_ancestor = true; $ items [$ key] -> classes = array_unique ($ classes); return $ items;
Het enige dat overblijft is om naar de admin-pagina van uw plug-in te gaan en de plug-in te activeren.
Er is altijd ruimte voor verbetering. Met een beetje jQuery kunt u bijvoorbeeld een koppeling 'Alles selecteren' onder de selectievakjes toevoegen of een 'laad' -symbool weergeven terwijl de AJAX bezig is met verwerken. Nu is deze plug-in niet de eenvoudigste oplossing, maar hij werkt goed en vermijdt de valkuilen van het toevoegen van een aangepaste link. De bovenstaande plug-in in zijn geheel is te vinden op mijn GitHub. Als u opmerkingen of suggesties heeft, kunt u een reactie achterlaten of contact met mij opnemen via Twitter.