{"id":230947,"date":"2022-12-24T18:36:00","date_gmt":"2022-12-24T15:36:00","guid":{"rendered":"https:\/\/wordpress.mediadoma.com\/?p=230947"},"modified":"2022-12-24T18:36:22","modified_gmt":"2022-12-24T15:36:22","slug":"ogolny-przyklad-wzorca-repozytorium-w-wordpress","status":"publish","type":"post","link":"https:\/\/wordpress.mediadoma.com\/pl\/ogolny-przyklad-wzorca-repozytorium-w-wordpress\/","title":{"rendered":"Og\u00f3lny przyk\u0142ad wzorca repozytorium w WordPress"},"content":{"rendered":"\n<p>Z mojego do\u015bwiadczenia wynika, \u017ce \u200b\u200bspos\u00f3b, w jaki po raz pierwszy wchodzimy w interakcj\u0119 ze wzorcem projektu repozytorium, cz\u0119sto wp\u0142ywa na to, jak my\u015blimy o wzorcu. (Ca\u0142e pierwsze wra\u017cenia s\u0105 trwa\u0142ymi wra\u017ceniami, prawda?)<\/p>\n<p>Celem tego postu jest pokazanie, jak mo\u017cna go zaimplementowa\u0107 w WordPressie, szczeg\u00f3lnie podczas pisania wtyczek obiektowych do odczytu danych (zapisywanie danych mo\u017ce by\u0107 om\u00f3wione w innym po\u015bcie), ale zanim to zrobi\u0142em, pr\u00f3bowa\u0142em wymy\u015bli\u0107 kilka sp\u00f3jno\u015bci mi\u0119dzy wariacje wzoru, kt\u00f3ry widzia\u0142em.<\/p>\n<p>Og\u00f3lnie rzecz bior\u0105c, uwa\u017cam, \u017ce wzorzec repozytorium powinien robi\u0107:<\/p>\n<ul>\n<li>zapewni\u0107 jedno miejsce do odczytu danych,<\/li>\n<li>streszczenie szczeg\u00f3\u0142\u00f3w sposobu dost\u0119pu do danych,<\/li>\n<li>i mie\u0107 do tego sp\u00f3jny interfejs.<\/li>\n<\/ul>\n<p>Oznacza to, \u017ce wszystko, co trzeba pobra\u0107 z aplikacji, mo\u017cna pobra\u0107 z bazy danych. Ale spos\u00f3b jego odzyskania mo\u017cna uzna\u0107 za czarn\u0105 skrzynk\u0119. To zale\u017cy od programisty implementuj\u0105cego wzorzec.<\/p>\n<p>A w przypadku tych, kt\u00f3rzy czytaj\u0105 ten post, to najprawdopodobniej my.<\/p>\n<h2>Wzorzec repozytorium w WordPress<\/h2>\n<p>Kilka lat temu <a href=\"https:\/\/wordpress.mediadoma.com\/pl\/podklad-wzorca-repozytorium\/\" title=\"pisa\u0142em o wzorcu repozytorium\">pisa\u0142em o wzorcu repozytorium<\/a> podaj\u0105c konkretny przyk\u0142ad. To wci\u0105\u017c aktualne, ale cel tego, co chc\u0119 om\u00f3wi\u0107 w tym po\u015bcie, jest nieco inny.<\/p>\n<p>Zamiast pokazywa\u0107 konkretn\u0105 implementacj\u0119 zakorzenion\u0105 w rzeczywistym przyk\u0142adzie, wol\u0119 przedstawi\u0107 argumenty za tym, jak mo\u017cemy wykorzysta\u0107 ten wzorzec w naszej codziennej pracy.<\/p>\n<p>Dwie rzeczy, o kt\u00f3rych nale\u017cy pami\u0119ta\u0107, czytaj\u0105c to, to:<\/p>\n<ol>\n<li>z perspektywy u\u017cytkownika bazowy magazyn danych nie ma znaczenia,<\/li>\n<li>z perspektywy programisty wzorzec pozwala nam pracowa\u0107 z wieloma \u017ar\u00f3d\u0142ami danych, a tak\u017ce makiety przyk\u0142adowego magazynu danych, dzi\u0119ki czemu mo\u017cemy testowa\u0107 dane.<\/li>\n<\/ol>\n<p>Przy implementacji wzorca nie ma znaczenia sk\u0105d pochodz\u0105 dane. Przynajmniej tak d\u0142ugo, jak jeste\u015b deweloperem lub klientem wywo\u0142uj\u0105cym go. Magazyn danych mo\u017ce by\u0107 baz\u0105 danych, zestawem funkcji API lub kombinacj\u0105 obu.<\/p>\n<p>Za\u0142\u00f3\u017cmy zatem, \u017ce pracujesz z niestandardowym typem wpisu dla zdarze\u0144, a tak\u017ce pracujesz z metadanymi wpisu i opcjami zwi\u0105zanymi z czym\u015b takim jak zdarzenia.<\/p>\n<p>Mo\u017cesz zrobi\u0107 co\u015b takiego:<\/p>\n<ul>\n<li>uzyska\u0107 nazw\u0119 wydarzenia,<\/li>\n<li>znale\u017a\u0107 informacje o lokalizacji wydarzenia,<\/li>\n<li>pobierz pierwszy typ posta i status uporz\u0105dkowany wed\u0142ug jego identyfikatora<\/li>\n<\/ul>\n<p>Wszystkie te informacje mog\u0105 by\u0107 rozproszone w r\u00f3\u017cnych miejscach, a spos\u00f3b ich pobierania mo\u017ce si\u0119 r\u00f3\u017cni\u0107.<\/p>\n<h3>1 Uzyskiwanie nazwy wydarzenia<\/h3>\n<p>Je\u015bli pracujemy z niestandardowym typem wpisu i potrzebujemy uzyska\u0107 nazw\u0119 zdarzenia, mo\u017cemy do tego u\u017cy\u0107 identyfikatora wpisu i <a href=\"https:\/\/gist.github.com\/tommcfarlin\/24e5bae859863d39512abc2af2169fbb#file-00-get-event-name-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">jednej z funkcji API WordPressa<\/a>.<\/p>\n<pre><code>&lt;?php\n\n\/**\n * Retrieves the title of the Event, a custom post type.\n *\n * @param  int    $eventId the ID of the event post type\n * @return string          the title of the post.\n *\/\npublic function getName(int $eventId): string\n{\n  return get_the_title($eventId);\n}<\/code><\/pre>\n<p>To jeden z przypadk\u00f3w, w kt\u00f3rych magazyn danych jest nadal od nas oderwany, a zamiast tego wykorzystuje istniej\u0105cy WordPress API.<\/p>\n<h3>2 Uzyskiwanie lokalizacji wydarzenia<\/h3>\n<p>W takim przypadku mo\u017cemy za\u0142o\u017cy\u0107, \u017ce lokalizacja zdarzenia zosta\u0142a wprowadzona r\u0119cznie lub by\u0107 mo\u017ce zosta\u0142a pobrana przez interfejs API innej firmy. A poniewa\u017c lokalizacja jest powi\u0105zana z konkretnym wydarzeniem, mo\u017ce znajdowa\u0107 si\u0119 w tabeli metadanych postu.<\/p>\n<p><a href=\"https:\/\/wordpress.mediadoma.com\/wp-content\/uploads\/2022\/01\/post-160195-61e7073d3924f.png\" data-rel=\"lightbox\"><img decoding=\"async\" class=\"SDStudio-light-box-enable SDStudio-editor-tools-md-imp\" src=\"https:\/\/wordpress.mediadoma.com\/wp-content\/uploads\/2022\/01\/post-160195-61e7073d3924f.png\" alt=\"Og\u00f3lny przyk\u0142ad wzorca repozytorium w WordPress\"><\/a><\/p>\n<p>Ponownie mo\u017cemy go pobra\u0107 za pomoc\u0105 istniej\u0105cych wcze\u015bniej funkcji API; jednak w takich sytuacjach sensowne jest posiadanie funkcji pomocniczej, poniewa\u017c prawdopodobnie b\u0119dziemy r\u00f3wnie\u017c uzyskiwa\u0107 dost\u0119p do innych metadanych.<\/p>\n<p>Wi\u0119c najpierw <a href=\"https:\/\/gist.github.com\/tommcfarlin\/24e5bae859863d39512abc2af2169fbb#file-01-get-the-event-location-helper-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">pomocnik<\/a> :<\/p>\n<pre><code>&lt;?php \n\/**\n * A helper function for easily retrieving post meta data for a given Event.\n *\n * @param int    $id  the ID of the event\n * @param string $key the key for the post meta data for which we're retrieveing the data\n *\n * @return string the result of retrieiving the meta data\n *\/\nprivate function get(int $id, string $key): string\n{\n    return get_post_meta($id, $key, true);\n}<\/code><\/pre>\n<p>A potem funkcja, kt\u00f3ra korzysta z pomocnika, aby <a href=\"https:\/\/gist.github.com\/tommcfarlin\/24e5bae859863d39512abc2af2169fbb#file-02-get-the-event-location-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">uzyska\u0107 lokalizacj\u0119<\/a> :<\/p>\n<pre><code>&lt;?php\n\/**\n * @param  int    $eventID the ID of the event\n * @return string          the name of the event of an empty string\n *\/\npublic function getLocationName($eventId): string\n{\n    return $this-&gt;get($eventId, 'ymc-event-location-name');\n}<\/code><\/pre>\n<p>Ale w tych dw\u00f3ch przyk\u0142adach nadal u\u017cywamy istniej\u0105cych funkcji API. A co z przypadkiem, w kt\u00f3rym musimy porozmawia\u0107 z baz\u0105 danych?<\/p>\n<h3>3 Pobieranie adresu URL pojedynczego posta<\/h3>\n<p>W tym przypadku b\u0119dziemy komunikowa\u0107 si\u0119 bezpo\u015brednio z baz\u0105 danych WordPress. Je\u015bli znasz obiekt <a href=\"https:\/\/codex.wordpress.org\/Class_Reference\/wpdb\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">$wpdb<\/a> i SQL, to nie b\u0119dzie to wielka sprawa.<\/p>\n<p><a href=\"https:\/\/wordpress.mediadoma.com\/wp-content\/uploads\/2022\/01\/post-160195-61e70741367bc.png\" data-rel=\"lightbox\"><img decoding=\"async\" class=\"SDStudio-light-box-enable SDStudio-editor-tools-md-imp\" src=\"https:\/\/wordpress.mediadoma.com\/wp-content\/uploads\/2022\/01\/post-160195-61e70741367bc.png\" alt=\"Og\u00f3lny przyk\u0142ad wzorca repozytorium w WordPress\"><\/a><\/p>\n<p>Je\u015bli nie, polecam poczyta\u0107 o funkcji <a href=\"https:\/\/codex.wordpress.org\/Data_Validation#Database\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">przygotowania<\/a>, a tak\u017ce funkcji <a href=\"https:\/\/codex.wordpress.org\/Class_Reference\/wpdb#Talking_to_the_Database:_The_wpdb_Class\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">get_results<\/a>.<\/p>\n<p>Bior\u0105c to pod uwag\u0119, mo\u017cemy napisa\u0107 zapytanie, kt\u00f3re wykona nast\u0119puj\u0105ce czynno\u015bci:<\/p>\n<ol>\n<li>we\u017a wszystkie posty, w kt\u00f3rych identyfikator pasuje do okre\u015blonej warto\u015bci, typ posta i status posta maj\u0105 okre\u015blon\u0105 warto\u015b\u0107, a wyniki uporz\u0105dkujemy rosn\u0105co wed\u0142ug warto\u015bci identyfikatora,<\/li>\n<li>nast\u0119pnie u\u017cyjemy wynik\u00f3w tego zapytania, aby uzyska\u0107 pojedyncz\u0105 warto\u015b\u0107.<\/li>\n<\/ol>\n<p>I <a href=\"https:\/\/gist.github.com\/tommcfarlin\/24e5bae859863d39512abc2af2169fbb#file-03-get-single-post-url-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">mo\u017cemy to zrobi\u0107<\/a>, uzyskuj\u0105c dost\u0119p do bazy danych i pisz\u0105c zagnie\u017cd\u017cone zapytanie:<\/p>\n<pre><code>&lt;?php\n\n\/**\n * @return string the URL to the event next to the current event.\n *\/\npublic function getNextEventUrl()\n{\n    global $wpdb;\n    $results = $wpdb-&gt;get_results(\n        $wpdb-&gt;prepare(\n            \"\n            SELECT *\n            FROM $wpdb-&gt;posts\n            WHERE ID &gt; (SELECT ID\n                FROM $wpdb-&gt;posts\n                WHERE ID = %d\n                AND post_type = '%s'\n                AND post_status = '%s'\n                ORDER BY ID ASC) AND post_type = '%s'\n            AND post_status = '%s'\n            ORDER BY ID ASC\n            LIMIT 1\n        \",\n            get_the_ID(),\n            'ymc-events',\n            'publish',\n            'ymc-events',\n            'publish') );\n\n  $result = (isset($result[0]))? $result[0]: '';\n\n  return $result;\n}<\/code><\/pre>\n<p>A potem wszystko to mo\u017cna zamkn\u0105\u0107 w jednej klasie, kt\u00f3ra by\u0142aby, powiedzmy, repozytorium zdarze\u0144 (lub <strong>EventRepository<\/strong> ).<\/p>\n<p>Wi\u0119cej na ten temat opowiem w kolejnym po\u015bcie. Mianowicie, jak obs\u0142u\u017cy\u0107 okre\u015bli\u0107, kt\u00f3re funkcje powinny gdzie, konwencje nazewnictwa i jak obs\u0142ugiwa\u0107 trwa\u0142o\u015b\u0107, je\u015bli chcesz wprowadzi\u0107 to r\u00f3wnie\u017c do swojego repozytorium.<\/p>\n<h2>Zdefiniowane repozytorium<\/h2>\n<p>Przede wszystkim pami\u0119taj o tym:<\/p>\n<p>Wzorzec repozytorium maskuje spos\u00f3b pobierania danych, ale zapewnia sp\u00f3jny spos\u00f3b pobierania danych, z kt\u00f3rymi jest powi\u0105zany.<\/p>\n<p>Niekt\u00f3rzy mog\u0105 r\u00f3wnie\u017c doda\u0107, jak mo\u017cna to pobra\u0107 <strong>i<\/strong> jak mo\u017cna to napisa\u0107, ale by\u0107 mo\u017ce om\u00f3wi\u0119 to w innym po\u015bcie.<\/p>\n<p><div id=\"PostUnique_PostSource\" style=\"padding-top: 50px\">\u0179r\u00f3d\u0142o nagrywania:  <a target=\"_blank\" rel=\"noopener nofollow\" href=\"\/\/tommcfarlin.com\" class=\"external external_icon\">tommcfarlin.com<\/a><\/div><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Wzorzec repozytorium zapewnia sp\u00f3jny spos\u00f3b pobierania danych. Oto jak mo\u017cna go zaimplementowa\u0107 we wtyczce WordPress.<\/p>\n","protected":false},"author":1,"featured_media":236255,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":"","_wp_rev_ctl_limit":""},"categories":[721,897,866],"tags":[1169],"class_list":["post-230947","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-deweloper","category-kod","category-wordpress-7","tag-affiai-pl"],"_links":{"self":[{"href":"https:\/\/wordpress.mediadoma.com\/pl\/wp-json\/wp\/v2\/posts\/230947","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=230947"}],"version-history":[{"count":0,"href":"https:\/\/wordpress.mediadoma.com\/pl\/wp-json\/wp\/v2\/posts\/230947\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/pl\/wp-json\/wp\/v2\/media\/236255"}],"wp:attachment":[{"href":"https:\/\/wordpress.mediadoma.com\/pl\/wp-json\/wp\/v2\/media?parent=230947"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/pl\/wp-json\/wp\/v2\/categories?post=230947"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/pl\/wp-json\/wp\/v2\/tags?post=230947"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}