{"id":233394,"date":"2023-02-13T17:13:00","date_gmt":"2023-02-13T14:13:00","guid":{"rendered":"https:\/\/wordpress.mediadoma.com\/?p=233394"},"modified":"2022-11-10T23:27:43","modified_gmt":"2022-11-10T20:27:43","slug":"samouczek-wordpress-niestandardowe-menu-dla-postow-lub-stron-na-pasku-bocznym","status":"publish","type":"post","link":"https:\/\/wordpress.mediadoma.com\/pl\/samouczek-wordpress-niestandardowe-menu-dla-postow-lub-stron-na-pasku-bocznym\/","title":{"rendered":"Samouczek WordPress: Niestandardowe menu dla post\u00f3w lub stron na pasku bocznym"},"content":{"rendered":"\n<p>Ten post jest dla Ciebie, kt\u00f3ry zarz\u0105dza witryn\u0105 WordPress, kt\u00f3ra ma du\u017co tre\u015bci, prawdopodobnie wiele stron uporz\u0105dkowanych hierarchicznie i chcesz mie\u0107 lepsz\u0105 nawigacj\u0119 poza menu g\u0142\u00f3wnym. Aby u\u0142atwi\u0107 poruszanie si\u0119 po witrynie, ogromnie pomo\u017ce niestandardowe menu zwi\u0105zane z aktualnym postem. Problem z umieszczeniem wid\u017cetu menu na pasku bocznym (lub gdziekolwiek chcesz) polega na tym, \u017ce pasek boczny jest powszechny. W tym po\u015bcie dowiemy si\u0119, jak wy\u015bwietli\u0107 dodatkowe niestandardowe menu na pasku bocznym, umo\u017cliwiaj\u0105c postom, stronom lub niestandardowym typom post\u00f3w wyb\u00f3r menu.<\/p>\n<p>Dodaj poni\u017cszy kod w motywie <code>functions.php<\/code>lub w kodzie wtyczki.<\/p>\n<h2>Zezwalaj postom lub stronom na wyb\u00f3r menu<\/h2>\n<p>Tworzenie menu w WordPressie jest \u0142atwe i mo\u017cesz u\u017cy\u0107 wid\u017cetu Menu, aby wy\u015bwietli\u0107 menu na pasku bocznym. Problem polega na tym, \u017ce pasek boczny jest globalny i wsz\u0119dzie b\u0119dzie wy\u015bwietlane to samo menu. Co zrobi\u0107, je\u015bli chcesz, aby okre\u015blone menu by\u0142y wy\u015bwietlane na okre\u015blonych stronach? Dowiesz si\u0119 r\u00f3wnie\u017c, jak upewni\u0107 si\u0119, \u017ce wybrane menu jest dziedziczone przez strony podrz\u0119dne. W ten spos\u00f3b wystarczy wybra\u0107 menu na stronie nadrz\u0119dnej. Wszelkie podstrony r\u00f3wnie\u017c poka\u017c\u0105 to samo menu bez konieczno\u015bci ich edycji.<\/p>\n<h3>Dodanie metabox do wyboru menu<\/h3>\n<p>Pierwszym krokiem jest stworzenie metaboxu na posty lub strony, gdzie mamy mo\u017cliwo\u015b\u0107 wyboru menu. U\u017cywamy funkcji <code>add_meta_box()<\/code>i decydujemy, dla jakich typ\u00f3w post\u00f3w chcemy j\u0105 pokaza\u0107.<\/p>\n<pre><code>add_action('add_meta_boxes', function() {\n    add_meta_box('metabox-sidebar-menu', __('Sidebar Menu', 'txtdomain'), 'awp_sidebar_menu_metabox_callback', ['post', 'page']);\n});<\/code><\/pre>\n<p>Dostosuj powy\u017cszy kod do tytu\u0142u i typ\u00f3w post\u00f3w, kt\u00f3re chcesz. Powy\u017cszy przyk\u0142ad doda metabox zar\u00f3wno do post\u00f3w, jak i stron. Trzecim parametrem, kt\u00f3ry nazwa\u0142em <code>awp_sidebar_menu_metabox_callback<\/code>, jest funkcja odpowiedzialna za renderowanie zawarto\u015bci metaboksu. Zdefiniujmy to dalej. Oto, co musimy zrobi\u0107 w naszym metaboksie:<\/p>\n<pre><code>function awp_sidebar_menu_metabox_callback($post) {\n    \/\/ Get all menus\n\u00a0\n    \/\/ Get the current saved menu, if set\n\u00a0\n    \/\/ Output HTML with a select showing all menus, and mark the currently saved one as selected\n}<\/code><\/pre>\n<p>Tablic\u0119 ze wszystkimi zapisanymi menu w WordPressie mo\u017cemy uzyska\u0107 za pomoc\u0105 <code>wp_get_nav_menus()<\/code>. Je\u015bli chodzi o pobieranie aktualnie wybranego menu, przechowujemy wybrane menu jako meta postu <code>awp_sidebar_menu<\/code>(nazywaj je, jak chcesz), a my po prostu pobieramy warto\u015b\u0107 na podstawie pr\u0105du <code>$post<\/code>dostarczonego nam w funkcji metabox. Zapiszemy identyfikatory menu, poniewa\u017c to wszystko, czego potrzebujemy, aby wy\u015bwietli\u0107 menu. A potem wypisujemy HTML dla zaznaczenia, kt\u00f3re przechodzi przez menu. Wynik HTML metaboksu zale\u017cy od Ciebie, poni\u017cej jest przyk\u0142ad. Do\u0142\u0105czy\u0142em r\u00f3wnie\u017c funkcjonalno\u015b\u0107 nonce dla bezpiecze\u0144stwa.<\/p>\n<pre><code>function awp_sidebar_menu_metabox_callback($post) {\n    \/\/ Get all menus\n    $menus = wp_get_nav_menus();\n\u00a0\n    \/\/ Get the current saved menu, if set\n    $current_selected = get_post_meta($post-&gt;ID, 'awp_sidebar_menu', true);\n\u00a0\n    \/\/ Output HTML with a select showing all menus, and mark the currently saved one as selected\n    wp_nonce_field('awp_sidebar_menu_metabox_nonce', 'awp_sidebar_menu_nonce');\n    ?&gt;&lt;div class=\"awp-metabox-item\"&gt;\n        &lt;div class=\"awp-metabox-label\"&gt;&lt;label&gt;&lt;?php _e('Choose menu', 'txtdomain'); ?&gt;&lt;\/label&gt;&lt;\/div&gt;\n        &lt;div class=\"awp-metabox-input\"&gt;&lt;?php\n        if (empty($menus)) {\n            echo '&lt;p&gt;'. __('No menus created.', 'txtdomain'). '&lt;\/p&gt;';\n        } else { ?&gt;\n            &lt;select name=\"awp-sidebar-menu\" id=\"awp-sidebar-menu\"&gt;\n                &lt;?php \n                echo '&lt;option value=\"\"&gt;'. __('Choose menu', 'txtdomain'). '&lt;\/option&gt;';\n                foreach ($menus as $menu) { \n                    echo '&lt;option value=\"'. $menu-&gt;term_id. '\" '.selected($current_selected, $menu-&gt;term_id).'&gt;'.$menu-&gt;name.'&lt;\/option&gt;';\n                } ?&gt;\n            &lt;\/select&gt;\n        &lt;?php } ?&gt;\n        &lt;\/div&gt;\n    &lt;\/div&gt;&lt;?php\n}<\/code><\/pre>\n<p>W wyniku HTML drukuj\u0119 etykiet\u0119. Je\u015bli w WordPressie nie ma \u017cadnych zapisanych menu, po prostu wy\u015bwietli akapit. W przeciwnym razie generowany jest wyb\u00f3r z identyfikatorami menu jako warto\u015bciami i nazwami menu jako etykiet\u0105. Dodaj\u0119 r\u00f3wnie\u017c pusty wyb\u00f3r, aby posty nie wy\u015bwietla\u0142y menu. Korzystam z funkcji pomocniczej WordPressa <code>[selected](https:\/\/developer.wordpress.org\/reference\/functions\/selected\/)()<\/code>do zaznaczania aktualnie zapisanej opcji jako wybranej.<\/p>\n<p>Je\u015bli edytujesz post lub stron\u0119, na dole powinno pojawi\u0107 si\u0119 metabox z zaznaczeniem. Wspania\u0142y! Jednak w tym momencie nie zapisze wyboru menu podczas zapisywania posta. To kolejny krok.<\/p>\n<h3>Zapisywanie wyboru menu<\/h3>\n<p>U\u017cywamy haka <code>save_post<\/code>do tworzenia funkcji, kt\u00f3ra zapisuje ka\u017cdy wyb\u00f3r, kt\u00f3ry dodali\u015bmy w naszym metaboksie. Podpi\u0119cie <code>save_post<\/code>jest uruchamiane za ka\u017cdym razem, gdy post jest zapisywany lub aktualizowany. Najpierw sprawdzimy warto\u015b\u0107 jednorazow\u0105 (je\u015bli nie masz pewno\u015bci, co to s\u0105, sprawd\u017a ten <a href=\"https:\/\/codex.wordpress.org\/WordPress_Nonces\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">przewodnik WordPressa o warto\u015bciach jednorazowych<\/a> ). Nast\u0119pnie dwukrotnie sprawdzamy, czy u\u017cytkownik mo\u017ce aktualizowa\u0107 posty, i aktualizujemy nasz\u0105 meta postu o wyb\u00f3r.<\/p>\n<pre><code>add_action('save_post', function($post_id) {\n    if (!isset($_POST['awp_sidebar_menu_nonce']) || !wp_verify_nonce($_POST['awp_sidebar_menu_nonce'], 'awp_sidebar_menu_metabox_nonce')) {\n        return;\n    }\n\u00a0\n    if (!current_user_can('edit_post', $post_id)) {\n        return;\n    }\n\u00a0\n    update_post_meta($post_id, 'awp_sidebar_menu', $_POST['awp-sidebar-menu']);\n});<\/code><\/pre>\n<p>Teraz, gdy aktualizujesz posty, zapisze r\u00f3wnie\u017c Tw\u00f3j wyb\u00f3r menu.<\/p>\n<p>I to tyle, je\u015bli chodzi o cz\u0119\u015b\u0107 dotycz\u0105c\u0105 wyboru post\u00f3w. Nast\u0119pnym krokiem jest w rzeczywisto\u015bci wy\u015bwietlenie menu, je\u015bli zosta\u0142o wybrane menu.<\/p>\n<h3>Wyb\u00f3r pozycji dla niestandardowego menu<\/h3>\n<p>Dodaj\u0119 dane wyj\u015bciowe na pasku bocznym, ale mo\u017cesz je wyprowadzi\u0107 w dowolnym miejscu w szablonach motywu. Potrzebujemy tylko predefiniowanego haka lub zdefiniowania w\u0142asnego. Jako przyk\u0142ad dodaj\u0119 niestandardowy zaczep na g\u00f3rze paska bocznego, abym m\u00f3g\u0142 utworzy\u0107 pod\u0142\u0105czon\u0105 do niego funkcj\u0119.<\/p>\n<p>Mo\u017cesz po prostu zadzwoni\u0107 <code>wp_nav_menu()<\/code>bezpo\u015brednio w szablonie, ale zamiast tego zalecam utworzenie niestandardowego hooka, poniewa\u017c dodamy sporo kodu i mo\u017ce si\u0119 to wydawa\u0107 nieuporz\u0105dkowane.<\/p>\n<p>W moim motywie, kt\u00f3ry edytuj\u0119 <code>sidebar.php<\/code>i tu\u017c przed <code>dynamic_sidebar()<\/code>wywo\u0142aniem paska bocznego (gdzie dodawane s\u0105 wid\u017cety), dodaj\u0119 m\u00f3j niestandardowy hak z <code>do_action()<\/code>podan\u0105 nazw\u0105. Mo\u017cesz go nazwa\u0107, jak chcesz, ale musi by\u0107 unikalny w WordPressie. Wi\u0119c przynajmniej poprzed\u017a to czym\u015b wyj\u0105tkowym dla Ciebie.<\/p>\n<pre><code>&lt;aside class=\"sidebar\"&gt;\n    &lt;?php \n    do_action('awp_before_sidebar');\n    dynamic_sidebar('left-sidebar'); \n    ?&gt;\n&lt;\/aside&gt;<\/code><\/pre>\n<h3>Renderowanie menu<\/h3>\n<p>Teraz mo\u017cemy wr\u00f3ci\u0107 do <code>functions.php<\/code>, zdefiniowa\u0107 pod\u0142\u0105czon\u0105 funkcj\u0119, <code>awp_before_sidebar<\/code>a jej wynik zostanie wy\u015bwietlony na pasku bocznym przed wid\u017cetami. Funkcja u\u017cyje <a href=\"https:\/\/codex.wordpress.org\/Conditional_Tags#A_Single_Page.2C_a_Single_Post.2C_an_Attachment_or_Any_Other_Custom_Post_Type\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">tag\u00f3w warunkowych WordPress,<\/a> aby sprawdzi\u0107, czy aktualnie wy\u015bwietlamy pojedynczy post lub stron\u0119. A je\u015bli tak, pobior\u0119 nasz\u0105 meta postu. Je\u015bli ustawiono meta posta, wyprowadzamy menu, wywo\u0142uj\u0105c <code>[wp_nav_menu](https:\/\/developer.wordpress.org\/reference\/functions\/wp_nav_menu\/)()<\/code>i podaj\u0105c identyfikator zapisanego menu jako jego <code>menu<\/code>parametr.<\/p>\n<pre><code>add_action('awp_before_sidebar', function() {\n    if (is_singular()) {\n        global $post;\n\u00a0\n        $sidebar_menu = get_post_meta($post-&gt;ID, 'awp_sidebar_menu', true);\n    }\n\u00a0\n    if (!empty($sidebar_menu)) {\n        ?&gt;&lt;section class=\"widget awp-sidebar-menu\"&gt;\n            &lt;?php wp_nav_menu(['menu' =&gt; $sidebar_menu]); ?&gt;\n        &lt;\/section&gt;&lt;?php\n    }\n});<\/code><\/pre>\n<p>Powiniene\u015b dostosowa\u0107 kod HTML wok\u00f3\u0142 menu, aby pasowa\u0142 do reszty tre\u015bci. W powy\u017cszym kodzie zawijam menu w ten sam kod HTML, w kt\u00f3rym s\u0105 zawini\u0119te wszystkie wid\u017cety na pasku bocznym, dzi\u0119ki czemu styl wid\u017cetu motywu ma zastosowanie do naszego niestandardowego menu.<\/p>\n<p>Ot\u00f3\u017c \u200b\u200bto! Za ka\u017cdym razem, gdy wybierzesz menu w po\u015bcie lub na stronie, menu zostanie wy\u015bwietlone nad paskiem bocznym podczas przegl\u0105dania tego posta lub strony.<\/p>\n<p>Mo\u017cemy jednak p\u00f3j\u015b\u0107 o krok dalej. Je\u015bli chcesz, aby strony dla dzieci pokazywa\u0142y to samo menu paska bocznego ustawione u kt\u00f3regokolwiek z rodzic\u00f3w, czytaj dalej.<\/p>\n<h2>Zezwalaj stronom podrz\u0119dnym na dziedziczenie menu rodzica<\/h2>\n<p>Ta dodatkowa funkcja ma sens, je\u015bli masz wiele stron w hierarchii lub niestandardowy typ posta z w\u0142\u0105czon\u0105 hierarchi\u0105. Edytowanie ka\u017cdej strony podrz\u0119dnej i wybieranie tego samego menu by\u0142oby zbyt k\u0142opotliwe. W takim przypadku lepiej by\u0142oby wybra\u0107 menu na stronie nadrz\u0119dnej i automatycznie pozwoli\u0107 wszystkim podstronom \u201edziedziczy\u0107&quot; ten wyb\u00f3r menu. Je\u015bli jakakolwiek podstrona wybierze inne menu, to menu zostanie wy\u015bwietlone raz zamiast \u201eodziedziczonego&#8221;.<\/p>\n<p>Wewn\u0105trz naszej funkcji podpi\u0119tej do <code>awp_before_sidebar<\/code>, dodamy fragment kodu, wewn\u0105trz sprawdzania, czy ogl\u0105damy pojedynczy post lub stron\u0119:<\/p>\n<pre><code>        ...\n        $sidebar_menu = get_post_meta($post-&gt;ID, 'awp_sidebar_menu', true);\n        if (!empty($sidebar_menu)) {\n            $parents = get_post_ancestors($post-&gt;ID);\n            if (!empty($parents)) {\n                \/\/ go step by step up the parents tree\n                for ($i = 0; $i &lt; count($parents); $i++) {\n                    $sidebar_menu = get_post_meta($post-&gt;ID, 'awp_sidebar_menu', true);\n                    if (!empty($sidebar_menu)) {\n                        break;\n                    }\n                }\n            }\n        }\n    }\n\u00a0\n    if (!empty($sidebar_menu)) {\n        ...<\/code><\/pre>\n<p>Co robi powy\u017cszy kod, je\u015bli nie znaleziono menu na bie\u017c\u0105cej stronie, pobiera wszystkich rodzic\u00f3w za pomoc\u0105 <code>[get_post_ancestors](https:\/\/developer.wordpress.org\/reference\/functions\/get_post_ancestors\/)()<\/code>. Ta funkcja zwraca tablic\u0119 nadrz\u0119dnych identyfikator\u00f3w post\u00f3w posortowanych najpierw wed\u0142ug najbli\u017cszego rodzica. Je\u015bli strona nie ma rodzic\u00f3w (na przyk\u0142ad je\u015bli jest to post), zwracana jest pusta tablica. A je\u015bli s\u0105 jacy\u015b rodzice, przechodzimy przez ka\u017cdego rodzica po kolei i sprawdzamy, czy ustawili nasz\u0105 meta postu. Je\u015bli taki zostanie znaleziony, wyrwiemy si\u0119 z przechodzenia przez rodzic\u00f3w i <code>$sidebar_menu<\/code>zostanie ustawiony, a menu zostanie wy\u015bwietlone p\u00f3\u017aniej za pomoc\u0105 <code>wp_nav_menu()<\/code>.<\/p>\n<p>I to tyle, je\u015bli chodzi o funkcjonalno\u015b\u0107 \u201edziedziczenia&#8221;!<\/p>\n<p><div id=\"PostUnique_PostSource\" style=\"padding-top: 50px\">\u0179r\u00f3d\u0142o nagrywania:  <a target=\"_blank\" rel=\"noopener nofollow\" href=\"\/\/awhitepixel.com\" class=\"external external_icon\">awhitepixel.com<\/a><\/div><\/p>\n","protected":false},"excerpt":{"rendered":"<p>W tym po\u015bcie dowiemy si\u0119, jak wy\u015bwietla\u0107 niestandardowe menu na pasku bocznym (lub w innym miejscu), umo\u017cliwiaj\u0105c postom lub stronom wyb\u00f3r menu.<\/p>\n","protected":false},"author":1,"featured_media":224072,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":"","_wp_rev_ctl_limit":""},"categories":[721,721,919,919,1110,805,805,836,836,845,929,929,845,866,866],"tags":[1169],"class_list":{"0":"post-233394","1":"post","2":"type-post","3":"status-publish","4":"format-standard","5":"has-post-thumbnail","6":"hentry","7":"category-deweloper","9":"category-inny","11":"category-n-a","12":"category-php-7","14":"category-przewodnik-dla-poczatkujacych","16":"category-samouczki","17":"category-tematy","20":"category-wordpress-7","22":"tag-affiai-pl"},"_links":{"self":[{"href":"https:\/\/wordpress.mediadoma.com\/pl\/wp-json\/wp\/v2\/posts\/233394","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wordpress.mediadoma.com\/pl\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/wordpress.mediadoma.com\/pl\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/pl\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/pl\/wp-json\/wp\/v2\/comments?post=233394"}],"version-history":[{"count":0,"href":"https:\/\/wordpress.mediadoma.com\/pl\/wp-json\/wp\/v2\/posts\/233394\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/pl\/wp-json\/wp\/v2\/media\/224072"}],"wp:attachment":[{"href":"https:\/\/wordpress.mediadoma.com\/pl\/wp-json\/wp\/v2\/media?parent=233394"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/pl\/wp-json\/wp\/v2\/categories?post=233394"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/pl\/wp-json\/wp\/v2\/tags?post=233394"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}