{"id":228708,"date":"2022-10-18T11:27:00","date_gmt":"2022-10-18T08:27:00","guid":{"rendered":"https:\/\/wordpress.mediadoma.com\/?p=228708"},"modified":"2022-11-09T03:57:20","modified_gmt":"2022-11-09T00:57:20","slug":"utilisation-de-lediteur-de-blocs-wordpress-gutenberg-avec-lapi-rest","status":"publish","type":"post","link":"https:\/\/wordpress.mediadoma.com\/fr\/utilisation-de-lediteur-de-blocs-wordpress-gutenberg-avec-lapi-rest\/","title":{"rendered":"Utilisation de l&rsquo;\u00e9diteur de blocs WordPress (Gutenberg) avec l&rsquo;API REST"},"content":{"rendered":"\n<p>Dans mon article pr\u00e9c\u00e9dent, j&rsquo;ai expliqu\u00e9 <a href=\"https:\/\/wholesomecode.ltd\/articles\/wp_query-and-the-wordpress-block-editor-gutenberg\/\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">comment parcourir les messages et les types de messages personnalis\u00e9s dans Gutenberg<\/a>. Dans cet article, je parle de la r\u00e9ception et de l&rsquo;utilisation de donn\u00e9es personnalis\u00e9es dans Gutenberg \u00e0 partir des points de terminaison de l&rsquo;API REST WordPress.<\/p>\n<p>Dans cet exemple nous allons :<\/p>\n<p><strong>L&rsquo;API REST n&rsquo;est pas toujours le bon chemin.<\/strong><\/p>\n<p>*Nous utilisons <code>get_option<\/code>l&rsquo;API REST uniquement \u00e0 titre d&rsquo;exemple. Si vous avez uniquement besoin d&rsquo;acc\u00e9der \u00e0 une option et que vous n&rsquo;avez pas l&rsquo;intention de modifier son \u00e9tat, vous pouvez utiliser <code>wp_localize_script<\/code>\u00e0 la place pour transmettre les options \u00e0 JavaScript.<\/p>\n<p>Si vous souhaitez acc\u00e9der \u00e0 une option ET modifier son \u00e9tat, je vous recommande de lire mon <a href=\"https:\/\/wholesomecode.ltd\/guides\/options-settings-data-wordpress-gutenberg\/\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">guide sur le stockage des param\u00e8tres et des donn\u00e9es dans la table des options avec Gutenberg \u00e0 l&rsquo;aide de l&rsquo;API Settings<\/a> .*<\/p>\n<h2>Cr\u00e9ation d&rsquo;un point de terminaison d&rsquo;API REST<\/h2>\n<p>Nous allons cr\u00e9er un point de terminaison API REST simple qui renvoie la valeur d&rsquo;une option WordPress (en utilisant <code>get_option<\/code>).<\/p>\n<pre><code>function wcltd_get_option() {\n    register_rest_route(\n        'wcltd\/wholesome-plugin\/v1',\n        '\/get\/option\/(?P&lt;option&gt;([A-Za-z0-9_])+)\/',\n        array(\n            'callback'            =&gt; function ($request) {\n                $option = isset( $request['option'] )? esc_attr( $request['option'] ): null;\n                $value  = get_option( $option, '' );\n                return $value;\n            },\n            'methods'             =&gt; 'GET',) );\n}\nadd_action( 'rest_api_init', 'wcltd_get_option' );\n<\/code><\/pre>\n<p>Apr\u00e8s avoir cr\u00e9\u00e9 ce point de terminaison, assurez-vous de <strong>r\u00e9enregistrer vos permaliens<\/strong> pour qu&rsquo;il s&rsquo;active. Notez qu&rsquo;il existe de meilleures fa\u00e7ons de le faire (comme l&rsquo;utilisation <code>flush_rewrite_rules()<\/code>sur le <code>register_activation_hook<\/code>), mais pour cet exemple, un r\u00e9enregistrement rapide suffira.<\/p>\n<p>Maintenant, lorsque nous passons l&rsquo;URL <code>\/wp-json\/wcltd\/wholesome-plugin\/v1\/get\/option\/test\/<\/code>(apr\u00e8s votre propre domaine \u00e9videmment) dans notre navigateur, il renverra une valeur, qui sera soit une cha\u00eene vide, <code>''<\/code>soit la valeur de l&rsquo;option si elle est d\u00e9finie.<\/p>\n<p><a href=\"https:\/\/cdn.hashnode.com\/res\/hashnode\/image\/upload\/v1639990082853\/S6umfXuzNF.png\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">Notre point de terminaison, renvoyant une cha\u00eene vide<\/a> Notre point de terminaison, renvoyant une cha\u00eene vide<\/p>\n<p>Notez que j&rsquo;ai d\u00e9lib\u00e9r\u00e9ment comment\u00e9 les lignes 12 \u00e0 14, ce qui garantirait que seule une personne disposant <code>edit_post<\/code>des droits puisse ex\u00e9cuter le code s&rsquo;il est laiss\u00e9. Cependant, avec ce commentaire, nous ne pouvons pas tester le code dans notre navigateur.<\/p>\n<p>Essayez d&rsquo;ajouter du code pour donner une valeur \u00e0 votre option et voyez ce qu&rsquo;elle renvoie. Par exemple, si je devais ex\u00e9cuter le code suivant avant ma fonction\u00a0:<\/p>\n<pre><code>update_option( 'wcltd_example_option', 'Hello World' );\n<\/code><\/pre>\n<p>Maintenant, si j&rsquo;atteins le point final <code>\/wp-json\/wcltd\/wholesome-plugin\/v1\/get\/option\/wcltd_example_option\/<\/code>, j&rsquo;obtiendrai la sortie suivante\u00a0:<\/p>\n<p>Notre point de terminaison, renvoyant des donn\u00e9es.<\/p>\n<h2>Enregistrement d&rsquo;un magasin de donn\u00e9es<\/h2>\n<p>Maintenant que nous avons un point de terminaison d&rsquo;API REST, nous pouvons cr\u00e9er un magasin de donn\u00e9es avec <code>registerStore<\/code>.<\/p>\n<p><code>registerStore<\/code>fournit un magasin de donn\u00e9es de type Redux, qui nous permet de g\u00e9rer l&rsquo;\u00e9tat de notre application. Il prend \u00e9galement en charge les r\u00e9solveurs, qui nous permettent de remplir l&rsquo;\u00e9tat \u00e0 partir d&rsquo;une source externe (telle que notre API REST).<\/p>\n<p>Vous pouvez <a href=\"https:\/\/reactjs.org\/docs\/state-and-lifecycle.html\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">en savoir plus sur l&rsquo;\u00e9tat REACT dans la documentation officielle<\/a>.<\/p>\n<p>Voici comment nous pouvons cr\u00e9er un magasin (comme <code>store.js<\/code>dans notre projet qui nous permettra d&rsquo;extraire des donn\u00e9es de notre point de terminaison API REST.<\/p>\n<h3>D\u00e9pendances<\/h3>\n<p>Nous aurons besoin d&rsquo;extraire <code>apiFetch<\/code>et <code>registerStore<\/code>de nos d\u00e9pendances WordPress.<\/p>\n<pre><code>import apiFetch from '@wordpress\/api-fetch';\nimport { registerStore } from '@wordpress\/data';\n<\/code><\/pre>\n<h3>S\u00e9lecteurs<\/h3>\n<p>La premi\u00e8re chose que nous voulons faire est de cr\u00e9er une fonction de s\u00e9lection, dans un objet appel\u00e9 &lsquo;selectors&rsquo;.<\/p>\n<p>Tout ce que cela fait est d&rsquo;extraire l&rsquo;option de l&rsquo;\u00e9tat et de la renvoyer.<\/p>\n<pre><code>const selectors = {\n    getOption( state, optionKey) {\n        const { option } = state;\n        return option;\n    },\n};\n<\/code><\/pre>\n<h3>R\u00e9solveurs<\/h3>\n<p>Le r\u00e9solveur est un effet secondaire du s\u00e9lecteur, et fait un peu plus.<\/p>\n<p>Ici, nous cr\u00e9ons notre fonction qui prend notre optionKey et transmet un point de terminaison API REST \u00e0 nos actions (que nous d\u00e9finirons ensuite).<\/p>\n<p>Cela d\u00e9finit alors l&rsquo;option, avec un autre appel \u00e0 nos actions.<\/p>\n<pre><code>const resolvers = {\n    *getOption( optionKey) {\n        const option = yield actions.getOption(\n            '\/wcltd\/wholesome-plugin\/v1\/get\/option\/' + optionKey + '\/',\n        );\n        return actions.setOption( option );\n    },\n};\n<\/code><\/pre>\n<h3>Actions<\/h3>\n<p>Les deux fonctions d&rsquo;un objet nomm\u00e9 <code>actions<\/code>que nous avons appel\u00e9 pr\u00e9c\u00e9demment sont d\u00e9finies ici.<\/p>\n<p>Ils indiquent quel contr\u00f4le ou r\u00e9ducteur nous allons utiliser pour d\u00e9finir ou obtenir la valeur.<\/p>\n<pre><code>const actions = {\n    setOption( option) {\n        return {\n            type: 'SET_OPTION',\n            option,\n        };\n    },\n    getOption( path) {\n        return {\n            type: 'GET_OPTION',\n            path,\n        };\n    },\n};\n<\/code><\/pre>\n<h3>Les contr\u00f4les<\/h3>\n<p>Dans nos contr\u00f4les, nous avons <code>GET_OPTION<\/code>qui effectue l&rsquo;appel d&rsquo;API en utilisant <code>apiFetch<\/code>et le chemin que nous avons d\u00e9fini pr\u00e9c\u00e9demment.<\/p>\n<pre><code>const controls = {\n    GET_OPTION( action) {\n        return apiFetch( { path: action.path } );\n    },\n};\n<\/code><\/pre>\n<h3>R\u00e9ducteur<\/h3>\n<p>Dans notre fonction de r\u00e9duction, nous avons <code>SET_OPTION<\/code>qui prend notre valeur (dans ce cas <code>option<\/code>, et d\u00e9finit son \u00e9tat.<\/p>\n<pre><code>function reducer( state = { option: '' }, action) {\n    switch (action.type) {\n        case 'SET_OPTION':\n            return {\n                ...state,\n                option: action.option,\n            };\n    }\n    return state;\n};\n<\/code><\/pre>\n<h3>Enregistrement du magasin<\/h3>\n<p>Enfin, nous enregistrons un magasin, lui donnons un espace de noms afin que nous puissions y acc\u00e9der, et transmettons un objet de tous les objets et fonctions ci-dessus.<\/p>\n<pre><code>const store = registerStore(\n    'wcltd\/wholesome-plugin\/data',\n    {\n        actions,\n        controls,\n        reducer,\n        resolvers,\n        selectors,\n    }\n);\n\nexport default store;\n<\/code><\/pre>\n<p>exporter le magasin par d\u00e9faut\u00a0;<\/p>\n<h2>Utilisation des donn\u00e9es avec un bloc<\/h2>\n<p>D\u00e9veloppons le <a href=\"https:\/\/wholesomecode.ltd\/articles\/an-overview-of-the-wordpress-create-block-script\/\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">bloc cr\u00e9\u00e9 par le <code>@wordpress\/create-block<\/code>script, dont j&rsquo;ai parl\u00e9 pr\u00e9c\u00e9demment<\/a> pour nous permettre de nous connecter \u00e0 un point de terminaison de l&rsquo;API REST.<\/p>\n<p>Cr\u00e9ez un fichier dans le <code>\/src<\/code>dossier appel\u00e9 <code>store.js<\/code>et copiez-y tout le code ci-dessus\u00a0:<\/p>\n<pre><code>import apiFetch from '@wordpress\/api-fetch';\nimport { registerStore } from '@wordpress\/data';\n\nconst selectors = {\n    getOption( state, optionKey) {\n        const { option } = state;\n        return option;\n    },\n};\n\nconst resolvers = {\n    *getOption( optionKey) {\n        const option = yield actions.getOption(\n            '\/wcltd\/wholesome-plugin\/v1\/get\/option\/' + optionKey + '\/',\n        );\n        return actions.setOption( option );\n    },\n};\n\nconst actions = {\n    setOption( option) {\n        return {\n            type: 'SET_OPTION',\n            option,\n        };\n    },\n    getOption( path) {\n        return {\n            type: 'GET_OPTION',\n            path,\n        };\n    },\n};\n\nconst controls = {\n    GET_OPTION( action) {\n        return apiFetch( { path: action.path } );\n    },\n};\n\nfunction reducer( state = { option: '' }, action) {\n    switch (action.type) {\n        case 'SET_OPTION':\n            return {\n                ...state,\n                option: action.option,\n            };\n    }\n    return state;\n};\n\nconst store = registerStore(\n    'wcltd\/wholesome-plugin\/data',\n    {\n        actions,\n        controls,\n        reducer,\n        resolvers,\n        selectors,\n    }\n);\n\nexport default store;\n<\/code><\/pre>\n<p>Modifiez maintenant notre <code>\/src\/index.js<\/code>fichier pour inclure le <code>store.js<\/code>fichier\u00a0:<\/p>\n<pre><code>\nimport store from '.\/store';\nimport Edit from '.\/edit';\nimport save from '.\/save';\n<\/code><\/pre>\n<p>Nous devons \u00e9galement nous assurer que nous avons inclus <code>withSelect<\/code>en haut de notre fichier\u00a0:<\/p>\n<pre><code>import { withSelect } from '@wordpress\/data';\n<\/code><\/pre>\n<p>Enveloppons ensuite notre module Edit avec <code>withSelect<\/code>pour faire l&rsquo;appel de l&rsquo;API REST \u00e0 notre option, comme ceci\u00a0:<\/p>\n<pre><code>\nedit: withSelect( (select) =&gt; {\n    const option = select( 'wcltd\/wholesome-plugin\/data' ).getOption( 'wcltd_example_option' );\n    return {\n        option,\n    };\n} )( Edit ),\n<\/code><\/pre>\n<p>Maintenant, nous pouvons acc\u00e9der <code>option<\/code>\u00e0 nos accessoires dans <code>edit.js<\/code>, comme ceci\u00a0:<\/p>\n<pre><code>export default function Edit( { className, option }) {\n    return (&lt;p className={ className }&gt;\n            { option }\n        &lt;\/p&gt;\n    );\n}\n<\/code><\/pre>\n<p>Enfin, regardons notre bloc dans l&rsquo;\u00e9diteur et voyons ce que nous obtenons\u00a0:<\/p>\n<p><a href=\"https:\/\/cdn.hashnode.com\/res\/hashnode\/image\/upload\/v1639990090843\/2uT6sdoTo.png\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">La sortie dans l&rsquo;\u00e9diteur de blocs.<\/a> La sortie dans l&rsquo;\u00e9diteur de blocs.<\/p>\n<p><div id=\"PostUnique_PostSource\" style=\"padding-top: 50px\">Source d&rsquo;enregistrement:  <a target=\"_blank\" rel=\"noopener nofollow\" href=\"\/\/wholesomecode.ltd\" class=\"external external_icon\">wholesomecode.ltd<\/a><\/div><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Dans mon article pr\u00e9c\u00e9dent, j&rsquo;ai expliqu\u00e9 comment parcourir les publications et les types de publication personnalis\u00e9s dans Gutenberg. Dans cet article, je parle de la r\u00e9ception et de l&rsquo;utilisation de donn\u00e9es personnalis\u00e9es dans Gutenberg f&#8230;<\/p>\n","protected":false},"author":1,"featured_media":220671,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":"","_wp_rev_ctl_limit":""},"categories":[915,893,717,862],"tags":[1167],"class_list":["post-228708","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-autre","category-code-2","category-developpeur","category-wordpress-3","tag-affiai-fr"],"_links":{"self":[{"href":"https:\/\/wordpress.mediadoma.com\/fr\/wp-json\/wp\/v2\/posts\/228708","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wordpress.mediadoma.com\/fr\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/wordpress.mediadoma.com\/fr\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/fr\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/fr\/wp-json\/wp\/v2\/comments?post=228708"}],"version-history":[{"count":0,"href":"https:\/\/wordpress.mediadoma.com\/fr\/wp-json\/wp\/v2\/posts\/228708\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/fr\/wp-json\/wp\/v2\/media\/220671"}],"wp:attachment":[{"href":"https:\/\/wordpress.mediadoma.com\/fr\/wp-json\/wp\/v2\/media?parent=228708"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/fr\/wp-json\/wp\/v2\/categories?post=228708"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/fr\/wp-json\/wp\/v2\/tags?post=228708"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}