{"id":230456,"date":"2022-12-06T15:03:00","date_gmt":"2022-12-06T12:03:00","guid":{"rendered":"https:\/\/wordpress.mediadoma.com\/?p=230456"},"modified":"2022-12-06T15:03:12","modified_gmt":"2022-12-06T12:03:12","slug":"organizacion-de-tipos-vistas-y-suscriptores-de-wordpress","status":"publish","type":"post","link":"https:\/\/wordpress.mediadoma.com\/es\/organizacion-de-tipos-vistas-y-suscriptores-de-wordpress\/","title":{"rendered":"Organizaci\u00f3n de tipos, vistas y suscriptores de WordPress"},"content":{"rendered":"\n<p>Una de las cosas que me encuentro tratando de hacer regularmente es optimizar la forma en que construyo la funcionalidad enfocada en WordPress. <strong><a href=\"https:\/\/wordpress.mediadoma.com\/es\/una-guia-simple-para-organizar-clases-centradas-en-wordpress\/\" title=\"Recientemente habl\u00e9 sobre esto\">Recientemente habl\u00e9 sobre esto<\/a><\/strong>, pero pens\u00e9 en ampliarlo un poco m\u00e1s.<\/p>\n<p>Es decir, pens\u00e9 en exponer el enfoque que tomo cuando construyo cosas como tipos de publicaciones personalizadas, taxonom\u00edas, metaboxes, etc.<\/p>\n<p>En general, piense en esto como una estrategia que sigo para desarrollar aspectos de un proyecto que interact\u00faa directamente con WordPress pero puede requerir algunos componentes como:<\/p>\n<ul>\n<li>clases que se registran en WordPress a trav\u00e9s de varios ganchos,<\/li>\n<li>clases que requieren llamadas a ciertas API de WordPress<\/li>\n<li>y clases que requieren una vista personalizada.<\/li>\n<\/ul>\n<p>Claro, no todo lo que interact\u00faa con WordPress necesitar\u00e1 todo lo anterior (por ejemplo, \u00bfun tipo de publicaci\u00f3n personalizada necesita una vista? No. Pero un cuadro meta s\u00ed).<\/p>\n<h2>Organizaci\u00f3n de los tipos de WordPress<\/h2>\n<p>Dicho esto, voy a tomar un ejemplo m\u00e1s complicado, como un cuadro meta y luego desglosar\u00e9 una forma en la que creo que se puede implementar. Voy a anotar las cosas que creo que son necesarias y las cosas que son opcionales.<\/p>\n<p>Y, como dije, estoy usando un cuadro meta como ejemplo porque tengo una referencia anterior e implica la mayor cantidad de trabajo, mientras que otra cosa, como una taxonom\u00eda personalizada, puede no requerir todas (solo un subconjunto) de las piezas. .<\/p>\n<p>Dicho esto, perm\u00edtanme exponer mi enfoque.<\/p>\n<h3>Necesitamos Suscriptores<\/h3>\n<p>He hablado lo suficiente sobre este patr\u00f3n en particular hasta el punto en que simplemente voy a <a href=\"https:\/\/en.wikipedia.org\/wiki\/Publish%E2%80%93subscribe_pattern\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">vincular a una definici\u00f3n del mismo<\/a>. Si est\u00e1 leyendo esta p\u00e1gina, es probable que est\u00e9 al tanto de los diversos ganchos y de c\u00f3mo usarlos en WordPress.<\/p>\n<p>Foto de Alexander Andrews en Unsplash<\/p>\n<p>Pero la raz\u00f3n por la que quiero mencionarlo es porque en lugar de pensar en conectar una funci\u00f3n para que se active cada vez que suceda algo, quiero que pienses en un objeto que se suscriba a un evento cuando ocurra.<\/p>\n<p>Esto significa que necesitaremos un tipo de clase de suscriptor.<\/p>\n<h3>Clases de la API de WordPress<\/h3>\n<p>En segundo lugar, necesitamos clases que sean responsables de interactuar directamente con WordPress. Estas son las clases que llaman a la API de WordPress y registran lo que sea que sean responsables de hacer.<\/p>\n<p>Es decir, tal vez van a definir un tipo de publicaci\u00f3n personalizada o tal vez, como se dijo, van a definir un metabox.<\/p>\n<h3>Definici\u00f3n de vistas<\/h3>\n<p>Finalmente, es importante tener en cuenta que para algunas funciones personalizadas para el \u00e1rea de administraci\u00f3n de WordPress (o incluso \u00e1reas p\u00fablicas), es posible que desee incluir una vista, una plantilla o una vista parcial (generalmente me refiero a ellas como vistas) que trabajar para representar los datos de un cuadro meta.<\/p>\n<p><a href=\"https:\/\/wordpress.mediadoma.com\/wp-content\/uploads\/2022\/01\/post-162654-61e741fa06c63.jpg\" 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-162654-61e741fa06c63.jpg\" alt=\"Organizaci\u00f3n de tipos, vistas y suscriptores de WordPress\"><\/a><\/p>\n<p>Foto de Saketh Garuda en Unsplash<\/p>\n<p>A veces esto ser\u00e1 simplemente informativo. A veces, esto requerir\u00e1 que se publique en el servidor y serialice los datos. Aunque creo que hablar de esto \u00faltimo ser\u00eda realmente beneficioso, est\u00e1 fuera del alcance actual de esta publicaci\u00f3n.<\/p>\n<p>Quiz\u00e1s en un futuro post.<\/p>\n<h2>Organizaci\u00f3n de clases<\/h2>\n<p>\u00bfQu\u00e9 dijo todo eso, c\u00f3mo ser\u00eda exponer todo esto? Por lo menos, estamos viendo:<\/p>\n<ul>\n<li>un suscriptor,<\/li>\n<li>un tipo de WordPress,<\/li>\n<li>una vista<\/li>\n<\/ul>\n<p>Y, como m\u00e1ximo, puede estar interesado en definir interfaces o clases abstractas para ayudar a hacer cumplir un contrato entre los distintos tipos de WordPress. Este tambi\u00e9n es un principio saludable orientado a objetos del que hablar\u00e9 en una publicaci\u00f3n futura.<\/p>\n<p>Por ahora, sin embargo, hablemos de c\u00f3mo configurar cada uno de estos.<\/p>\n<h3>el suscriptor<\/h3>\n<p>En pocas palabras, el suscriptor es responsable de escuchar cada vez que WordPress genera un evento (publica un evento). Y cuando se da cuenta de que lo hace, activa una funci\u00f3n que est\u00e1 enganchada a \u00e9l.<\/p>\n<p>Esto generalmente se define en el patr\u00f3n de registro. Si no has le\u00eddo esa publicaci\u00f3n, te la recomiendo, pero configurar el c\u00f3digo <strong><a href=\"https:\/\/gist.github.com\/tommcfarlin\/274b69d0fc1e39aaf51384287240cea6#file-00-acme-meta-box-subscriber-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">es bastante f\u00e1cil:<\/a><\/strong><\/p>\n<pre><code>&lt;?php\n\nclass AcmeMetaBoxSubscriber extends AbstractSubscriber\n{\n    public function __construct(string $hook)\n    {\n        parent::__construct($hook);\n    }\n\n    public function load()\n    {\n        (new AcmeMetaBox())-&gt;render();\n    }\n}\n<\/code><\/pre>\n<p>A partir de ah\u00ed, cada vez que se genere el evento, la funci\u00f3n se activar\u00e1. Sin embargo, aqu\u00ed est\u00e1 la cosa: la funci\u00f3n tiene que ser parte de una cierta clase. Por lo tanto, la necesidad del tipo WordPress<\/p>\n<h3>El tipo de WordPress<\/h3>\n<p>Me gusta considerar los tipos de cosas que interact\u00faan con WordPress como tipos de WordPress (al igual que nuestros lenguajes de programaci\u00f3n tienen tipos nativos como cadenas y n\u00fameros enteros). WordPress tiene taxonom\u00edas, metacuadros, men\u00fas, etc.<\/p>\n<p>Para que nuestro suscriptor funcione correctamente, debe conocer nuestro tipo de WordPress. De acuerdo con el ejemplo del cuadro meta, <strong><a href=\"https:\/\/gist.github.com\/tommcfarlin\/274b69d0fc1e39aaf51384287240cea6#file-01-acme-meta-box-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">as\u00ed es como se ver\u00e1:<\/a><\/strong><\/p>\n<pre><code>&lt;?php\n\nclass AcmeMetaBox extends AbstractMetaBox\n{\n    public function render()\n    {\n        add_meta_box(\n            'acme-data',\n            'Acme Data',\n            [$this, 'display'],\n            $this-&gt;postType,\n            'normal',\n            'high'\n        );\n    }\n\n    public function display()\n    {\n        include_once plugin_dir_path(__FILE__).'Views\/acme-data.php';\n    }\n}\n<\/code><\/pre>\n<p>Luego, debemos asegurarnos de que el registro reconozca esta clase.<\/p>\n<h3>La vista<\/h3>\n<p>Finalmente, para un cuadro meta, debemos asegurarnos de que haya una vista que al menos muestre informaci\u00f3n. Serializar informaci\u00f3n y luego actualizar la vista para el usuario es un poco diferente.<\/p>\n<p>Pero, \u00bfc\u00f3mo ser\u00eda una vista? <strong><a href=\"https:\/\/gist.github.com\/tommcfarlin\/274b69d0fc1e39aaf51384287240cea6#file-02-acme-data-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">F\u00e1cil<\/a><\/strong> :<\/p>\n<pre><code>&lt;div class=\"acme-data-metabox\"&gt;\n  &lt;?php echo __('Acme Data', 'acme-meta-box'); ?&gt;\n  &lt;p class=\"description\"&gt;\n    This is the content of the metabox.\n  &lt;\/p&gt;\n&lt;\/div&gt;<\/code><\/pre>\n<p>Es solo un marcado b\u00e1sico que brinda informaci\u00f3n al usuario.<\/p>\n<h2>Atarlo todo junto<\/h2>\n<p>Cada vez que re\u00fano todo esto, generalmente tengo una clase de complemento que lo pone todo en marcha. Si un proyecto es grande, puede haber m\u00e1s de uno, pero en este caso, creo que est\u00e1 bien mostrar c\u00f3mo se ve usando una sola clase.<\/p>\n<p>Entonces, primero, la clase de complemento principal <strong><a href=\"https:\/\/gist.github.com\/tommcfarlin\/274b69d0fc1e39aaf51384287240cea6#file-03-plugin-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">se ve as\u00ed:<\/a><\/strong><\/p>\n<pre><code>&lt;?php\n\nclass Plugin\n{\n    private $registry;\n\n    public function __construct(Registry $registry)\n    {\n        $this-&gt;registry = $registry;\n    }\n\n    public function start()\n    {\n        array_map(function ($subscriber) {\n            add_action($subscriber-&gt;getHook(), [$subscriber, 'load']);\n        }, $this-&gt;registry-&gt;getRegisteredSubscribers());\n    }\n}\n<\/code><\/pre>\n<p>Y el arranque para el complemento <strong><a href=\"https:\/\/gist.github.com\/tommcfarlin\/274b69d0fc1e39aaf51384287240cea6#file-04-bootstrap-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">se ve as\u00ed:<\/a><\/strong><\/p>\n<pre><code>&lt;?php\n\n\/\/ Setup a filter so we can retrieve the registry throughout the plugin.\n$registry = new Registry();\nadd_filter('acmeApiRegistry', function() use ($registry) {\n    return $registry;\n});\n\n\/\/ Register all of our objects with a basic registry.\n$registry-&gt;add('acmeMetaBoxSubscriber', new AcmeMetaBoxSubscriber('add_meta_boxes'));\n\n$plugin = new Plugin($registry);\n$plugin-&gt;start();<\/code><\/pre>\n<p>Y, a partir de ah\u00ed, todo lo dem\u00e1s se pone en marcha.<\/p>\n<h2>\u00bfQu\u00e9 pasa con la funcionalidad m\u00e1s avanzada?<\/h2>\n<p>Hago esta pregunta porque ya he hablado un poco sobre esto anteriormente en la publicaci\u00f3n. Es decir, habl\u00e9 de:<\/p>\n<ol>\n<li>la idea de volver a publicar datos en el servidor (y probablemente leerlos de nuevo),<\/li>\n<li>y he hablado sobre el uso de interfaces.<\/li>\n<\/ol>\n<p>Ambas son cosas que creo que vale la pena explorar con m\u00e1s detalle. Pero antes de hacer eso, sentar las bases de c\u00f3mo organizo esta informaci\u00f3n es que est\u00e1 construida especialmente dado que se basa en publicaciones anteriores como <strong><a href=\"https:\/\/wordpress.mediadoma.com\/es\/usando-el-patron-de-registro-en-wordpress\/\" title=\"el patr\u00f3n de registro\">el patr\u00f3n de registro<\/a><\/strong> y tambi\u00e9n organiza clases centradas en WordPress a trav\u00e9s de <strong><a href=\"https:\/\/wordpress.mediadoma.com\/es\/una-guia-simple-para-organizar-clases-centradas-en-wordpress\/\" title=\"metaboxes\">metaboxes<\/a><\/strong>.<\/p>\n<p><div id=\"PostUnique_PostSource\" style=\"padding-top: 50px\">Fuente de grabaci\u00f3n:  <a target=\"_blank\" rel=\"noopener nofollow\" href=\"\/\/tommcfarlin.com\" class=\"external external_icon\">tommcfarlin.com<\/a><\/div><\/p>\n","protected":false},"excerpt":{"rendered":"<p>La organizaci\u00f3n de tipos de WordPress, vistas, suscriptores y otro material relacionado puede ser sistem\u00e1tica. Esto es algo bueno ya que nos brinda una forma repetible de construir varios proyectos para nuestros clientes.<\/p>\n","protected":false},"author":1,"featured_media":162655,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":"","_wp_rev_ctl_limit":""},"categories":[861],"tags":[1172],"class_list":["post-230456","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-wordpress-2","tag-affiai-es"],"_links":{"self":[{"href":"https:\/\/wordpress.mediadoma.com\/es\/wp-json\/wp\/v2\/posts\/230456","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wordpress.mediadoma.com\/es\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/wordpress.mediadoma.com\/es\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/es\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/es\/wp-json\/wp\/v2\/comments?post=230456"}],"version-history":[{"count":0,"href":"https:\/\/wordpress.mediadoma.com\/es\/wp-json\/wp\/v2\/posts\/230456\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/es\/wp-json\/wp\/v2\/media\/162655"}],"wp:attachment":[{"href":"https:\/\/wordpress.mediadoma.com\/es\/wp-json\/wp\/v2\/media?parent=230456"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/es\/wp-json\/wp\/v2\/categories?post=230456"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/es\/wp-json\/wp\/v2\/tags?post=230456"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}