{"id":230839,"date":"2022-12-15T11:17:00","date_gmt":"2022-12-15T08:17:00","guid":{"rendered":"https:\/\/wordpress.mediadoma.com\/?p=230839"},"modified":"2022-12-17T15:09:14","modified_gmt":"2022-12-17T12:09:14","slug":"widgets-de-wordpress-refactorizacion-parte-4","status":"publish","type":"post","link":"https:\/\/wordpress.mediadoma.com\/es\/widgets-de-wordpress-refactorizacion-parte-4\/","title":{"rendered":"Widgets de WordPress: Refactorizaci\u00f3n, Parte 4"},"content":{"rendered":"\n<p>Hemos implementado una cantidad significativa de cambios en el modelo est\u00e1ndar de widgets de WordPress. Si no ha estado siguiendo, le recomiendo comenzar desde el principio de la serie y ponerse al d\u00eda.<\/p>\n<p>Sin embargo, si ha estado siguiendo y tambi\u00e9n est\u00e1 ejecutando algunas de las herramientas de calidad de c\u00f3digo que examinan el estado del proyecto, notar\u00e1 algunos errores en la consola.<\/p>\n<p>Normalmente, este es el punto en el que recomiendo prestar atenci\u00f3n a lo que comparte y luego corregir lo que informa, pero a\u00fan no hemos llegado all\u00ed.<\/p>\n<p>Por ejemplo, algunos de los errores que est\u00e1n mostrando nuestras herramientas en este momento se basan en el hecho de que tenemos variables sin usar. Por supuesto, ese es el caso, sin embargo, porque no hemos comenzado a construir un widget.<\/p>\n<p>Pero todav\u00eda hay algunas clases concretas que debemos implementar.<\/p>\n<h2>El modelo de widget de WordPress: refactorizaci\u00f3n, parte 4<\/h2>\n<p>Uno de los problemas que a\u00fan existen en el c\u00f3digo tal como est\u00e1 ahora es que el constructor del widget est\u00e1 registrando funciones y esto no es bueno.<\/p>\n<p>El prop\u00f3sito de un constructor es establecer los valores de las propiedades de la clase, no implementar ning\u00fan tipo de l\u00f3gica. Esto se debe a algunas razones:<\/p>\n<ul>\n<li>crea un fuerte acoplamiento o dependencias entre las clases en el proyecto cada vez que se instancia una clase dada,<\/li>\n<li>introduce la l\u00f3gica empresarial en una funci\u00f3n que no pretende contener dicha funcionalidad,<\/li>\n<li>hace que sea dif\u00edcil probar una clase de forma aislada.<\/li>\n<\/ul>\n<p>La forma de manejar esto es doble:<\/p>\n<ol>\n<li>agregue un Registro que podamos usar para registrar clases en la aplicaci\u00f3n (y pasarlas con la menor cantidad de dependencias posible, lo cual explicar\u00e9 m\u00e1s adelante),<\/li>\n<li>crear suscriptores que puedan manejar la l\u00f3gica empresarial en funci\u00f3n de un enlace espec\u00edfico.<\/li>\n<\/ol>\n<p>En las siguientes tres publicaciones:<\/p>\n<ol>\n<li>veremos c\u00f3mo crear un Registro,<\/li>\n<li>c\u00f3mo podemos introducirlo en el archivo de arranque,<\/li>\n<li>y luego observe c\u00f3mo crear suscriptores para cada una de nuestras funciones (que no deber\u00eda ser demasiado dif\u00edcil dado lo que hicimos en la publicaci\u00f3n anterior y lo que estamos haciendo en esta publicaci\u00f3n).<\/li>\n<\/ol>\n<h3>Crear el registro<\/h3>\n<p>Antes de escribir el c\u00f3digo para el Registro, es importante tener en cuenta cu\u00e1l es su prop\u00f3sito principal. En pocas palabras, la clase debe contener una referencia a cualquier clase que est\u00e9, ejem, registrada con ella.<\/p>\n<p>Esto se hace pasando una referencia a un objeto dado a una funci\u00f3n y tambi\u00e9n vincul\u00e1ndola a una clave para que podamos recuperarla f\u00e1cilmente m\u00e1s tarde.<\/p>\n<h4>Consideraciones iniciales<\/h4>\n<p>Pero hay algunas cosas a considerar. Por ejemplo:<\/p>\n<p>si un objeto ya existe dentro del registro para una clave dada, entonces debemos lanzar una excepci\u00f3n; si un usuario intenta tomar un objeto del registro con una clave dada, entonces deber\u00eda lanzar una excepci\u00f3n<\/p>\n<p>Por supuesto, no necesariamente tiene que lanzar excepciones. En su lugar, tambi\u00e9n puede mostrar mensajes de error, devolver valores nulos o vac\u00edos, o lo que elija.<\/p>\n<p>En segundo lugar, el registro debe poder devolver una lista de todos los suscriptores que contiene para que puedan registrarse en WordPress (que es lo que veremos en la pr\u00f3xima publicaci\u00f3n).<\/p>\n<p>Sin embargo, para hacer esto, debemos asegurarnos de que sea compatible con todos los suscriptores y aqu\u00ed es donde entra en juego la noci\u00f3n de AbstractSubscriber de <a href=\"https:\/\/wordpress.mediadoma.com\/es\/widgets-de-wordpress-refactorizacion-parte-3\/\" title=\"la publicaci\u00f3n anterior .\">la publicaci\u00f3n anterior .<\/a> Es decir, mientras una clase sea una clase secundaria de esa clase, entonces estamos bien.<\/p>\n<h4>Creando el Registro<\/h4>\n<p>Dicho esto, planeemos lo siguiente:<\/p>\n<ul>\n<li>Crearemos una clase de Registro y la colocaremos en un espacio de nombres de Utilidades (y, por lo tanto, en un directorio) si a\u00fan no existe en su trabajo.<\/li>\n<li>Haremos que el registro mantenga una referencia a todos sus objetos en una matriz asociativa.<\/li>\n<li>Necesitamos m\u00e9todos para <strong>agregar<\/strong> y <strong>obtener<\/strong> un suscriptor individual y luego uno para recuperar la lista de suscriptores completos.<\/li>\n<\/ul>\n<p>El resguardo de la clase se ver\u00e1 <a href=\"https:\/\/gist.github.com\/tommcfarlin\/b45606bde5d777e88fd5e3988f610dea#file-00-registry-stub-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">as\u00ed:<\/a><\/p>\n<pre><code>&lt;?php\n\nclass Registry extends AbstractSubscriber\n{\n    public function __construct()\n    {\n    }\n\n    public function add($id, $obj)\n    {\n    }\n\n    public function get($id)\n    {\n    }\n\n    public function getRegisteredSubscribers()\n    {\n    }\n}\n<\/code><\/pre>\n<p>A continuaci\u00f3n, <a href=\"https:\/\/gist.github.com\/tommcfarlin\/b45606bde5d777e88fd5e3988f610dea#file-01-registry-constructor-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">podemos definir la propiedad b\u00e1sica<\/a>, una matriz, e inicializarla en el constructor:<\/p>\n<pre><code>&lt;?php\n\nclass Registry\n{\n    private $registry;\n\n    public function __construct()\n    {\n        $this-&gt;registry = [];\n    }\n\n    \/\/ ...\n\n}<\/code><\/pre>\n<p>Despu\u00e9s de eso, <a href=\"https:\/\/gist.github.com\/tommcfarlin\/b45606bde5d777e88fd5e3988f610dea#file-02-registry-add-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">podemos crear el m\u00e9todo add<\/a>. Recuerde que en mi implementaci\u00f3n, opt\u00e9 por lanzar una excepci\u00f3n si ya se defini\u00f3 una clave, pero no tiene que hacerlo.<\/p>\n<pre><code>&lt;?php\n\npublic function add($id, $obj)\n{\n    if (isset($this-&gt;registry[$id])) {\n        throw new Exception('An object already exists for this given key.');\n    }\n    $this-&gt;registry[$id] = $obj;\n}<\/code><\/pre>\n<p>De manera similar, <a href=\"https:\/\/gist.github.com\/tommcfarlin\/b45606bde5d777e88fd5e3988f610dea#file-03-registry-get-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">el m\u00e9todo get<\/a> devolver\u00e1 una referencia a la instancia de un objeto identificado con esa clave. Si la clave no est\u00e1 configurada, generar\u00e1 una excepci\u00f3n. Si est\u00e1 configurado, pero no existe ning\u00fan objeto, devolveremos nulo.<\/p>\n<pre><code>&lt;?php\n\npublic function get($id)\n{\n    if (!isset($this-&gt;registry[$id])) {\n        throw new Exception('No object exists for the specified key.');\n    }\n\n    return $this-&gt;registry[$id] ?? null;\n}<\/code><\/pre>\n<p>Finalmente, necesitamos un m\u00e9todo para devolver todos los suscriptores registrados. En una publicaci\u00f3n futura, el uso de esto ser\u00e1 mucho m\u00e1s evidente, pero por ahora, tenga en cuenta que crearemos una matriz de cualquier clase que sea una instancia de la clase <strong>AbstractSubscriber<\/strong> y <a href=\"https:\/\/gist.github.com\/tommcfarlin\/b45606bde5d777e88fd5e3988f610dea#file-04-registry-get-subscribers-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">luego devolveremos la matriz filtrada.<\/a><\/p>\n<pre><code>&lt;?php\n\npublic function getRegisteredSubscribers()\n{\n    $subscribers = [];\n    foreach ($this-&gt;registry as $object) {\n        if ($object instanceof AbstractSubscriber) {\n            $subscribers[] = $object;\n        }\n    }\n\n    return array_filter($subscribers);\n}<\/code><\/pre>\n<p>En este punto, <a href=\"https:\/\/gist.github.com\/tommcfarlin\/b45606bde5d777e88fd5e3988f610dea#file-05-registry-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">tenemos la clase<\/a> completa (completa con documentaci\u00f3n):<\/p>\n<pre><code>&lt;?php\n\n\/*\n * This file is part of the WordPress Widget Boilerplate\n *\n * (c) Tom McFarlin &lt;tom@tommcfarlin.com&gt;\n *\n * This source file is subject to the GPL license that is bundled\n * with this source code in the file LICENSE.\n *\/\n\nnamespace WordPressWidgetBoilerplateUtilities;\n\nuse Exception;\nuse WordPressWidgetBoilerplateSubscriberAbstractSubscriber;\n\n\/**\n * This class services as a simple container that can be used to pass objects\n * around the plugin.\n *\n * To use this class you'd make a call to the registry by saying Registry-&gt;get(),\n * then making a class to `register()` and `retrieve()` on an instance of the object.\n *\/\nclass Registry\n{\n    \/**\n     * @var array an array used to maintain the objects registered with the plugin\n     *\/\n    private $registry;\n\n    \/**\n     * Initializes the class by setting up the registry.\n     *\/\n    public function __construct()\n    {\n        $this-&gt;registry = [];\n    }\n\n    \/**\n     * Registers an object with the registry with the specified ID; however, will throw an\n     * exception if the ID is already referencing an object.\n     *\n     * @param string $id  an ID by which the specified object will be referenced\n     * @param mixed  $obj an instance of an object to store in the registry\n     *\n     * @throws Exception if an object already exists for the specified key\n     *\/\n    public function add($id, $obj)\n    {\n        if (isset($this-&gt;registry[$id])) {\n            throw new Exception('An object already exists for this given key.');\n        }\n        $this-&gt;registry[$id] = $obj;\n    }\n\n    \/**\n     * @param string $id the ID for the object that we wish to retrieve\n     *\n     * @throws Exception if no object exists for the specified key\n     *\n     * @return mixed a reference to the object or null\n     *\/\n    public function get($id)\n    {\n        if (!isset($this-&gt;registry[$id])) {\n            throw new Exception('No object exists for the specified key.');\n        }\n\n        return $this-&gt;registry[$id] ?? null;\n    }\n\n    \/**\n     * @return array all of the the Subscribers that should be registered with WordPress\n     *\/\n    public function getRegisteredSubscribers()\n    {\n        $subscribers = [];\n        foreach ($this-&gt;registry as $object) {\n            if ($object instanceof AbstractSubscriber) {\n                $subscribers[] = $object;\n            }\n        }\n\n        return array_filter($subscribers);\n    }\n}\n<\/code><\/pre>\n<p>Ahora necesitamos agregarlo al bootstrap de nuestro complemento.<\/p>\n<h2>Antes de Bootstrap, aunque<\/h2>\n<p>Como se mencion\u00f3 anteriormente en la publicaci\u00f3n, debemos agregar esto al arranque del complemento. Sin embargo, para hacer esto, necesitamos definir nuestro propio filtro para que podamos pasar f\u00e1cilmente el registro por el resto del complemento (cuando llegue el momento de hacerlo).<\/p>\n<p>Sin embargo, antes de hacer eso, es importante asegurarse de que tiene un buen manejo del Registro que acabamos de crear, que encaja en el complemento y que est\u00e1 rastreando con la rama de <a href=\"https:\/\/github.com\/tommcfarlin\/WordPress-Widget-Boilerplate\/tree\/develop\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">desarrollo<\/a> que tenemos hasta ahora.<\/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>Un problema que todav\u00eda existe en el c\u00f3digo tal como est\u00e1 ahora es que el constructor del widget de WordPress est\u00e1 registrando funciones y esto no es bueno.<\/p>\n","protected":false},"author":1,"featured_media":223984,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":"","_wp_rev_ctl_limit":""},"categories":[892,716,861],"tags":[1172],"class_list":["post-230839","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-codigo","category-desarrollador","category-wordpress-2","tag-affiai-es"],"_links":{"self":[{"href":"https:\/\/wordpress.mediadoma.com\/es\/wp-json\/wp\/v2\/posts\/230839","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=230839"}],"version-history":[{"count":0,"href":"https:\/\/wordpress.mediadoma.com\/es\/wp-json\/wp\/v2\/posts\/230839\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/es\/wp-json\/wp\/v2\/media\/223984"}],"wp:attachment":[{"href":"https:\/\/wordpress.mediadoma.com\/es\/wp-json\/wp\/v2\/media?parent=230839"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/es\/wp-json\/wp\/v2\/categories?post=230839"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/es\/wp-json\/wp\/v2\/tags?post=230839"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}