{"id":229418,"date":"2022-11-01T10:08:00","date_gmt":"2022-11-01T07:08:00","guid":{"rendered":"https:\/\/wordpress.mediadoma.com\/?p=229418"},"modified":"2022-11-09T06:57:28","modified_gmt":"2022-11-09T03:57:28","slug":"registrando-hooks-do-wordpress-usando-outra-classe","status":"publish","type":"post","link":"https:\/\/wordpress.mediadoma.com\/pt-pt\/registrando-hooks-do-wordpress-usando-outra-classe\/","title":{"rendered":"Registrando Hooks do WordPress usando outra classe"},"content":{"rendered":"\n<p>No <a href=\"https:\/\/wordpress.mediadoma.com\/pt-pt\/construtores-de-plugins-do-wordpress-nao-devem-definir-ganchos\/\" title=\"post de ontem\" >post de ontem<\/a>, falei sobre os construtores de plugins do WordPress e a raz\u00e3o de por que os hooks n\u00e3o deveriam estar no construtor.<\/p>\n<p>Embora eu tenha mencionado v\u00e1rias maneiras de lidar com o registro de ganchos, n\u00e3o me preocupei em entrar em detalhes para cada uma dessas estrat\u00e9gias. No que me diz respeito, eles merecem seu pr\u00f3prio artigo para fornecer o m\u00e1ximo de detalhes poss\u00edvel sobre como configurar algo.<\/p>\n<p>Por exemplo, um dos m\u00e9todos que compartilhei afirmou:<\/p>\n<ul>\n<li>\u00c9 poss\u00edvel criar uma classe que mantenha um registro de objetos e os ganchos com o WordPress.<\/li>\n<\/ul>\n<p>Em outras palavras, trata-se de registrar hooks do WordPress usando uma abordagem orientada a objetos para diminuir o acoplamento e aumentar a coes\u00e3o entre os componentes do plug-in.<\/p>\n<p>Mas o que isso significa mesmo? Quais s\u00e3o as vantagens que ele traz, como \u00e9 configurado e como \u00e9 usado?<\/p>\n<h2>Registrando ganchos do WordPress<\/h2>\n<p>Se voc\u00ea est\u00e1 lendo isso, provavelmente est\u00e1 familiarizado com o <a href=\"https:\/\/codex.wordpress.org\/Plugin_API#Hooks:_Actions_and_Filters\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">sistema de gancho<\/a> do WordPress, a ordem de como eles s\u00e3o acionados e como uma fun\u00e7\u00e3o ou classe pode registrar suas fun\u00e7\u00f5es com o WordPress para que possam executar qualquer trabalho que precisem.<\/p>\n<p>E muitas vezes vemos classes fazendo isso por conta pr\u00f3pria. Dependendo do projeto, eu mesmo fa\u00e7o. Para quem n\u00e3o conhece, geralmente \u00e9 <a href=\"https:\/\/gist.github.com\/tommcfarlin\/340900ba153fa9c3b30b83f7b163210c#file-00-plugins-loaded-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">algo assim<\/a> :<\/p>\n<pre><code>&lt;?php\n\nadd_action( 'plugins_loaded', 'acme_start' );\n\/**\n * Start the machine.\n * https:\/\/www.youtube.com\/watch?v=ysoMOefPyRs\n *\/\nfunction acme_start() {\n    $plugin = new AcmeColumn();\n}\n<\/code><\/pre>\n<p>Mas tudo isso pode ser dividido em classes mais coesas para, em \u00faltima an\u00e1lise, dar a elas ainda menos responsabilidade (uma coisa boa) e diminuir o acoplamento entre uma classe ou conjunto de classes com o WordPress.<\/p>\n<p>Um exemplo de um design que vou detalhar neste post.<\/p>\n<p>A natureza contra-intuitiva disso, por\u00e9m, \u00e9 que exigir\u00e1 pelo menos uma outra classe. Mas aqui est\u00e1 como funciona.<\/p>\n<h2>Configurando<\/h2>\n<p>Para os prop\u00f3sitos deste exemplo, usaremos apenas uma classe simples que registrar\u00e1 algum tipo de a\u00e7\u00e3o com o WordPress. A ideia para a arquitetura funciona mais ou menos assim:<\/p>\n<ol>\n<li>Existe a classe principal que tem a fun\u00e7\u00e3o que queremos conectar ao WordPress.<\/li>\n<li>Existe uma classe respons\u00e1vel por orquestrar a conex\u00e3o da fun\u00e7\u00e3o da classe ao WordPress.<\/li>\n<\/ol>\n<p>F\u00e1cil o suficiente, certo? Mas aqui est\u00e1 o problema: a classe respons\u00e1vel por registrar as fun\u00e7\u00f5es de uma determinada classe com o WordPress \u00e9 o ponto que requer uma decis\u00e3o de design.<\/p>\n<p>Primeiro, vamos chamar a classe <strong>HookRegistry<\/strong> para que possamos nos referir a ela corretamente. Em seguida, vamos chamar a classe com as fun\u00e7\u00f5es que queremos conectar <strong>AcmeColumn<\/strong> simplesmente para representar uma classe que adiciona uma nova coluna ao painel da p\u00e1gina na \u00e1rea de administra\u00e7\u00e3o do WordPress.<\/p>\n<p>Com isso em vigor, a decis\u00e3o de design se resume a isso:<\/p>\n<ol>\n<li><strong>O HookRegistery<\/strong> deve saber sobre <strong>AcmeColumn?<\/strong><\/li>\n<li><strong>A AcmeColumn<\/strong> deve saber sobre o <strong>HookRegistry<\/strong>? <\/li>\n<\/ol>\n<p>Eu sei que existem outras maneiras de organizar isso e tamb\u00e9m existem estrat\u00e9gias de como lidar com isso (como <a href=\"https:\/\/carlalexander.ca\/dependency-inversion-principle-wordpress\/\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">invers\u00e3o de controle<\/a>) e esses s\u00e3o t\u00f3picos que valem a pena explorar, mas para manter essa ideia inicial o mais direta poss\u00edvel, vou tabelar isso para uma postagem futura.<\/p>\n<h3>Usando a classe<\/h3>\n<p>Dadas as op\u00e7\u00f5es acima, passaremos uma inst\u00e2ncia de <strong>AcmeColumn<\/strong> para o <strong>HookRegistry<\/strong> quando as classes forem instanciadas durante o processo inicial de inicializa\u00e7\u00e3o do plugin WordPress. Isso pode ser algo <a href=\"https:\/\/gist.github.com\/tommcfarlin\/340900ba153fa9c3b30b83f7b163210c#file-01-startup-process-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">assim<\/a> :<\/p>\n<pre><code>&lt;?php\n\nadd_action( 'plugins_loaded', 'acme_start' );\n\/**\n * Start the machine.\n * https:\/\/www.youtube.com\/watch?v=ysoMOefPyRs\n *\/\nfunction acme_start() {\n\n  $registry    = new HookRegistry();\n\n  $acme_column = new AcmeColumn( $registry );\n  $acme_column-&gt;start();\n}\n<\/code><\/pre>\n<p>Em seguida, sempre que for a hora de <strong>AcmeColumn\u00a0<\/strong> registrar sua fun\u00e7\u00e3o no WordPress, chamaremos o <strong>HookRegistry<\/strong> e o instruiremos a faz\u00ea-lo.<\/p>\n<p>Primeiro, <a href=\"https:\/\/gist.github.com\/tommcfarlin\/340900ba153fa9c3b30b83f7b163210c#file-01-acme-column-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">AcmeColumn<\/a> :<\/p>\n<pre><code>&lt;?php\n\nclass AcmeColumn {\n\n    private $registry;\n\n    public function __construct( $registry) {\n        $this-&gt;registry = $registry;\n    }\n\n    public function start() {\n        $registry-&gt;add_hook( 'filter', 'manage_edit-page_columns', $this, 'add_page_column' );\n    }\n\n    public function add_page_column( $page_columns) {\n\n        $page_columns['template'] = 'Acme Column';\n        return $page_columns;\n    } \n}\n<\/code><\/pre>\n<p>Em seguida, o <strong><a href=\"https:\/\/gist.github.com\/tommcfarlin\/340900ba153fa9c3b30b83f7b163210c#file-02-hook-registry-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">HookRegistry<\/a> :<\/strong><\/p>\n<pre><code>&lt;?php\n\nclass HookRegistry {\n\n  public add_hook( $type, $name, $object, $method) {\n\n    $type = strtolower( $type );\n    if ('filter' !== $type || 'action' !== $type) {\n      return new WP_Error( '1', 'No proper hook type defined.' );\n    }\n  }\n\n  private function add_filter( $name, $object, $method) {\n    add_filter( $name, array( $object, $method) );\n  }\n\n  private function add_action( $name, $object, $method) {\n    add_action( $name, array( $object, $method) );\n  }\n}\n<\/code><\/pre>\n<p>Opcionalmente, tamb\u00e9m podemos manter uma lista das v\u00e1rias classes e ganchos que foram registrados. Isso pode ou n\u00e3o ser \u00fatil dependendo de sua implementa\u00e7\u00e3o, ent\u00e3o estou compartilhando apenas como um &quot;aqui est\u00e1 algo que voc\u00ea pode querer fazer&quot;.<\/p>\n<p>E isso poderia <a href=\"https:\/\/gist.github.com\/tommcfarlin\/340900ba153fa9c3b30b83f7b163210c#file-03-hook-registry-improved-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">ser assim<\/a> (usando uma matriz associativa simples):<\/p>\n<pre><code>&lt;?php\n\nclass HookRegistry {\n\n  private $registry;\n\n  public function __construct() {\n    $this-&gt;registery = array(); \n  }\n\n  public add_hook( $id, $type, $name, $object, $method) {\n\n    $type = strtolower( $type );\n    if ('filter' !== $type || 'action' !== $type) {\n      return new WP_Error( '1', 'No proper hook type defined.' );\n    }\n\n    if ('filter' === $type) {\n      $this-&gt;add_filter( $name, $object, $method );\n    } else {\n      $this-&gt;add_action( $name, $object, $method );\n    }\n\n    $hook_info = array(\n      $type,\n      $name,\n      $object,\n      $method,\n    );\n    $this-&gt;registry[ $id ] = $hook_info;\n  }\n\n  private function add_filter( $name, $object, $method) {\n    add_filter( $name, array( $object, $method) );\n  }\n\n  private function add_action( $name, $object, $method) {\n    add_action( $name, array( $object, $method) );\n  }\n}\n<\/code><\/pre>\n<p>Observe que na classe acima, agora ele aceita um <strong>$id<\/strong> como par\u00e2metro. Existem v\u00e1rias maneiras de identificar as informa\u00e7\u00f5es que est\u00e3o entrando em um registro, a mais f\u00e1cil delas \u00e9 criar a ID voc\u00ea mesmo.<\/p>\n<p>No entanto, se voc\u00ea quiser usar algo como o nome do gancho ou o nome da classe, isso tamb\u00e9m funcionar\u00e1. Apenas observe que, como \u00e9 um array associativo, ele s\u00f3 pode manter um \u00fanico valor por chave, ent\u00e3o voc\u00ea pode acabar destruindo dados anteriores se n\u00e3o for cuidadoso.<\/p>\n<p>Independentemente disso, isso \u00e9 algo que considero opcional, mas se for implementado, \u00e9 importante garantir que voc\u00ea tenha as fun\u00e7\u00f5es adequadas para recuperar uma inst\u00e2ncia do objeto por uma chave.<\/p>\n<h2>Um de muitos<\/h2>\n<p>Como acontece com qualquer coisa relacionada a esse tipo de trabalho, \u00e9 poss\u00edvel rearquitetar ou reorientar isso de uma maneira que funcione de maneira diferente ou que atenda \u00e0s suas necessidades. O objetivo n\u00e3o \u00e9 mostrar o padr\u00e3o definitivo de como fazer algo, mas uma maneira de abord\u00e1-lo e adapt\u00e1-lo (como qualquer padr\u00e3o de design).<\/p>\n<p>Al\u00e9m disso, o objetivo \u00e9 garantir que nossas classes mantenham as responsabilidades para as quais foram criadas, permitindo que elas se registrem no WordPress conforme necess\u00e1rio. Desta vez, por\u00e9m, a classe n\u00e3o precisa fazer isso sozinha.<\/p>\n<p>Em vez disso, ele passa a responsabilidade para uma classe que tem a responsabilidade exclusiva de registrar esses ganchos. Portanto, embora introduza mais classes, aumenta a coes\u00e3o e diminui o acoplamento.<\/p>\n<p>Isso oferece benef\u00edcios em manuten\u00e7\u00e3o, testes e design geral.<\/p>\n<p><div id=\"PostUnique_PostSource\" style=\"padding-top: 50px\">Fonte de grava\u00e7\u00e3o:  <a target=\"_blank\" rel=\"noopener nofollow\" href=\"\/\/tommcfarlin.com\" class=\"external external_icon\">tommcfarlin.com<\/a><\/div><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Trata-se de registrar ganchos do WordPress usando uma abordagem orientada a objetos para diminuir o acoplamento e aumentar a coes\u00e3o no plug-in.<\/p>\n","protected":false},"author":1,"featured_media":223973,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":"","_wp_rev_ctl_limit":""},"categories":[898,722,920,816,867],"tags":[1170],"class_list":["post-229418","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-codigo-2","category-desenvolvedor","category-outro","category-plug-ins","category-wordpress-8","tag-affiai-pt-pt"],"_links":{"self":[{"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/posts\/229418","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/comments?post=229418"}],"version-history":[{"count":0,"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/posts\/229418\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/media\/223973"}],"wp:attachment":[{"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/media?parent=229418"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/categories?post=229418"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/tags?post=229418"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}