{"id":233668,"date":"2023-02-19T17:49:00","date_gmt":"2023-02-19T14:49:00","guid":{"rendered":"https:\/\/wordpress.mediadoma.com\/?p=233668"},"modified":"2022-11-11T08:44:55","modified_gmt":"2022-11-11T05:44:55","slug":"utworz-niestandardowy-blok-gutenberga-czesc-9-dynamiczne-bloki-i-renderowanie-php","status":"publish","type":"post","link":"https:\/\/wordpress.mediadoma.com\/pl\/utworz-niestandardowy-blok-gutenberga-czesc-9-dynamiczne-bloki-i-renderowanie-php\/","title":{"rendered":"Utw\u00f3rz niestandardowy blok Gutenberga &#8211; cz\u0119\u015b\u0107 9: Dynamiczne bloki i renderowanie PHP"},"content":{"rendered":"\n<p>Do tej pory renderowali\u015bmy dane wyj\u015bciowe bloku w JavaScript. Jednak w przypadku dynamicznej zawarto\u015bci, takiej jak ostatnie posty lub wy\u015bwietlanie posta, musimy renderowa\u0107 wyj\u015bcie bloku w PHP. W tym po\u015bcie dowiemy si\u0119 jak i dlaczego.<\/p>\n<h2>Dlaczego musimy inaczej obs\u0142ugiwa\u0107 bloki dynamiczne?<\/h2>\n<p>Niekt\u00f3re przyk\u0142ady s\u0105 oczywiste; blok wy\u015bwietlaj\u0105cy najnowsze posty w kategorii jest dynamiczny, poniewa\u017c posty b\u0119d\u0105 si\u0119 zmienia\u0107 w czasie. Nie wybierasz post\u00f3w w bloku; zamiast tego prawdopodobnie b\u0119dziesz mie\u0107 ustawienia wyboru kategorii, jakie informacje maj\u0105 by\u0107 wy\u015bwietlane dla ka\u017cdego posta, liczba post\u00f3w, liczba kolumn i tak dalej. Za ka\u017cdym razem, gdy WordPress \u0142aduje post z tym blokiem, musi w tym czasie zapyta\u0107 WordPressa o najnowsze posty. Wy\u015bwietlenie tego samego posta miesi\u0105c p\u00f3\u017aniej mo\u017ce da\u0107 inne wyniki, nawet je\u015bli post z samym blokiem nie zosta\u0142 zaktualizowany.<\/p>\n<p>Jednak konieczno\u015b\u0107 stosowania blok\u00f3w dynamicznych czasami nie jest a\u017c tak oczywista. Mo\u017cesz sobie wyobrazi\u0107, \u017ce polecany blok post\u00f3w, w kt\u00f3rym wybierasz jeden konkretny post do wy\u015bwietlenia, niekoniecznie jest dynamiczny. Ale mo\u017ce by\u0107 \u2013 i powinno by\u0107. Pami\u0119taj, \u017ce wybrany post mo\u017ce w dowolnym momencie zaktualizowa\u0107 tytu\u0142, fragment lub wyr\u00f3\u017cniony obraz \u2013 i powinno to by\u0107 odzwierciedlone w blokach, kt\u00f3re zawieraj\u0105 ten post.<\/p>\n<p>Aby utworzy\u0107 niedynamiczny blok do wy\u015bwietlania pojedynczego posta, musisz zapisa\u0107 identyfikator posta, jego adres URL, adres URL polecanego obrazu, ci\u0105g fragmentu lub cokolwiek, czego potrzebujesz, aby wy\u015bwietli\u0107 podgl\u0105d posta, w atrybutach bloku. I w tym tkwi problem. Je\u015bli zaktualizujesz polecany obraz wybranego posta, post z blokiem polecanego posta nie zaktualizuje automatycznie swoich atrybut\u00f3w. Pozostanie zapisany z adresem URL starego polecanego obrazu. Dopiero gdy edytujesz post z blokiem i upewnisz si\u0119, \u017ce ponownie zapisze atrybuty ze zaktualizowanymi informacjami, blok wy\u015bwietli poprawne zaktualizowane informacje.<\/p>\n<p>Tak wi\u0119c zawsze, gdy mamy do czynienia z tre\u015bciami dynamicznymi \u2013 postami, kategoriami lub czymkolwiek, co mo\u017ce si\u0119 z czasem zmieni\u0107 \u2013 mamy do czynienia z blokami dynamicznymi. A w przypadku blok\u00f3w dynamicznych musimy u\u017cy\u0107 PHP \u2013 kodu po stronie serwera \u2013 do renderowania naszego bloku, aby zapewni\u0107, \u017ce b\u0119dzie pobiera\u0142 zaktualizowane informacje za ka\u017cdym razem, gdy jest renderowany.<\/p>\n<h2>Zmieniony charakter blok\u00f3w dynamicznych w edytorze<\/h2>\n<p>Kiedy zaczniesz tworzy\u0107 dynamiczne bloki, zmieni si\u0119 charakter Twojego bloku w edytorze. Funkcja Twojego bloku r\u00f3wnie\u017c <code>edit<\/code>cz\u0119sto musi by\u0107 dynamiczna. Na przyk\u0142ad w przypadku bloku polecanych post\u00f3w musisz pobra\u0107 posty do wyboru, a w przypadku bloku najnowszych wiadomo\u015bci musisz pobra\u0107 list\u0119 kategorii do wyboru przez u\u017cytkownika.<\/p>\n<p>W pe\u0142ni mo\u017cliwe jest \u017c\u0105danie informacji z WordPressa z poziomu edytora, wykonuj\u0105c \u017c\u0105dania AJAX \u2013 u\u017cywaj\u0105c pakiet\u00f3w i komponent\u00f3w lub wykonuj\u0105c je r\u0119cznie za pomoc\u0105 <a href=\"https:\/\/developer.wordpress.org\/rest-api\/\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">WordPress REST API<\/a>. Niezale\u017cnie od wybranej metody blok musi obs\u0142ugiwa\u0107 asynchroniczny strumie\u0144 danych wej\u015bciowych \u2013 ramy czasowe podczas oczekiwania na odpowied\u017a.<\/p>\n<p>Istnieje wiele metod i wzorc\u00f3w tworzenia dynamicznego bloku dla Gutenberga. Najcz\u0119\u015bciej b\u0119dziesz u\u017cywa\u0142 wzorca React zwanego <a href=\"https:\/\/reactjs.org\/docs\/higher-order-components.html\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">komponentami wy\u017cszego rz\u0119du,<\/a> w kt\u00f3rym WordPress zapewnia mn\u00f3stwo funkcji i komponent\u00f3w.<\/p>\n<p>Przyjrzymy si\u0119, jak pobiera\u0107 posty i jak pobiera\u0107 kategorie w naszym bloku w nast\u0119pnej cz\u0119\u015bci samouczka. Na razie musimy si\u0119 nauczy\u0107, jak sprawi\u0107, by PHP renderowa\u0142 nasz blok.<\/p>\n<h2>Przygotowanie naszego bloku do renderowania PHP<\/h2>\n<p>G\u0142\u00f3wn\u0105 cz\u0119\u015bci\u0105, kt\u00f3r\u0105 musimy zrobi\u0107 w JavaScript, jest <code>save<\/code>zwr\u00f3cenie funkcji bloku <code>null<\/code>. Mo\u017cesz zachowa\u0107 oryginalne wyj\u015bcie, ale gdy powiemy WordPressowi, aby u\u017cywa\u0142 PHP do renderowania bloku, zostanie to zignorowane. Aby by\u0142o jasne dla siebie i innych, \u017ce wyj\u015bcie bloku nie jest obs\u0142ugiwane w JavaScript, zmienimy <code>save<\/code>funkcj\u0119.<\/p>\n<pre><code>registerBlockType('awp\/firstblock', {\n    title: __('My first block', 'awhitepixel'), \n    category: 'common',\n    ...\n    edit: FirstBlockEdit,\n    save:() =&gt; { return null }\n});<\/code><\/pre>\n<p>Nie zapominaj, \u017ce zmiana funkcji zapisu spowoduje zerwanie wszystkich istniej\u0105cych blok\u00f3w. Ponownie dodaj blok. Blok powinien dzia\u0142a\u0107 tak jak poprzednio; z ustawieniami i aktualizacj\u0105 atrybut\u00f3w. Teraz po prostu nie wypisze niczego w interfejsie. B\u0119dzie tam blok komentarza, przechowuj\u0105cy wszystkie atrybuty w JSON, ale nie jest renderowany \u017caden widoczny kod HTML.<\/p>\n<p>Jednak\u017ce; je\u015bli kt\u00f3rykolwiek z Twoich atrybut\u00f3w korzysta z tej <code>source<\/code>w\u0142a\u015bciwo\u015bci, musisz to zmieni\u0107. Nie jest to obs\u0142ugiwane w przypadku blok\u00f3w renderowanych za pomoc\u0105 PHP, poniewa\u017c s\u0105 one analizowane bezpo\u015brednio z wyj\u015bcia zapisu \u2013 do czego teraz wracamy <code>null<\/code>. U\u017cywamy source na drugim <code>RichText<\/code>w naszym bloku \u2013 dla akapitu. W tym momencie edytor w og\u00f3le nie zapisze tego, co w nim umie\u015bcisz <code>RichText<\/code>.<\/p>\n<p>Je\u015bli wi\u0119c nadal u\u017cywasz <code>source<\/code>atrybutu <code>myRichText<\/code>, musimy usun\u0105\u0107 w\u0142a\u015bciwo\u015bci <code>source<\/code>i <code>selector<\/code>, aby upewni\u0107 si\u0119, \u017ce atrybuty b\u0119d\u0105 przechowywane, a nie analizowane z <code>save<\/code>funkcji:<\/p>\n<pre><code>attributes: {\n    ...\n    myRichText: {\n        type: 'string',\n    },\n    ...<\/code><\/pre>\n<p>Po tym nasz blok jest gotowy do renderowania w PHP. Mo\u017cemy zostawi\u0107 pliki Javascript (nie zapomnij go zbudowa\u0107), a reszt\u0119 zrobimy w PHP.<\/p>\n<h2>Bloki renderowania w PHP<\/h2>\n<p>Aby nakaza\u0107 WordPressowi renderowanie wyj\u015bcia bloku w PHP, dodajemy nowy argument do funkcji <code>register_block_type()<\/code>. Musimy doda\u0107 klucz <code>render_callback<\/code>do tablicy z warto\u015bci\u0105 funkcji, kt\u00f3r\u0105 ma uruchomi\u0107.<\/p>\n<pre><code>add_action('init', function() {\n    register_block_type('awp\/firstblock', [\n        'editor_script' =&gt; 'awp-myfirstblock-js',\n        'render_callback' =&gt; 'awp_myfirstblock_render'\n    ]);\n});<\/code><\/pre>\n<h3>Funkcja renderowania PHP<\/h3>\n<p>Zdefiniujmy funkcj\u0119 <code>awp_myfirstblock_render<\/code>dalej <code>functions.php<\/code>(lub gdziekolwiek umie\u015bci\u0142e\u015b sw\u00f3j kod PHP). Nasza funkcja otrzyma dwa parametry; nazwiemy je <code>$attr<\/code>i <code>$content<\/code>.<\/p>\n<pre><code>function awp_myfirstblock_render($attr, $content) {\n    \/\/ return the block's output here\n}<\/code><\/pre>\n<p>Parametr <code>$attr<\/code>b\u0119dzie tablic\u0105 asocjacyjn\u0105 ze wszystkimi zapisanymi atrybutami. Drugi parametr, <code>$content<\/code>, dotyczy blok\u00f3w wewn\u0105trz naszego bloku. Dotyczy to tylko blok\u00f3w, kt\u00f3re obs\u0142uguj\u0105 bloki zagnie\u017cd\u017cone \u2013 co na przyk\u0142ad robi\u0105 kolumny lub os\u0142ona.<\/p>\n<p>Funkcja nigdy nie powinna <code>echo<\/code>nic nie dzia\u0142a\u0107. Wszystkie dane wyj\u015bciowe musz\u0105 zosta\u0107 zwr\u00f3cone, wi\u0119c musisz zbudowa\u0107 \u0142a\u0144cuch i zwr\u00f3ci\u0107 go na ko\u0144cu.<\/p>\n<p>Nale\u017cy pami\u0119ta\u0107 o atrybutach, \u017ce tylko zapisane atrybuty pojawi\u0105 si\u0119 w pierwszym parametrze funkcji. Je\u015bli atrybut nigdy nie zosta\u0142 faktycznie zmieniony i zapisany \u2013 tj. polega\u0142 tylko na its <code>default<\/code>, atrybut nie zostanie w og\u00f3le uwzgl\u0119dniony w naszej funkcji PHP.<\/p>\n<p>Musisz poradzi\u0107 sobie z tym problemem albo zawsze sprawdzaj\u0105c <code>if (isset($attr['...']))<\/code>, albo w preferowany spos\u00f3b: definiuj\u0105c atrybuty w naszym <code>register_block_type()<\/code>wywo\u0142aniu. Mo\u017cemy poda\u0107 inny klucz <code>attributes<\/code>i ustawi\u0107 jego warto\u015b\u0107 na tablic\u0119 ze wszystkimi atrybutami, kt\u00f3re chcemy wyodr\u0119bni\u0107 z naszego bloku. Struktura powinna by\u0107 identyczna z t\u0105, kt\u00f3r\u0105 zdefiniowa\u0142e\u015b w JavaScript, ale zamiast obiektu JavaScript potrzebujesz go w tablicy PHP. Przedefiniowanie tych samych atrybut\u00f3w mo\u017ce by\u0107 troch\u0119 k\u0142opotliwe, ale z inteligentnym edytorem kodu powinno by\u0107 do\u015b\u0107 szybkie skopiowanie+wklejenie i wielowierszowa edycja do PHP.<\/p>\n<h3>Dodanie atrybut\u00f3w dla naszej funkcji render<\/h3>\n<p>Dodajmy nowy <code>attributes<\/code>element <code>register_block_type()<\/code>i wklejmy dok\u0142adnie te same atrybuty, kt\u00f3re zdefiniowali\u015bmy w naszym pliku JavaScript:<\/p>\n<pre><code>add_action('init', function() {\n    register_block_type('awp\/firstblock', [\n        'editor_script' =&gt; 'awp-myfirstblock-js',\n        'render_callback' =&gt; 'awp_myfirstblock_render',\n        'attributes' =&gt; [\n            'myRichHeading' =&gt; [\n                'type' =&gt; 'string'\n            ],\n            'myRichText' =&gt; [\n                'type' =&gt; 'string'\n            ],\n            'textAlignment' =&gt; [\n                'type' =&gt; 'string',\n            ],\n            'toggle' =&gt; [\n                'type' =&gt; 'boolean',\n                'default' =&gt; true\n            ],\n            'favoriteAnimal' =&gt; [\n                'type' =&gt; 'string',\n                'default' =&gt; 'dogs'\n            ],\n            'favoriteColor' ==&gt; [\n                'type' =&gt; 'string',\n                'default' =&gt; '#DDDDDD'\n            ],\n            'activateLasers' =&gt; [\n                'type' =&gt; 'boolean',\n                'default' =&gt; false\n            ],\n        ]\n    ]);\n});\n\u00a0\nfunction awp_myfirstblock_render($attr, $content) {\n    return '&lt;div&gt;'.$attr['favoriteColor'].'&lt;\/div&gt;';\n}<\/code><\/pre>\n<p>Pami\u0119taj, \u017ce je\u015bli zdefiniujesz a <code>default<\/code>dla wszystkich atrybut\u00f3w, <code>$attr<\/code>parametr Twojej funkcji powinien zawsze zawiera\u0107 wszystkie atrybuty. Na przyk\u0142ad <code>textAlignment<\/code>powy\u017cszy atrybut b\u0119dzie istnia\u0142 tylko <code>$attr<\/code>wtedy, gdy zosta\u0142 zmieniony \u2013 i musisz sprawdzi\u0107 <code>isset($attr['textAlignment'])<\/code>.<\/p>\n<p>Niestety, w tej chwili s\u0105 dwie rzeczy, kt\u00f3rych <strong>nie b\u0119dziesz mie\u0107 w przypadku PHP block render<\/strong>. Jednym z nich jest <code>className<\/code>rekwizyt \u2013 wi\u0119c musisz sam zbudowa\u0107 klas\u0119 owijania (je\u015bli chcesz). Druga to <code>support<\/code>w\u0142a\u015bciwo\u015b\u0107 wyr\u00f3wnania blok\u00f3w. Obecnie WordPress nie obs\u0142uguje tej w\u0142a\u015bciwo\u015bci w blokach dynamicznych. Nie zdob\u0119dziemy warto\u015bci wybranego wyr\u00f3wnania bloku, chyba \u017ce zmienimy go na atrybut i obs\u0142u\u017cymy go r\u0119cznie w JavaScript.<\/p>\n<p>Je\u015bli chodzi o wyj\u015bcie HTML funkcji, to w pe\u0142ni zale\u017cy to od Ciebie!<\/p>\n<h2>\u017b\u0105danie renderowania PHP z wewn\u0105trz edytora<\/h2>\n<p>Mo\u017cliwe jest za\u017c\u0105danie renderowania PHP naszego bloku wewn\u0105trz edytora. Jest to przydatne, je\u015bli chcesz mie\u0107 mo\u017cliwo\u015b\u0107 podgl\u0105du wyj\u015bcia bloku w edytorze. Mo\u017cemy to zrobi\u0107 za pomoc\u0105 komponentu wywo\u0142ywanego <code>ServerSideRender<\/code>z <code>wp.editor<\/code>pakietu.<\/p>\n<p>Jako rekwizyty <code>ServerSideRender<\/code>musisz zdefiniowa\u0107 wszystkie atrybuty, kt\u00f3re chcesz przekaza\u0107. Jako minimum musisz poda\u0107 nazw\u0119 bloku do prop <code>block<\/code>, aby WordPress wiedzia\u0142, jakiej metody renderowania szuka\u0107. Jest to dost\u0119pne dla Ciebie w <code>props.name<\/code>funkcji <code>edit<\/code>. Musisz r\u00f3wnie\u017c poda\u0107 wszystkie potrzebne atrybuty w prop <code>attributes<\/code>. Je\u015bli chcesz, mo\u017cesz tutaj r\u00f3wnie\u017c doda\u0107 niestandardowe zmienne poza atrybutami. Pami\u0119taj tylko, \u017ce b\u0119dzie to dzia\u0142a\u0107 tylko w edytorze wewn\u0119trznym, a nie w interfejsie.<\/p>\n<p>Nie mo\u017cesz u\u017cy\u0107 <code>ServerSideRender<\/code>w funkcji bloku <code>save<\/code>. Twoja <code>save<\/code>funkcja musi nadal zwraca\u0107 <code>null<\/code>.<\/p>\n<p>Zaimplementujmy <code>ServerSideRender<\/code>w naszym bloku, aby zobaczy\u0107 to w praktyce.<\/p>\n<h3>U\u017cywanie ServerSideRender do podgl\u0105du\/edycji bloku<\/h3>\n<p>Je\u015bli wykona\u0142e\u015b poprzedni krok, w kt\u00f3rym stworzyli\u015bmy prze\u0142\u0105cznik trybu podgl\u0105du\/edycji dla naszego bloku, mo\u017cemy teraz u\u017cy\u0107 <code>ServerSideRender<\/code>do renderowania podgl\u0105du bloku z PHP, gdy prze\u0142\u0105czymy si\u0119 do trybu podgl\u0105du.<\/p>\n<p>Najpierw musimy pami\u0119ta\u0107 o destrukturyzacji <code>ServerSideRender<\/code>na g\u00f3rze:<\/p>\n<pre><code>const { ServerSideRender } = wp.editor;<\/code><\/pre>\n<p>Je\u015bli pami\u0119tasz z poprzedniego kroku, u\u017cyli\u015bmy komponent\u00f3w <code>Disabled<\/code>i\/lub <code>Placeholder<\/code>do trzymania podgl\u0105du. Problem z u\u017cywaniem <code>Placeholder<\/code>polega na tym, \u017ce otrzymujemy niechcian\u0105 stylizacj\u0119 na naszym wyj\u015bciu. Zast\u0105pmy. <code>Placeholder<\/code>_ <code>ServerSideRender<\/code>Mo\u017cesz zachowa\u0107 <code>Disabled<\/code>komponent, aby upewni\u0107 si\u0119, \u017ce \u017cadna jego zawarto\u015b\u0107 nie b\u0119dzie klikalna ani przeci\u0105gana.<\/p>\n<p>W kodzie do renderowania bloku, gdy atrybut <code>editMode<\/code>ma warto\u015b\u0107 false, robimy:<\/p>\n<pre><code>...\n{!this.state.editMode &amp;&amp; \n    &lt;ServerSideRender\n        block={this.props.name}\n        attributes={{ \n            myRichHeading: attributes.myRichHeading, \n            myRichText: attributes.myRichText, \n            textAlignment: attributes.textAlignment, \n            toggle: attributes.toggle, \n            favoriteAnimal: attributes.favoriteAnimal, \n            favoriteColor: attributes.favoriteColor,\n            activateLasers: attributes.activateLasers\n        }}\n    \/&gt;\n}\n...<\/code><\/pre>\n<p>Teraz nasz niestandardowy przycisk na pasku narz\u0119dzi wyrenderuje dane wyj\u015bciowe z PHP, gdy prze\u0142\u0105czymy si\u0119 w tryb podgl\u0105du. Dane wyj\u015bciowe powinny by\u0107 identyczne podczas przegl\u0105dania posta w interfejsie u\u017cytkownika. Jest to dobry zwyczaj, aby upewni\u0107 si\u0119, \u017ce dane wyj\u015bciowe s\u0105 identyczne zar\u00f3wno w edytorze, jak i interfejsie.<\/p>\n<h2>Przyk\u0142ad: Dynamiczny blok pokazuj\u0105cy wybrany post<\/h2>\n<p>Dane wyj\u015bciowe w funkcji renderowania PHP mog\u0105 by\u0107 dowolne i masz pe\u0142ny dost\u0119p do wszystkich funkcji WordPress. Za\u0142\u00f3\u017cmy blok, w kt\u00f3rym w atrybucie zostanie zapisany identyfikator posta. W <code>render_callback<\/code>funkcji PHP mo\u017cesz wys\u0142a\u0107 zapytanie do wiadomo\u015bci na podstawie identyfikatora i wy\u015bwietli\u0107 jego informacje. Powinno by\u0107 do\u015b\u0107 oczywiste, jak to zrobi\u0107, ale oto szybki przyk\u0142ad.<\/p>\n<p><strong>Uwaga<\/strong>: w tym przyk\u0142adzie po prostu dodamy tekst do edytora, aby r\u0119cznie wprowadzi\u0107 identyfikator posta. Nie jest to bardzo intuicyjne i przyjazne dla u\u017cytkownika rozwi\u0105zanie wyboru posta \u2013 ale o tym nauczymy si\u0119 w nast\u0119pnym kroku. Skupiamy si\u0119 tutaj na cz\u0119\u015bci PHP renderowania wybranego posta.<\/p>\n<p>Dodajmy atrybut <code>selectedPostId<\/code>o numerze typu:<\/p>\n<pre><code>attributes: {\n    selectedPostId: {\n        type: 'number'\n    }\n}<\/code><\/pre>\n<p>A gdzie\u015b wewn\u0105trz <code>edit<\/code>funkcji naszego bloku dodajemy <code>TextControl<\/code>komponent. Mo\u017ce by\u0107 gdziekolwiek chcesz \u2013 w bloku lub w Inspektorze.<\/p>\n<pre><code>&lt;TextControl \n    label={__(\"Type in post ID\", 'awhitepixel')}\n    type=\"number\"\n    value={attributes.selectedPostId}\n    onChange={(newval) =&gt; setAttributes({ selectedPostId: parseInt(newval) })}\n\/&gt;<\/code><\/pre>\n<p>Zwr\u00f3\u0107 uwag\u0119, \u017ce bardzo dbam o to, aby dane wej\u015bciowe poprawnie zapisa\u0142y atrybut jako liczb\u0119, konwertuj\u0105c go na liczb\u0119 ca\u0142kowit\u0105 za pomoc\u0105 <code>parseInt()<\/code>. Mimo \u017ce ustawili\u015bmy type prop <code>type<\/code>na <code>number<\/code>, aby wyrenderowa\u0107 dane wej\u015bciowe liczbowe, zmieniona warto\u015b\u0107 jest nadal interpretowana jako ci\u0105g znak\u00f3w. WordPress nie zapisze Twojego atrybutu, je\u015bli ma z\u0142y format.<\/p>\n<p>Nie zapomnij doda\u0107 nowego atrybutu do swojego <code>ServerSideRender<\/code>komponentu, je\u015bli taki posiadasz:<\/p>\n<pre><code>&lt;ServerSideRender\n    block={this.props.name}\n    attributes={{ \n        selectedPostId: attributes.selectedPostId,\n        ...<\/code><\/pre>\n<h3>Cz\u0119\u015b\u0107 PHP<\/h3>\n<p>To powinno zaj\u0105\u0107 si\u0119 cz\u0119\u015bci\u0105 JavaScript. Przejd\u017amy do PHP. Najpierw musimy doda\u0107 nowy atrybut <code>selectedPostId<\/code>do <code>attributes<\/code>tablicy w <code>register_block_type()<\/code>:<\/p>\n<pre><code>register_block_type('awp\/firstblock', [\n    'editor_script' =&gt; 'awp-myfirstblock-js',\n    'render_callback' =&gt; 'awp_myfirstblock_render',\n    'attributes' =&gt; [\n        'selectedPostId' =&gt; [\n            'type' =&gt; 'number',\n            'default' =&gt; 0\n        ],\n        ...\n    ]\n]);<\/code><\/pre>\n<p>W <code>render_callback<\/code>funkcji mo\u017cemy teraz uzyska\u0107 dost\u0119p do identyfikatora posta za pomoc\u0105 <code>$attr['selectedPostId']<\/code>. Mo\u017cemy dzi\u0119ki temu wykona\u0107 proste <code>get_post()<\/code>i wyprowadzi\u0107 dane posta; jego link i tytu\u0142:<\/p>\n<pre><code>function awp_myfirstblock_render($attr, $content) {\n    $str = '';\n    if ($attr['selectedPostId'] &gt; 0) {\n        $post = get_post($attr['selectedPostId']);\n        if (!$post) {\n            return $str;\n        }\n        $str = '&lt;div class=\"awp-myfirstblock\"&gt;';\n        $str .= '&lt;a href=\"'. get_the_permalink($post). '\"&gt;';\n        $str .= '&lt;h3&gt;'. get_the_title($post). '&lt;\/h3&gt;';\n        $str .= '&lt;\/a&gt;';\n        $str .= '&lt;\/div&gt;';\n    }\n    return $str;\n}<\/code><\/pre>\n<p>To jest bardzo prosty przyk\u0142ad, kt\u00f3ry ma s\u0142u\u017cy\u0107 jako trampolina do pisania bardziej zaawansowanego i niestandardowego kodu.<\/p>\n<p>Teraz, gdy wiemy, jak radzi\u0107 sobie z renderowaniem blok\u00f3w dynamicznych, nast\u0119pnym krokiem jest nauczenie si\u0119, jak sprawi\u0107, by cz\u0119\u015b\u0107 edytora by\u0142a r\u00f3wnie\u017c bardziej intuicyjna. W nast\u0119pnym kroku skupimy si\u0119 na tym, jak wyszukiwa\u0107 posty z poziomu edytora blok\u00f3w i zapewni\u0107 u\u017cytkownikowi lepszy spos\u00f3b wybierania postu.<\/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 przypadku dynamicznej zawarto\u015bci bloku, takiej jak ostatnie posty lub wy\u015bwietlanie posta, musimy renderowa\u0107 wyj\u015bcie bloku w PHP. W tym po\u015bcie dowiemy si\u0119 jak i dlaczego.<\/p>\n","protected":false},"author":1,"featured_media":152680,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":"","_wp_rev_ctl_limit":""},"categories":[897,940,940,897,1110,805,805,845,845,866,866],"tags":[1169],"class_list":["post-233668","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-kod","category-gutenberg-7","category-n-a","category-php-7","category-samouczki","category-wordpress-7","tag-affiai-pl"],"_links":{"self":[{"href":"https:\/\/wordpress.mediadoma.com\/pl\/wp-json\/wp\/v2\/posts\/233668","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=233668"}],"version-history":[{"count":0,"href":"https:\/\/wordpress.mediadoma.com\/pl\/wp-json\/wp\/v2\/posts\/233668\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/pl\/wp-json\/wp\/v2\/media\/152680"}],"wp:attachment":[{"href":"https:\/\/wordpress.mediadoma.com\/pl\/wp-json\/wp\/v2\/media?parent=233668"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/pl\/wp-json\/wp\/v2\/categories?post=233668"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/pl\/wp-json\/wp\/v2\/tags?post=233668"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}