{"id":44109,"date":"2021-09-09T12:59:37","date_gmt":"2021-09-09T10:59:37","guid":{"rendered":"https:\/\/kinsta.com\/?p=100908"},"modified":"2025-02-07T11:08:59","modified_gmt":"2025-02-07T14:08:59","slug":"abstracao-wordpress","status":"publish","type":"post","link":"https:\/\/kinsta.com\/pt\/blog\/abstracao-wordpress\/","title":{"rendered":"Abstra\u00e7\u00e3o WordPress: Melhores Pr\u00e1ticas e Plugins de Abstra\u00e7\u00e3o WordPress"},"content":{"rendered":"<p>O WordPress \u00e9 um CMS antigo, mas tamb\u00e9m o <a href=\"https:\/\/kinsta.com\/pt\/wordpress-quota-mercado\/\">mais usado<\/a>. Gra\u00e7as ao seu hist\u00f3rico de suporte a vers\u00f5es PHP desatualizadas e c\u00f3digos legados, ainda falta implementar pr\u00e1ticas modernas de codifica\u00e7\u00e3o &#8211; a abstra\u00e7\u00e3o do WordPress \u00e9 um exemplo.<\/p>\n<p>Por exemplo, seria muito melhor dividir o c\u00f3digo do n\u00facleo do WordPress em pacotes gerenciados pelo Composer. Ou talvez, para carregar automaticamente classes WordPress a partir de caminhos de arquivos.<\/p>\n<p>Este artigo ir\u00e1 ensin\u00e1-lo a abstrair o c\u00f3digo WordPress manualmente e a usar os recursos de plugins de abstra\u00e7\u00e3o WordPress.<\/p>\n<div><\/div><kinsta-auto-toc heading=\"Table of Contents\" exclude=\"last\" list-style=\"arrow\" selector=\"h2\" count-number=\"-1\"><\/kinsta-auto-toc>\n<h2>Problemas com a integra\u00e7\u00e3o de ferramentas WordPress e PHP<\/h2>\n<p>Devido a sua arquitetura antiga, ocasionalmente encontramos problemas ao integrar o WordPress com ferramentas para bases de c\u00f3digo PHP, como o analisador est\u00e1tico <a href=\"https:\/\/phpstan.org\/\">PHPStan<\/a>, a biblioteca de testes de unidade <a href=\"https:\/\/phpunit.de\/\">PHPUnit<\/a> e a biblioteca de namespace-scoping <a href=\"https:\/\/github.com\/humbug\/php-scoper\">PHP-Scoper<\/a>. Por exemplo, considere os seguintes casos:<\/p>\n<ul>\n<li>Antes do <a href=\"https:\/\/kinsta.com\/pt\/blog\/wordpress-5-6\/\">WordPress 5.6<\/a> com suporte ao <a href=\"https:\/\/kinsta.com\/pt\/blog\/php-8\/\">PHP 8.0<\/a>, um relat\u00f3rio do Yoast descreveu como rodar o PHPStan no n\u00facleo do WordPress iria produzir <a href=\"https:\/\/developer.yoast.com\/blog\/the-2020-wordpress-and-php-8-compatibility-report\/#h-scanning-wordpress-with-phpstan\">milhares de problemas<\/a>.<\/li>\n<li>Devido ao seu ainda suporte ao PHP 5.6, as su\u00edtes de teste do WordPress atualmente <a href=\"https:\/\/core.trac.wordpress.org\/ticket\/46149\">s\u00f3 suportam PHPUnit at\u00e9 a vers\u00e3o 7.5<\/a>, que chegou ao fim da vida.<\/li>\n<li>Scoping WordPress plugins via PHP-Scoper <a href=\"https:\/\/github.com\/humbug\/php-scoper#wordpress\">\u00e9 muito desafiador<\/a>.<\/li>\n<\/ul>\n<p>O c\u00f3digo WordPress dentro de nossos projetos ser\u00e1 apenas uma fra\u00e7\u00e3o do total; o projeto tamb\u00e9m conter\u00e1 c\u00f3digo de neg\u00f3cios agn\u00f3stico do CMS subjacente. No entanto, apenas por ter algum c\u00f3digo WordPress, o projeto pode n\u00e3o se integrar corretamente com as ferramentas.<\/p>\n<p>Por causa disso, poderia fazer sentido dividir o projeto em pacotes, alguns deles contendo c\u00f3digo WordPress e outros tendo apenas c\u00f3digo de neg\u00f3cios usando PHP &#8220;vanilla&#8221; e sem c\u00f3digo WordPress. Desta forma, estes \u00faltimos pacotes n\u00e3o ser\u00e3o afetados pelos problemas descritos acima, mas podem ser perfeitamente integrados com o tooling.<\/p>\n<h2>O que \u00e9 abstra\u00e7\u00e3o de c\u00f3digo?<\/h2>\n<p>A abstra\u00e7\u00e3o de c\u00f3digo remove depend\u00eancias fixas do c\u00f3digo, produzindo pacotes que interagem uns com os outros atrav\u00e9s de contratos. Estes pacotes podem ent\u00e3o ser adicionados a diferentes aplicativos com diferentes pilhas, maximizando a sua usabilidade. O resultado da abstra\u00e7\u00e3o de c\u00f3digo \u00e9 uma base de c\u00f3digo claramente desacoplada, baseada nos seguintes pilares:<\/p>\n<ol>\n<li>C\u00f3digo contra interfaces, n\u00e3o implementa\u00e7\u00f5es.<\/li>\n<li>Crie pacotes e distribua-os atrav\u00e9s do Composer.<\/li>\n<li>Cole todas as partes atrav\u00e9s de inje\u00e7\u00e3o de depend\u00eancia.<\/li>\n<\/ol>\n\n<h2>C\u00f3digo contra interfaces, n\u00e3o contra implementa\u00e7\u00f5es<\/h2>\n<p>A codifica\u00e7\u00e3o contra interfaces \u00e9 a pr\u00e1tica de usar contratos para que pe\u00e7as de c\u00f3digo interajam umas com as outras. Um contrato \u00e9 simplesmente uma interface PHP (ou qualquer linguagem diferente) que define que fun\u00e7\u00f5es est\u00e3o dispon\u00edveis e suas assinaturas, ou seja, que entradas recebem e suas sa\u00eddas.<\/p>\n<p>Uma interface declara a inten\u00e7\u00e3o da funcionalidade sem explicar como a funcionalidade ser\u00e1 implementada. Ao acessar funcionalidades atrav\u00e9s de interfaces, nosso <a href=\"https:\/\/kinsta.com\/pt\/blog\/monitoramento-desempenho-aplicativos\/\">aplicativo<\/a> pode contar com pe\u00e7as de c\u00f3digo aut\u00f4nomas que atingem um objetivo espec\u00edfico sem saber, ou se preocupar com a forma como o fazem. Desta forma, o aplicativo n\u00e3o precisa ser adaptada para mudar para outro peda\u00e7o de c\u00f3digo que atinja o mesmo objetivo &#8211; por exemplo, de um provedor diferente.<\/p>\n<h3>Exemplo de contratos<\/h3>\n<p>O c\u00f3digo a seguir usa o contrato da Symfony <code><a href=\"https:\/\/github.com\/symfony\/symfony\/blob\/302b844\/src\/Symfony\/Contracts\/Cache\/CacheInterface.php\">CacheInterface<\/a><\/code> e o contrato da <code><a href=\"https:\/\/github.com\/php-fig\/cache\/blob\/0a7c67d\/src\/CacheItemInterface.php\">CacheItemInterface<\/a><\/code> da<span style=\"font-family: Roboto, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif;font-size: 1rem\"> Recomenda\u00e7\u00e3o Padr\u00e3o do PHP (PSR) para implementar a funcionalidade de cache:<\/span><\/p>\n<pre><code class=\"language-php\">use Psr\\Cache\\CacheItemInterface;\nuse Symfony\\Contracts\\Cache\\CacheInterface;\n\n$value = $cache-&gt;get('my_cache_key', function (CacheItemInterface $item) {\n    $item-&gt;expiresAfter(3600);\n    return 'foobar';\n});<\/code><\/pre>\n<p><code>$cache<\/code> implementa a <code>CacheInterface<\/code>, que define o m\u00e9todo <code>get<\/code> para recuperar um objeto do cache. Ao aceder a esta funcionalidade atrav\u00e9s do contrato, o aplicativo pode ficar alheia ao local onde se encontra a cache. Seja na mem\u00f3ria, disco, banco de dados, rede ou em qualquer outro lugar. Mesmo assim, ele tem que executar a fun\u00e7\u00e3o. A <code>CacheItemInterface<\/code> define o m\u00e9todo que <code>expiresAfter<\/code> de declarar por quanto tempo o item deve ser mantido no cache. O aplicativo pode invocar este m\u00e9todo sem se preocupar com o que \u00e9 o objeto em cache; ela s\u00f3 se preocupa com quanto tempo ele deve ser mantido em cache.<\/p>\n<h2>Codifica\u00e7\u00e3o contra interfaces no WordPress<\/h2>\n<p>Como estamos abstraindo o c\u00f3digo WordPress, o resultado ser\u00e1 que o aplicativo n\u00e3o far\u00e1 refer\u00eancia direta ao <a href=\"https:\/\/kinsta.com\/pt\/blog\/editar-codigo-wordpress\/\">c\u00f3digo WordPress<\/a>, mas sempre atrav\u00e9s de uma interface. Por exemplo, a fun\u00e7\u00e3o <code>get_posts<\/code> do WordPress tem esta assinatura:<\/p>\n<pre><code class=\"language-php\">\/**\n * @param array $args\n * @return WP_Post[]|int[] Array of post objects or post IDs.\n *\/\nfunction get_posts( $args = null )\n<\/code><\/pre>\n<p>Em vez de invocar este m\u00e9todo diretamente, podemos acess\u00e1-lo atrav\u00e9s do contrato <code>Owner\\MyApp\\Contracts\\PostsAPIInterface<\/code>:<\/p>\n<pre><code class=\"language-php\">namespace Owner\\MyApp\\Contracts;\n\ninterface PostAPIInterface\n{\n  public function get_posts(array $args = null): PostInterface[]|int[];\n}<\/code><\/pre>\n<p>Observe que a fun\u00e7\u00e3o <code>get_posts<\/code> do WordPress pode retornar objetos da classe <code>WP_Post<\/code>, que \u00e9 espec\u00edfica para o WordPress. Ao abstrair o c\u00f3digo, \u00e9 necess\u00e1rio remover esse tipo de depend\u00eancia fixa. O m\u00e9todo <code>get_posts<\/code> no contrato retorna objetos do tipo <code>PostInterface<\/code>, permitindo que voc\u00ea fa\u00e7a refer\u00eancia \u00e0 classe <code>WP_Post<\/code> sem ser expl\u00edcito sobre ela. A classe <code>PostInterface<\/code> precisar\u00e1 fornecer acesso a todos os m\u00e9todos e atributos do <code>WP_Post<\/code>:<\/p>\n<pre><code class=\"language-php\">namespace Owner\\MyApp\\Contracts;\n\ninterface PostInterface\n{\n  public function get_ID(): int;\n  public function get_post_author(): string;\n  public function get_post_date(): string;\n  \/\/ ...\n}\n<\/code><\/pre>\n<p>A execu\u00e7\u00e3o desta estrat\u00e9gia pode mudar o nosso entendimento de onde o WordPress cabe na nossa pilha. Em vez de pensarmos no WordPress como o pr\u00f3prio aplicativo (sobre o qual instalamos temas e plugins), podemos pensar nele simplesmente como uma outra depend\u00eancia dentro do aplicativo, substitu\u00edvel como qualquer outro componente. (Mesmo que n\u00e3o substituamos o WordPress na pr\u00e1tica, ele <em>\u00e9 <\/em>substitu\u00edvel de um ponto de vista conceitual).<\/p>\n<h2>Cria\u00e7\u00e3o e distribui\u00e7\u00e3o de pacotes<\/h2>\n<p>O <a href=\"https:\/\/getcomposer.org\/\">Composer<\/a> \u00e9 um gerenciador de pacotes para PHP. Ele permite que aplicativos PHP recuperem pacotes (ou seja, peda\u00e7os de c\u00f3digo) de um reposit\u00f3rio e os instalem como depend\u00eancias. Para dissociar o aplicativo do WordPress, devemos distribuir seu c\u00f3digo em pacotes de dois tipos diferentes: aqueles contendo c\u00f3digo WordPress e os outros contendo l\u00f3gica de neg\u00f3cios (ou seja, sem c\u00f3digo WordPress).<\/p>\n<p>Finalmente, adicionamos todos os pacotes como depend\u00eancias no aplicativo, e os instalamos atrav\u00e9s do Composer. Como as ferramentas ser\u00e3o aplicadas aos pacotes de c\u00f3digo de neg\u00f3cios, estes devem conter a maior parte do c\u00f3digo do aplicativo; quanto maior a porcentagem, melhor. Fazer com que eles gerenciem cerca de 90% do c\u00f3digo geral \u00e9 um bom objetivo.<\/p>\n<h2>Extraindo o c\u00f3digo WordPress para dentro dos pacotes<\/h2>\n<p>Seguindo o exemplo anterior, os contratos <code>PostAPIInterface<\/code> e <code>PostInterface<\/code> ser\u00e3o adicionados ao pacote contendo o c\u00f3digo de neg\u00f3cios, e outro pacote incluir\u00e1 a implementa\u00e7\u00e3o desses contratos no WordPress. Para satisfazer a <code>PostInterface<\/code>, criamos uma classe <code>PostWrapper<\/code> que ir\u00e1 recuperar todos os atributos de um objeto <code>WP_Post<\/code>:<\/p>\n<pre><code class=\"language-php\">namespace Owner\\MyAppForWP\\ContractImplementations;\n\nuse Owner\\MyApp\\Contracts\\PostInterface;\nuse WP_Post;\n\nclass PostWrapper implements PostInterface\n{\n  private WP_Post $post;\n  \n  public function __construct(WP_Post $post)\n  {\n    $this-&gt;post = $post;\n  }\n\n  public function get_ID(): int\n  {\n    return $this-&gt;post-&gt;ID;\n  }\n\n  public function get_post_author(): string\n  {\n    return $this-&gt;post-&gt;post_author;\n  }\n\n  public function get_post_date(): string\n  {\n    return $this-&gt;post-&gt;post_date;\n  }\n\n  \/\/ ...\n}<\/code><\/pre>\n<p>Ao implementar <code>PostAPI<\/code>, uma vez que o m\u00e9todo <code>get_posts<\/code> retorna <code>PostInterface[]<\/code>, devemos converter objetos de <code>WP_Post<\/code> para <code>PostWrapper<\/code>:<\/p>\n<pre><code class=\"language-php\">namespace Owner\\MyAppForWP\\ContractImplementations;\n\nuse Owner\\MyApp\\Contracts\\PostAPIInterface;\nuse WP_Post;\n\nclass PostAPI implements PostAPIInterface\n{\n  public function get_posts(array $args = null): PostInterface[]|int[]\n  {\n    \/\/ This var will contain WP_Post[] or int[]\n    $wpPosts = \\get_posts($args);\n\n    \/\/ Convert WP_Post[] to PostWrapper[]\n    return array_map(\n      function (WP_Post|int $post) {\n        if ($post instanceof WP_Post) {\n          return new PostWrapper($post);\n        }\n        return $post\n      },\n      $wpPosts\n    );\n  }\n}\n<\/code><\/pre>\n<h2>Usando a inje\u00e7\u00e3o de depend\u00eancia<\/h2>\n<p>A inje\u00e7\u00e3o de depend\u00eancia \u00e9 um padr\u00e3o de design que permite a colagem de todas as pe\u00e7as do aplicativo de uma forma solta. Com a inje\u00e7\u00e3o de depend\u00eancia, o aplicativo acessa servi\u00e7os atrav\u00e9s de seus contratos, e as implementa\u00e7\u00f5es de contrato s\u00e3o &#8220;injetadas&#8221; no aplicativo atrav\u00e9s da configura\u00e7\u00e3o.<\/p>\n<p>Simplesmente mudando a configura\u00e7\u00e3o, podemos mudar facilmente de um fornecedor de contrato para outro. Existem v\u00e1rias bibliotecas de inje\u00e7\u00e3o de depend\u00eancia que podemos escolher. Aconselhamos escolher uma que siga as <a href=\"https:\/\/www.php-fig.org\/\">Recomenda\u00e7\u00f5es Padr\u00e3o do PHP<\/a> (frequentemente referidas como &#8220;PSR&#8221;), para que possamos facilmente substituir a biblioteca por outra, se a necessidade surgir. Em rela\u00e7\u00e3o \u00e0 inje\u00e7\u00e3o de depend\u00eancia, a biblioteca deve satisfazer a <a href=\"https:\/\/www.php-fig.org\/psr\/psr-11\/\">PSR-11<\/a>, que fornece a especifica\u00e7\u00e3o para uma &#8220;interface de recipiente&#8221;. Entre outras, as seguintes bibliotecas est\u00e3o em conformidade com o PSR-11:<\/p>\n<ul>\n<li><a href=\"https:\/\/github.com\/symfony\/dependency-injection\">A Depend\u00eancia de SymfonyInje\u00e7\u00e3o<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/PHP-DI\/PHP-DI\">PHP-DI<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/auraphp\/Aura.Di\">Aura.Di<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/thephpleague\/container\">Container (Inje\u00e7\u00e3o de Depend\u00eancia)<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/yiisoft\/di\">Yii Inje\u00e7\u00e3o de Depend\u00eancia<\/a><\/li>\n<\/ul>\n<h3>Acesso aos servi\u00e7os atrav\u00e9s do contentor de Servi\u00e7os<\/h3>\n<p>A biblioteca de inje\u00e7\u00e3o de depend\u00eancia disponibilizar\u00e1 um &#8220;recipiente de servi\u00e7o&#8221;, que resolve um contrato em sua classe de implementa\u00e7\u00e3o correspondente. O aplicativo deve contar com o contentor de servi\u00e7o para aceder a todas as funcionalidades. Por exemplo, enquanto n\u00f3s normalmente invocar\u00edamos diretamente as fun\u00e7\u00f5es do WordPress:<\/p>\n<pre><code class=\"language-php\">$posts = get_posts();<\/code><\/pre>\n<p>&#8230; com o contentor de servi\u00e7o, devemos primeiro obter o servi\u00e7o que satisfaz o\u00a0 <code>PostAPIInetrface<\/code> e executar a funcionalidade atrav\u00e9s dele:<\/p>\n<pre><code class=\"language-php\">use Owner\\MyApp\\Contracts\\PostAPIInterface;\n\n\/\/ Obtain the service container, as specified by the library we use\n$serviceContainer = ContainerBuilderFactory::getInstance();\n\n\/\/ The obtained service will be of class Owner\\MyAppForWP\\ContractImplementations\\PostAPI\n$postAPI = $serviceContainer-&gt;get(PostAPIInterface::class);\n\n\/\/ Now we can invoke the WordPress functionality\n$posts = $postAPI-&gt;get_posts();\n<\/code><\/pre>\n<h3>Usando a inje\u00e7\u00e3o de depend\u00eancia da Symfony<\/h3>\n<p><a href=\"https:\/\/symfony.com\/doc\/current\/components\/dependency_injection.html\">O componente Symfony&#8217;sDependency Injection<\/a> \u00e9 atualmente a mais popular biblioteca de inje\u00e7\u00e3o de depend\u00eancia. Ele permite que voc\u00ea configure o container de servi\u00e7o via PHP, YAML, ou c\u00f3digo XML. Por exemplo, para definir que o contrato <code>PostAPIInterface<\/code> \u00e9 satisfeito atrav\u00e9s da classe <code>PostAPI<\/code> \u00e9 configurado no YAML desta forma:<\/p>\n<pre><code class=\"language-yaml\">services:\n  Owner\\MyApp\\Contracts\\PostAPIInterface:\n    class: \\Owner\\MyAppForWP\\ContractImplementations\\PostAPI\n<\/code><\/pre>\n<p>A Symfony DependencyInjection tamb\u00e9m permite que inst\u00e2ncias de um servi\u00e7o sejam automaticamente injetadas (ou &#8220;autowired&#8221;) em qualquer outro servi\u00e7o que dependa dele. Al\u00e9m disso, torna f\u00e1cil definir que uma classe \u00e9 uma implementa\u00e7\u00e3o de seu pr\u00f3prio servi\u00e7o. Por exemplo, considere a <a href=\"https:\/\/github.com\/leoloso\/PoP\/blob\/8602e9041ac92f4683966eed5c4a90686b9395fa\/layers\/GraphQLAPIForWP\/plugins\/graphql-api-for-wp\/config\/hybrid-services.yaml\">seguinte configura\u00e7\u00e3o de YAML<\/a>:<\/p>\n<pre><code class=\"language-yaml\">services:\n  _defaults:\n    public: true\n    autowire: true\n\n  GraphQLAPI\\GraphQLAPI\\Registries\\UserAuthorizationSchemeRegistryInterface:\n    class: '\\GraphQLAPI\\GraphQLAPI\\Registries\\UserAuthorizationSchemeRegistry'\n\n  GraphQLAPI\\GraphQLAPI\\Security\\UserAuthorizationInterface:\n    class: '\\GraphQLAPI\\GraphQLAPI\\Security\\UserAuthorization'\n    \n  GraphQLAPI\\GraphQLAPI\\Security\\UserAuthorizationSchemes\\:\n    resource: '..\/src\/Security\/UserAuthorizationSchemes\/*'\n<\/code><\/pre>\n<p>Esta configura\u00e7\u00e3o define o seguinte:<\/p>\n<ul>\n<li>Contrato <code>UserAuthorizationSchemeRegistryInterface<\/code> \u00e9 satisfeito atrav\u00e9s da classe \u00a0<code>UserAuthorizationSchemeRegistry<\/code><\/li>\n<li>Contrato <code>UserAuthorizationInterface<\/code> \u00e9 satisfeita atrav\u00e9s da classe <code>UserAuthorization<\/code><\/li>\n<li>Todas as classes sob a pasta <code>UserAuthorizationSchemes\/<\/code> s\u00e3o uma implementa\u00e7\u00e3o de si mesmas<\/li>\n<li>Os servi\u00e7os devem ser injectados automaticamente uns nos outros (<code>autowire: true<\/code>)<\/li>\n<\/ul>\n<p>Vamos ver como funciona a cablagem autom\u00e1tica. A classe <code><a href=\"https:\/\/github.com\/leoloso\/PoP\/blob\/bd56f23b52a3e02966fdcbde4bc58f246a47a6e5\/layers\/GraphQLAPIForWP\/plugins\/graphql-api-for-wp\/src\/Security\/UserAuthorization.php\">UserAuthorization<\/a><\/code> depende do servi\u00e7o com contrato <code>UserAuthorizationSchemeRegistryInterface<\/code>:<\/p>\n<pre><code class=\"language-php\">class UserAuthorization implements UserAuthorizationInterface\n{\n  public function __construct(\n      protected UserAuthorizationSchemeRegistryInterface $userAuthorizationSchemeRegistry\n  ) {\n  }\n\n  \/\/ ...\n}<\/code><\/pre>\n<p>Gra\u00e7as ao <code>autowire: true<\/code>, o componente DependencyInjection ter\u00e1 automaticamente o servi\u00e7o <code>UserAuthorization<\/code> receber\u00e1 sua depend\u00eancia requerida, que \u00e9 uma inst\u00e2ncia do <code>UserAuthorizationSchemeRegistry<\/code>.<\/p>\n<h2>Quando abstrair<\/h2>\n<p>Abstrair o c\u00f3digo pode consumir tempo e esfor\u00e7o consider\u00e1veis, por isso s\u00f3 devemos assumi-lo quando os seus benef\u00edcios superarem os seus custos. As sugest\u00f5es a seguir s\u00e3o sugest\u00f5es de quando a abstra\u00e7\u00e3o do c\u00f3digo pode valer a pena. Voc\u00ea pode fazer isso usando trechos de c\u00f3digo neste artigo ou os plugins WordPress abstract sugeridos abaixo.<\/p>\n<h3>Obtendo acesso a ferramentas<\/h3>\n<p>Como mencionado anteriormente, <a href=\"https:\/\/github.com\/humbug\/php-scoper\/issues\/303\">rodar o PHP-Scoperno WordPress \u00e9 dif\u00edcil<\/a>. Desacoplando o c\u00f3digo do WordPress em pacotes distintos, torna-se exequ\u00edvel <a href=\"https:\/\/graphql-api.com\/blog\/graphql-api-for-wp-is-now-scoped-thanks-to-php-scoper\/\">escanear um plugin do WordPress<\/a> diretamente.<\/p>\n<h3>Redu\u00e7\u00e3o de tempo e custo de ferramentas<\/h3>\n<p>Executar um conjunto de testes PHPUnit leva mais tempo quando ele precisa inicializar e executar o WordPress do que quando n\u00e3o o faz. Menos tempo tamb\u00e9m pode se traduzir em menos dinheiro gasto rodando os testes &#8211; por exemplo, o <a href=\"https:\/\/kinsta.com\/pt\/blog\/que-github\/\">GitHub<\/a> Actions cobra pelos corredores hospedados no GitHub com base no tempo gasto usando-os.<\/p>\n<h3>Uma grande refatora\u00e7\u00e3o n\u00e3o \u00e9 necess\u00e1ria<\/h3>\n<p>Um projeto existente pode requerer uma refatora\u00e7\u00e3o pesada para introduzir a arquitetura necess\u00e1ria (inje\u00e7\u00e3o de depend\u00eancia, divis\u00e3o do c\u00f3digo em pacotes, etc.), dificultando a retirada. Abstrair o c\u00f3digo ao criar um projeto do zero o torna muito mais gerenci\u00e1vel.<\/p>\n<h3>C\u00f3digo de produ\u00e7\u00e3o para m\u00faltiplas plataformas<\/h3>\n<p>Ao extrair 90% do c\u00f3digo para um pacote CMS-agn\u00f3stico, podemos produzir uma vers\u00e3o de biblioteca que funciona para um CMS ou framework diferente, substituindo apenas 10% da base de c\u00f3digo global.<\/p>\n<h3>Migrando para uma plataforma diferente<\/h3>\n<p>Se precisarmos migrar um projeto de <a href=\"https:\/\/kinsta.com\/pt\/blog\/wordpress-vs-drupal\/\">Drupal para WordPress<\/a>, WordPress para <a href=\"https:\/\/kinsta.com\/pt\/blog\/laravel-9\/\">Laravel<\/a>, ou qualquer outra combina\u00e7\u00e3o, ent\u00e3o apenas 10% do c\u00f3digo deve ser reescrito &#8211; uma economia significativa.<\/p>\n<h2>Melhores pr\u00e1ticas<\/h2>\n<p>Enquanto desenhamos os contratos para abstrair nosso c\u00f3digo, h\u00e1 v\u00e1rias melhorias que podemos aplicar \u00e0 base de c\u00f3digo.<\/p>\n<h3>Aderir ao PSR-12<\/h3>\n<p>Ao definir a interface para acessar os m\u00e9todos do WordPress, devemos aderir ao <a href=\"https:\/\/www.php-fig.org\/psr\/psr-12\/\">PSR-12<\/a>. Esta especifica\u00e7\u00e3o recente visa reduzir o atrito cognitivo ao digitalizar c\u00f3digo de diferentes autores. Aderir \u00e0 PSR-12 implica renomear as fun\u00e7\u00f5es do WordPress.<\/p>\n<p>O WordPress funciona com o uso de <strong>snake_case<\/strong>, enquanto o PSR-12 usa o <strong>camelCase<\/strong>. Portanto, a fun\u00e7\u00e3o <code>get_posts<\/code> se tornar\u00e1 <code>getPosts<\/code>:<\/p>\n<pre><code class=\"language-php\">interface PostAPIInterface\n{\n  public function getPosts(array $args = null): PostInterface[]|int[];\n}\n<\/code><\/pre>\n<p>&#8230;e:<\/p>\n<pre><code class=\"language-php\">class PostAPI implements PostAPIInterface\n{\n  public function getPosts(array $args = null): PostInterface[]|int[]\n  {\n    \/\/ This var will contain WP_Post[] or int[]\n    $wpPosts = \\get_posts($args);\n\n    \/\/ Rest of the code\n    \/\/ ...\n  }\n}\n<\/code><\/pre>\n<h3>M\u00e9todos de divis\u00e3o<\/h3>\n<p>Os m\u00e9todos na interface n\u00e3o precisam ser uma r\u00e9plica do WordPress. Podemos transform\u00e1-los sempre que isso fizer sentido. Por exemplo, a fun\u00e7\u00e3o do WordPress <code>get_user_by($field, $value)<\/code> sabe como recuperar o usu\u00e1rio do banco de dados atrav\u00e9s do par\u00e2metro <code>$field<\/code>, que aceita os valores <code>\"id\"<\/code>, <code>\"ID\"<\/code>, <code>\"slug<\/code>&#8220;, <code>\"email\"<\/code> ou <code>\"login<\/code>&#8220;. Este design tem alguns problemas:<\/p>\n<ul>\n<li>N\u00e3o falhar\u00e1 na hora da compila\u00e7\u00e3o se passarmos uma corda errada.<\/li>\n<li>O par\u00e2metro <code>$value<\/code> precisa aceitar todos os tipos diferentes para todas as op\u00e7\u00f5es, mesmo que ao passar &#8220;<code>ID\"<\/code> ele espera uma <code>int<\/code>, ao passar <code>\"e-mail\"<\/code> ele s\u00f3 pode receber uma string<\/li>\n<\/ul>\n<p>Podemos melhorar esta situa\u00e7\u00e3o, dividindo a fun\u00e7\u00e3o em v\u00e1rias:<\/p>\n<pre><code class=\"language-php\">namespace Owner\\MyApp\\Contracts;\n\ninterface UserAPIInterface\n{\n  public function getUserById(int $id): ?UserInterface;\n  public function getUserByEmail(string $email): ?UserInterface;\n  public function getUserBySlug(string $slug): ?UserInterface;\n  public function getUserByLogin(string $login): ?UserInterface;\n}\n<\/code><\/pre>\n<p>O contrato \u00e9 resolvido para o WordPress desta forma (assumindo que criamos o <code>UserWrappe<\/code>\u00a0e a <code>UserInterface<\/code>, como explicado anteriormente):<\/p>\n<pre><code class=\"language-php\">namespace Owner\\MyAppForWP\\ContractImplementations;\n\nuse Owner\\MyApp\\Contracts\\UserAPIInterface;\n\nclass UserAPI implements UserAPIInterface\n{\n  public function getUserById(int $id): ?UserInterface\n  {\n    return $this-&gt;getUserByProp('id', $id);\n  }\n\n  public function getUserByEmail(string $email): ?UserInterface\n  {\n    return $this-&gt;getUserByProp('email', $email);\n  }\n\n  public function getUserBySlug(string $slug): ?UserInterface\n  {\n    return $this-&gt;getUserByProp('slug', $slug);\n  }\n\n  public function getUserByLogin(string $login): ?UserInterface\n  {\n    return $this-&gt;getUserByProp('login', $login);\n  }\n\n  private function getUserByProp(string $prop, int|string $value): ?UserInterface\n  {\n    if ($user = \\get_user_by($prop, $value)) {\n      return new UserWrapper($user);\n    }\n    return null;\n  }\n}\n<\/code><\/pre>\n<h3>Remover detalhes de implementa\u00e7\u00e3o da assinatura da fun\u00e7\u00e3o<\/h3>\n<p>As fun\u00e7\u00f5es no WordPress podem fornecer informa\u00e7\u00f5es sobre como elas s\u00e3o implementadas em sua pr\u00f3pria assinatura. Esta informa\u00e7\u00e3o pode ser removida ao avaliar a fun\u00e7\u00e3o a partir de uma perspectiva abstrata. Por exemplo, a obten\u00e7\u00e3o do sobrenome do usu\u00e1rio no WordPress \u00e9 feita chamando <code>get_the_author_meta<\/code>, tornando expl\u00edcito que o sobrenome de um usu\u00e1rio \u00e9 armazenado como um valor &#8220;meta&#8221; (na tabela <code>wp_usermeta<\/code>):<\/p>\n<pre><code class=\"language-php\">$userLastname = get_the_author_meta(\"user_lastname\", $user_id);\n<\/code><\/pre>\n<p>Voc\u00ea n\u00e3o tem que transmitir esta informa\u00e7\u00e3o ao contrato. As interfaces s\u00f3 se preocupam com o qu\u00ea, n\u00e3o com o como. Portanto, o contrato pode ter um m\u00e9todo <code>getUserLastname<\/code>, que n\u00e3o fornece qualquer informa\u00e7\u00e3o sobre como \u00e9 implementado:<\/p>\n<pre><code class=\"language-php\">interface UserAPIInterface\n{\n  public function getUserLastname(UserWrapper $userWrapper): string;\n  ...\n}\n<\/code><\/pre>\n<h3>Adicionar tipos mais estritos<\/h3>\n<p>Algumas fun\u00e7\u00f5es do WordPress podem receber par\u00e2metros de diferentes maneiras, levando \u00e0 ambig\u00fcidade. Por exemplo, a fun\u00e7\u00e3o <code>add_query_arg<\/code> pode tanto receber uma \u00fanica chave e valor:<\/p>\n<pre><code class=\"language-php\">$url = add_query_arg('id', 5, $url);\n<\/code><\/pre>\n<p>&#8230; ou um array de <code>key =&gt; value<\/code>:<\/p>\n<pre><code class=\"language-php\">$url = add_query_arg(['id' =&gt; 5], $url);\n<\/code><\/pre>\n<p>Nossa interface pode definir uma inten\u00e7\u00e3o mais compreens\u00edvel, dividindo tais fun\u00e7\u00f5es em v\u00e1rias separadas, cada uma delas aceitando uma combina\u00e7\u00e3o \u00fanica de entradas:<\/p>\n<pre><code class=\"language-php\">public function addQueryArg(string $key, string $value, string $url);\npublic function addQueryArgs(array $keyValues, string $url);\n<\/code><\/pre>\n<h3>Elimina\u00e7\u00e3o da d\u00edvida t\u00e9cnica<\/h3>\n<p>A fun\u00e7\u00e3o <code>get_post<\/code> do WordPress retorna n\u00e3o s\u00f3 &#8220;artigos&#8221; mas tamb\u00e9m &#8220;p\u00e1ginas&#8221; ou qualquer entidade do tipo &#8220;artigoss personalizados&#8221;, e essas entidades n\u00e3o s\u00e3o intercambi\u00e1veis. Tanto artigos como p\u00e1ginas s\u00e3o artigos personalizados, mas uma p\u00e1gina n\u00e3o \u00e9 um artigo e n\u00e3o \u00e9 uma p\u00e1gina. Portanto, a execu\u00e7\u00e3o de <code>get_posts<\/code> pode retornar p\u00e1ginas. Este comportamento \u00e9 uma discrep\u00e2ncia conceitual.<\/p>\n<p>Para fazer isso corretamente, <code>get_posts<\/code> deve ser chamado de <code>get_customposts<\/code>, mas nunca foi renomeado no n\u00facleo do WordPress. \u00c9 um problema comum na maioria dos softwares de longa dura\u00e7\u00e3o e \u00e9 chamado de &#8220;d\u00edvida t\u00e9cnica&#8221; &#8211; c\u00f3digo que tem problemas, mas nunca \u00e9 corrigido porque introduz mudan\u00e7as de quebra.<\/p>\n<p>Ao criar os nossos contratos, no entanto, temos a oportunidade de evitar este tipo de d\u00edvida t\u00e9cnica. Neste caso, podemos criar uma nova interface <code>ModelAPIInterface<\/code> que pode lidar com entidades de diferentes tipos, e fazemos v\u00e1rios m\u00e9todos, cada um para lidar com um tipo diferente:<\/p>\n<pre><code class=\"language-php\">interface ModelAPIInterface\n{\n  public function getPosts(array $args): array;\n  public function getPages(array $args): array;\n  public function getCustomPosts(array $args): array;\n}\n<\/code><\/pre>\n<p>Desta forma, a discrep\u00e2ncia n\u00e3o ocorrer\u00e1 mais, e voc\u00ea ver\u00e1 estes resultados:<\/p>\n<ul>\n<li><code>getPosts<\/code> retorna apenas mensagens<\/li>\n<li><code>getPages<\/code> devolve apenas p\u00e1ginas<\/li>\n<li><code>getCustomPosts<\/code> devolve tanto artigos como p\u00e1ginas<\/li>\n<\/ul>\n<h2>Benef\u00edcios de abstrair o c\u00f3digo<\/h2>\n<p>As principais vantagens de abstrair o c\u00f3digo de um aplicativo s\u00e3o:<\/p>\n<ul>\n<li>A execu\u00e7\u00e3o de ferramentas em pacotes contendo apenas c\u00f3digo de neg\u00f3cios \u00e9 mais f\u00e1cil de configurar e levar\u00e1 menos tempo (e menos dinheiro) para ser executada.<\/li>\n<li>Podemos usar ferramentas que n\u00e3o funcionam com o WordPress, como o scoping de um plugin com o PHP-Scoper.<\/li>\n<li>Voc\u00ea pode acabar produzindo dezenas de pacotes que depois t\u00eam de ser gerenciados e mantidos.<\/li>\n<li>A migra\u00e7\u00e3o de um aplicativo para outras plataformas torna-se mais f\u00e1cil.<\/li>\n<li>Podemos mudar a nossa mentalidade do pensamento no WordPress para pensar em termos da nossa l\u00f3gica empresarial.<\/li>\n<li>Os contratos descrevem a inten\u00e7\u00e3o do pedido, tornando-o mais compreens\u00edvel.<\/li>\n<li>O aplicativo \u00e9 organizado atrav\u00e9s de pacotes, criando um aplicativo enxuto contendo o m\u00ednimo necess\u00e1rio e melhorando-o progressivamente conforme a necessidade.<\/li>\n<li>N\u00f3s podemos saldar a d\u00edvida t\u00e9cnica.<\/li>\n<\/ul>\n<h2>Quest\u00f5es com o c\u00f3digo de abstra\u00e7\u00e3o<\/h2>\n<p>As desvantagens de abstrair o c\u00f3digo de um aplicativo s\u00e3o:<\/p>\n<ul>\n<li>Inicialmente envolve uma quantidade consider\u00e1vel de trabalho.<\/li>\n<li>O c\u00f3digo torna-se mais verboso; adiciona camadas extras de c\u00f3digo para alcan\u00e7ar o mesmo resultado.<\/li>\n<li>Voc\u00ea pode acabar produzindo <a href=\"https:\/\/graphql-api.com\/blog\/why-to-support-cms-agnosticism-the-graphql-api-split-to-around-90-packages\/\">dezenas de pacotes<\/a> que devem ent\u00e3o ser gerenciados e mantidos.<\/li>\n<li>Voc\u00ea pode precisar de um monorepo para gerenciar todos os pacotes juntos.<\/li>\n<li>A inje\u00e7\u00e3o de depend\u00eancia pode ser exagerada para aplicativos simples (diminuindo os retornos).<\/li>\n<li>A abstra\u00e7\u00e3o do c\u00f3digo nunca ser\u00e1 totalmente realizada, uma vez que existe normalmente uma prefer\u00eancia geral impl\u00edcita na arquitectura do CMS.<\/li>\n<\/ul>\n<h2>Op\u00e7\u00f5es de plugin de abstra\u00e7\u00e3o WordPress<\/h2>\n<p>Embora seja geralmente mais sensato extrair seu c\u00f3digo para um <a href=\"https:\/\/kinsta.com\/pt\/blog\/instalar-wordpress-localmente\/\">ambiente local<\/a> antes de trabalhar nele, alguns plugins do WordPress podem ajud\u00e1-lo a atingir seus objetivos de abstra\u00e7\u00e3o. Estas s\u00e3o as nossas melhores escolhas.<\/p>\n<h3>1. WPide<\/h3>\n<p>Produzido pela WebFactory Ltd, o popular <a href=\"https:\/\/wordpress.org\/plugins\/wpide\/\">plugin WPide<\/a> amplia drasticamente a funcionalidade padr\u00e3o do editor de c\u00f3digo do WordPress. Ele serve como um plugin de abstra\u00e7\u00e3o WordPress, permitindo que voc\u00ea visualize seu c\u00f3digo in situ para visualizar melhor o que precisa de aten\u00e7\u00e3o.<\/p>\n<figure>\n<p><figure style=\"width: 900px\" class=\"wp-caption alignnone\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/kinsta.com\/wp-content\/uploads\/2021\/08\/wpide-plugin.jpg\" alt=\"O plugin WPide.\" width=\"900\" height=\"291\"><figcaption class=\"wp-caption-text\">O plugin WPide.<\/figcaption><\/figure><\/figure>\n<p>WPide tamb\u00e9m tem uma fun\u00e7\u00e3o de busca e substitui\u00e7\u00e3o para localizar rapidamente c\u00f3digo desatualizado ou expirado e substitu\u00ed-lo por uma rendi\u00e7\u00e3o refatorada.<\/p>\n<p>Al\u00e9m disso, WPide fornece muitas caracter\u00edsticas extras, incluindo:<\/p>\n<ul>\n<li>Sintaxe e destaque de blocos<\/li>\n<li><a href=\"https:\/\/kinsta.com\/pt\/docs\/hospedagem-de-wordpress\/backups-wordpress\/#wordpress-backup\">Backups autom\u00e1ticas<\/a><\/li>\n<li>Cria\u00e7\u00e3o de arquivos e pastas<\/li>\n<li>Abrangente navegador de \u00e1rvore de arquivos<\/li>\n<li>Acesso \u00e0 API do sistema de arquivos WordPress<\/li>\n<\/ul>\n<h3>2. Ultimate DB Manager<\/h3>\n<p>O <a href=\"https:\/\/wordpress.org\/plugins\/ultimate-db-manager-lite\/\">plugin Ultimate WP DB Manager<\/a> do WPHobby d\u00e1 uma forma r\u00e1pida de baixar suas bases de dados na totalidade para extra\u00e7\u00e3o e refatora\u00e7\u00e3o.<\/p>\n<figure>\n<p><figure style=\"width: 900px\" class=\"wp-caption alignnone\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/kinsta.com\/wp-content\/uploads\/2021\/08\/ultimate-db-manager-plugin.jpg\" alt=\"O plug-in do Ultimate DB Manager.\" width=\"900\" height=\"250\"><figcaption class=\"wp-caption-text\">O plug-in do Ultimate DB Manager.<\/figcaption><\/figure><\/figure>\n<p>Naturalmente, plugins deste tipo n\u00e3o s\u00e3o necess\u00e1rios para os usu\u00e1rios Kinsta, pois Kinsta oferece <a href=\"https:\/\/kinsta.com\/pt\/docs\/hospedagem-de-wordpress\/gerenciamento-de-banco-de-dados\/acesso-ao-banco-de-dados-wordpress\/\">acesso direto \u00e0 base de dados<\/a> a todos os clientes. No entanto, se voc\u00ea n\u00e3o tiver acesso suficiente \u00e0 base de dados atrav\u00e9s do seu provedor de hospedagem, o Ultimate DB Manager pode vir a ser \u00fatil como um plugin de abstra\u00e7\u00e3o WordPress.<\/p>\n<h3>3. Seu pr\u00f3prio plugin personalizado de Abstra\u00e7\u00e3o WordPress<\/h3>\n<p>No final, a melhor escolha para abstra\u00e7\u00e3o ser\u00e1 sempre criar o seu plugin. Pode parecer um grande empreendimento, mas se voc\u00ea tem habilidade limitada para gerenciar seus arquivos principais do WordPress diretamente, isso oferece uma solu\u00e7\u00e3o de abstra\u00e7\u00e3o amig\u00e1vel.<\/p>\n<p>Faz\u00ea-lo tem benef\u00edcios claros:<\/p>\n<ul>\n<li>Abstrai as suas fun\u00e7\u00f5es dos seus arquivos de temas<\/li>\n<li>Preserva o seu c\u00f3digo atrav\u00e9s de altera\u00e7\u00f5es de temas e atualiza\u00e7\u00f5es da bases de dados<\/li>\n<\/ul>\n<p>Voc\u00ea pode aprender como criar seu plugin de abstra\u00e7\u00e3o WordPress atrav\u00e9s do <a href=\"https:\/\/developer.wordpress.org\/plugins\/\">Plugin Developer Handbook do WordPress<\/a>.<\/p>\n\n<h2>Resumo<\/h2>\n<p>Devemos abstrair o c\u00f3digo dos nossos aplicativos? As vezes, n\u00e3o existe uma &#8220;resposta certa ou predefinida&#8221;, porque depende de cada projeto. Os projetos que requerem um tempo tremendo para analisar com PHPUnit ou PHPStan podem ser os que mais se beneficiam, mas o esfor\u00e7o necess\u00e1rio para conseguir isso pode nem sempre valer a pena.<\/p>\n<p>Voc\u00ea aprendeu tudo o que precisa saber para come\u00e7ar a abstrair o c\u00f3digo WordPress.<\/p>\n<p><em>Voc\u00ea planeja implementar esta estrat\u00e9gia em seu projeto? Em caso afirmativo, voc\u00ea vai usar um plugin de abstra\u00e7\u00e3o WordPress? Informe-nos na sec\u00e7\u00e3o de coment\u00e1rios!<\/em><\/p>\n","protected":false},"excerpt":{"rendered":"<p>O WordPress \u00e9 um CMS antigo, mas tamb\u00e9m o mais usado. Gra\u00e7as ao seu hist\u00f3rico de suporte a vers\u00f5es PHP desatualizadas e c\u00f3digos legados, ainda falta &#8230;<\/p>\n","protected":false},"author":196,"featured_media":44113,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_kinsta_gated_content":false,"_kinsta_gated_content_redirect":"","footnotes":""},"tags":[360,528],"topic":[1026,1033],"class_list":["post-44109","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","tag-code","tag-web-developement","topic-desenvolvimento-wordpress","topic-plugins-wordpress"],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v24.6 (Yoast SEO v24.6) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Abstra\u00e7\u00e3o WordPress: Melhores Pr\u00e1ticas e Plugins de Abstra\u00e7\u00e3o WordPress<\/title>\n<meta name=\"description\" content=\"Aprenda como usar trechos de c\u00f3digo ou um Plugins de Abstra\u00e7\u00e3o WordPress para remover depend\u00eancias fixas do c\u00f3digo e produzir pacotes interativos.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/kinsta.com\/pt\/blog\/abstracao-wordpress\/\" \/>\n<meta property=\"og:locale\" content=\"pt_PT\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Abstra\u00e7\u00e3o WordPress: Melhores Pr\u00e1ticas e Plugins de Abstra\u00e7\u00e3o WordPress\" \/>\n<meta property=\"og:description\" content=\"Aprenda como usar trechos de c\u00f3digo ou um Plugins de Abstra\u00e7\u00e3o WordPress para remover depend\u00eancias fixas do c\u00f3digo e produzir pacotes interativos.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/kinsta.com\/pt\/blog\/abstracao-wordpress\/\" \/>\n<meta property=\"og:site_name\" content=\"Kinsta\u00ae\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/kinstapt\/\" \/>\n<meta property=\"article:published_time\" content=\"2021-09-09T10:59:37+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-02-07T14:08:59+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/kinsta.com\/pt\/wp-content\/uploads\/sites\/3\/2021\/09\/abstract-wordpress-plugin.jpeg\" \/>\n\t<meta property=\"og:image:width\" content=\"1460\" \/>\n\t<meta property=\"og:image:height\" content=\"730\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Leonardo Losoviz\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:description\" content=\"Aprenda como usar trechos de c\u00f3digo ou um Plugins de Abstra\u00e7\u00e3o WordPress para remover depend\u00eancias fixas do c\u00f3digo e produzir pacotes interativos.\" \/>\n<meta name=\"twitter:image\" content=\"https:\/\/kinsta.com\/pt\/wp-content\/uploads\/sites\/3\/2021\/09\/abstract-wordpress-plugin.jpeg\" \/>\n<meta name=\"twitter:creator\" content=\"@losoviz\" \/>\n<meta name=\"twitter:site\" content=\"@kinsta_pt\" \/>\n<meta name=\"twitter:label1\" content=\"Escrito por\" \/>\n\t<meta name=\"twitter:data1\" content=\"Leonardo Losoviz\" \/>\n\t<meta name=\"twitter:label2\" content=\"Tempo estimado de leitura\" \/>\n\t<meta name=\"twitter:data2\" content=\"16 minutos\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/kinsta.com\/pt\/blog\/abstracao-wordpress\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/kinsta.com\/pt\/blog\/abstracao-wordpress\/\"},\"author\":{\"name\":\"Leonardo Losoviz\",\"@id\":\"https:\/\/kinsta.com\/pt\/#\/schema\/person\/c382de1885cc21b079ec1e71d7faf238\"},\"headline\":\"Abstra\u00e7\u00e3o WordPress: Melhores Pr\u00e1ticas e Plugins de Abstra\u00e7\u00e3o WordPress\",\"datePublished\":\"2021-09-09T10:59:37+00:00\",\"dateModified\":\"2025-02-07T14:08:59+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/kinsta.com\/pt\/blog\/abstracao-wordpress\/\"},\"wordCount\":3302,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/kinsta.com\/pt\/#organization\"},\"image\":{\"@id\":\"https:\/\/kinsta.com\/pt\/blog\/abstracao-wordpress\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/kinsta.com\/pt\/wp-content\/uploads\/sites\/3\/2021\/09\/abstract-wordpress-plugin.jpeg\",\"keywords\":[\"code\",\"web developement\"],\"articleSection\":[\"Melhores Tutoriais WordPress\"],\"inLanguage\":\"pt-PT\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/kinsta.com\/pt\/blog\/abstracao-wordpress\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/kinsta.com\/pt\/blog\/abstracao-wordpress\/\",\"url\":\"https:\/\/kinsta.com\/pt\/blog\/abstracao-wordpress\/\",\"name\":\"Abstra\u00e7\u00e3o WordPress: Melhores Pr\u00e1ticas e Plugins de Abstra\u00e7\u00e3o WordPress\",\"isPartOf\":{\"@id\":\"https:\/\/kinsta.com\/pt\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/kinsta.com\/pt\/blog\/abstracao-wordpress\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/kinsta.com\/pt\/blog\/abstracao-wordpress\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/kinsta.com\/pt\/wp-content\/uploads\/sites\/3\/2021\/09\/abstract-wordpress-plugin.jpeg\",\"datePublished\":\"2021-09-09T10:59:37+00:00\",\"dateModified\":\"2025-02-07T14:08:59+00:00\",\"description\":\"Aprenda como usar trechos de c\u00f3digo ou um Plugins de Abstra\u00e7\u00e3o WordPress para remover depend\u00eancias fixas do c\u00f3digo e produzir pacotes interativos.\",\"breadcrumb\":{\"@id\":\"https:\/\/kinsta.com\/pt\/blog\/abstracao-wordpress\/#breadcrumb\"},\"inLanguage\":\"pt-PT\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/kinsta.com\/pt\/blog\/abstracao-wordpress\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"pt-PT\",\"@id\":\"https:\/\/kinsta.com\/pt\/blog\/abstracao-wordpress\/#primaryimage\",\"url\":\"https:\/\/kinsta.com\/pt\/wp-content\/uploads\/sites\/3\/2021\/09\/abstract-wordpress-plugin.jpeg\",\"contentUrl\":\"https:\/\/kinsta.com\/pt\/wp-content\/uploads\/sites\/3\/2021\/09\/abstract-wordpress-plugin.jpeg\",\"width\":1460,\"height\":730,\"caption\":\"Abstrac\u00e7\u00e3o WordPress: Melhores Pr\u00e1ticas e Plugins de Abstra\u00e7\u00e3o do WordPress\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/kinsta.com\/pt\/blog\/abstracao-wordpress\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/kinsta.com\/pt\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Desenvolvimento WordPress\",\"item\":\"https:\/\/kinsta.com\/pt\/topicos\/desenvolvimento-wordpress\/\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Abstra\u00e7\u00e3o WordPress: Melhores Pr\u00e1ticas e Plugins de Abstra\u00e7\u00e3o WordPress\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/kinsta.com\/pt\/#website\",\"url\":\"https:\/\/kinsta.com\/pt\/\",\"name\":\"Kinsta\u00ae\",\"description\":\"Solu\u00e7\u00f5es de hospedagem Premium, r\u00e1pida e segura\",\"publisher\":{\"@id\":\"https:\/\/kinsta.com\/pt\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/kinsta.com\/pt\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"pt-PT\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/kinsta.com\/pt\/#organization\",\"name\":\"Kinsta\",\"url\":\"https:\/\/kinsta.com\/pt\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"pt-PT\",\"@id\":\"https:\/\/kinsta.com\/pt\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/kinsta.com\/pt\/wp-content\/uploads\/sites\/3\/2023\/12\/kinsta-logo.jpeg\",\"contentUrl\":\"https:\/\/kinsta.com\/pt\/wp-content\/uploads\/sites\/3\/2023\/12\/kinsta-logo.jpeg\",\"width\":500,\"height\":500,\"caption\":\"Kinsta\"},\"image\":{\"@id\":\"https:\/\/kinsta.com\/pt\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/www.facebook.com\/kinstapt\/\",\"https:\/\/x.com\/kinsta_pt\",\"https:\/\/www.instagram.com\/kinstahosting\/\",\"https:\/\/www.linkedin.com\/company\/kinsta\/\",\"https:\/\/www.pinterest.com\/kinstahosting\/\",\"https:\/\/www.youtube.com\/c\/Kinsta\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/kinsta.com\/pt\/#\/schema\/person\/c382de1885cc21b079ec1e71d7faf238\",\"name\":\"Leonardo Losoviz\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"pt-PT\",\"@id\":\"https:\/\/kinsta.com\/pt\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/b28085726ee66e49f08be16ad668efd5?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/b28085726ee66e49f08be16ad668efd5?s=96&d=mm&r=g\",\"caption\":\"Leonardo Losoviz\"},\"description\":\"Leo writes about innovative web development trends, mostly concerning PHP, WordPress and GraphQL. You can find him at leoloso.com and twitter.com\/losoviz.\",\"sameAs\":[\"https:\/\/leoloso.com\",\"https:\/\/x.com\/losoviz\",\"https:\/\/www.youtube.com\/@GatoGraphQL\"],\"url\":\"https:\/\/kinsta.com\/pt\/blog\/author\/leonardolosoviz\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Abstra\u00e7\u00e3o WordPress: Melhores Pr\u00e1ticas e Plugins de Abstra\u00e7\u00e3o WordPress","description":"Aprenda como usar trechos de c\u00f3digo ou um Plugins de Abstra\u00e7\u00e3o WordPress para remover depend\u00eancias fixas do c\u00f3digo e produzir pacotes interativos.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/kinsta.com\/pt\/blog\/abstracao-wordpress\/","og_locale":"pt_PT","og_type":"article","og_title":"Abstra\u00e7\u00e3o WordPress: Melhores Pr\u00e1ticas e Plugins de Abstra\u00e7\u00e3o WordPress","og_description":"Aprenda como usar trechos de c\u00f3digo ou um Plugins de Abstra\u00e7\u00e3o WordPress para remover depend\u00eancias fixas do c\u00f3digo e produzir pacotes interativos.","og_url":"https:\/\/kinsta.com\/pt\/blog\/abstracao-wordpress\/","og_site_name":"Kinsta\u00ae","article_publisher":"https:\/\/www.facebook.com\/kinstapt\/","article_published_time":"2021-09-09T10:59:37+00:00","article_modified_time":"2025-02-07T14:08:59+00:00","og_image":[{"width":1460,"height":730,"url":"https:\/\/kinsta.com\/pt\/wp-content\/uploads\/sites\/3\/2021\/09\/abstract-wordpress-plugin.jpeg","type":"image\/jpeg"}],"author":"Leonardo Losoviz","twitter_card":"summary_large_image","twitter_description":"Aprenda como usar trechos de c\u00f3digo ou um Plugins de Abstra\u00e7\u00e3o WordPress para remover depend\u00eancias fixas do c\u00f3digo e produzir pacotes interativos.","twitter_image":"https:\/\/kinsta.com\/pt\/wp-content\/uploads\/sites\/3\/2021\/09\/abstract-wordpress-plugin.jpeg","twitter_creator":"@losoviz","twitter_site":"@kinsta_pt","twitter_misc":{"Escrito por":"Leonardo Losoviz","Tempo estimado de leitura":"16 minutos"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/kinsta.com\/pt\/blog\/abstracao-wordpress\/#article","isPartOf":{"@id":"https:\/\/kinsta.com\/pt\/blog\/abstracao-wordpress\/"},"author":{"name":"Leonardo Losoviz","@id":"https:\/\/kinsta.com\/pt\/#\/schema\/person\/c382de1885cc21b079ec1e71d7faf238"},"headline":"Abstra\u00e7\u00e3o WordPress: Melhores Pr\u00e1ticas e Plugins de Abstra\u00e7\u00e3o WordPress","datePublished":"2021-09-09T10:59:37+00:00","dateModified":"2025-02-07T14:08:59+00:00","mainEntityOfPage":{"@id":"https:\/\/kinsta.com\/pt\/blog\/abstracao-wordpress\/"},"wordCount":3302,"commentCount":0,"publisher":{"@id":"https:\/\/kinsta.com\/pt\/#organization"},"image":{"@id":"https:\/\/kinsta.com\/pt\/blog\/abstracao-wordpress\/#primaryimage"},"thumbnailUrl":"https:\/\/kinsta.com\/pt\/wp-content\/uploads\/sites\/3\/2021\/09\/abstract-wordpress-plugin.jpeg","keywords":["code","web developement"],"articleSection":["Melhores Tutoriais WordPress"],"inLanguage":"pt-PT","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/kinsta.com\/pt\/blog\/abstracao-wordpress\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/kinsta.com\/pt\/blog\/abstracao-wordpress\/","url":"https:\/\/kinsta.com\/pt\/blog\/abstracao-wordpress\/","name":"Abstra\u00e7\u00e3o WordPress: Melhores Pr\u00e1ticas e Plugins de Abstra\u00e7\u00e3o WordPress","isPartOf":{"@id":"https:\/\/kinsta.com\/pt\/#website"},"primaryImageOfPage":{"@id":"https:\/\/kinsta.com\/pt\/blog\/abstracao-wordpress\/#primaryimage"},"image":{"@id":"https:\/\/kinsta.com\/pt\/blog\/abstracao-wordpress\/#primaryimage"},"thumbnailUrl":"https:\/\/kinsta.com\/pt\/wp-content\/uploads\/sites\/3\/2021\/09\/abstract-wordpress-plugin.jpeg","datePublished":"2021-09-09T10:59:37+00:00","dateModified":"2025-02-07T14:08:59+00:00","description":"Aprenda como usar trechos de c\u00f3digo ou um Plugins de Abstra\u00e7\u00e3o WordPress para remover depend\u00eancias fixas do c\u00f3digo e produzir pacotes interativos.","breadcrumb":{"@id":"https:\/\/kinsta.com\/pt\/blog\/abstracao-wordpress\/#breadcrumb"},"inLanguage":"pt-PT","potentialAction":[{"@type":"ReadAction","target":["https:\/\/kinsta.com\/pt\/blog\/abstracao-wordpress\/"]}]},{"@type":"ImageObject","inLanguage":"pt-PT","@id":"https:\/\/kinsta.com\/pt\/blog\/abstracao-wordpress\/#primaryimage","url":"https:\/\/kinsta.com\/pt\/wp-content\/uploads\/sites\/3\/2021\/09\/abstract-wordpress-plugin.jpeg","contentUrl":"https:\/\/kinsta.com\/pt\/wp-content\/uploads\/sites\/3\/2021\/09\/abstract-wordpress-plugin.jpeg","width":1460,"height":730,"caption":"Abstrac\u00e7\u00e3o WordPress: Melhores Pr\u00e1ticas e Plugins de Abstra\u00e7\u00e3o do WordPress"},{"@type":"BreadcrumbList","@id":"https:\/\/kinsta.com\/pt\/blog\/abstracao-wordpress\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/kinsta.com\/pt\/"},{"@type":"ListItem","position":2,"name":"Desenvolvimento WordPress","item":"https:\/\/kinsta.com\/pt\/topicos\/desenvolvimento-wordpress\/"},{"@type":"ListItem","position":3,"name":"Abstra\u00e7\u00e3o WordPress: Melhores Pr\u00e1ticas e Plugins de Abstra\u00e7\u00e3o WordPress"}]},{"@type":"WebSite","@id":"https:\/\/kinsta.com\/pt\/#website","url":"https:\/\/kinsta.com\/pt\/","name":"Kinsta\u00ae","description":"Solu\u00e7\u00f5es de hospedagem Premium, r\u00e1pida e segura","publisher":{"@id":"https:\/\/kinsta.com\/pt\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/kinsta.com\/pt\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"pt-PT"},{"@type":"Organization","@id":"https:\/\/kinsta.com\/pt\/#organization","name":"Kinsta","url":"https:\/\/kinsta.com\/pt\/","logo":{"@type":"ImageObject","inLanguage":"pt-PT","@id":"https:\/\/kinsta.com\/pt\/#\/schema\/logo\/image\/","url":"https:\/\/kinsta.com\/pt\/wp-content\/uploads\/sites\/3\/2023\/12\/kinsta-logo.jpeg","contentUrl":"https:\/\/kinsta.com\/pt\/wp-content\/uploads\/sites\/3\/2023\/12\/kinsta-logo.jpeg","width":500,"height":500,"caption":"Kinsta"},"image":{"@id":"https:\/\/kinsta.com\/pt\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/kinstapt\/","https:\/\/x.com\/kinsta_pt","https:\/\/www.instagram.com\/kinstahosting\/","https:\/\/www.linkedin.com\/company\/kinsta\/","https:\/\/www.pinterest.com\/kinstahosting\/","https:\/\/www.youtube.com\/c\/Kinsta"]},{"@type":"Person","@id":"https:\/\/kinsta.com\/pt\/#\/schema\/person\/c382de1885cc21b079ec1e71d7faf238","name":"Leonardo Losoviz","image":{"@type":"ImageObject","inLanguage":"pt-PT","@id":"https:\/\/kinsta.com\/pt\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/b28085726ee66e49f08be16ad668efd5?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/b28085726ee66e49f08be16ad668efd5?s=96&d=mm&r=g","caption":"Leonardo Losoviz"},"description":"Leo writes about innovative web development trends, mostly concerning PHP, WordPress and GraphQL. You can find him at leoloso.com and twitter.com\/losoviz.","sameAs":["https:\/\/leoloso.com","https:\/\/x.com\/losoviz","https:\/\/www.youtube.com\/@GatoGraphQL"],"url":"https:\/\/kinsta.com\/pt\/blog\/author\/leonardolosoviz\/"}]}},"acf":[],"_links":{"self":[{"href":"https:\/\/kinsta.com\/pt\/wp-json\/wp\/v2\/posts\/44109","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/kinsta.com\/pt\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/kinsta.com\/pt\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/kinsta.com\/pt\/wp-json\/wp\/v2\/users\/196"}],"replies":[{"embeddable":true,"href":"https:\/\/kinsta.com\/pt\/wp-json\/wp\/v2\/comments?post=44109"}],"version-history":[{"count":12,"href":"https:\/\/kinsta.com\/pt\/wp-json\/wp\/v2\/posts\/44109\/revisions"}],"predecessor-version":[{"id":71085,"href":"https:\/\/kinsta.com\/pt\/wp-json\/wp\/v2\/posts\/44109\/revisions\/71085"}],"alternate":[{"embeddable":true,"hreflang":"en","title":"English","href":"https:\/\/kinsta.com\/pt\/wp-json\/kinsta\/v1\/posts\/44109\/translations\/en"},{"embeddable":true,"hreflang":"it","title":"Italian","href":"https:\/\/kinsta.com\/pt\/wp-json\/kinsta\/v1\/posts\/44109\/translations\/it"},{"embeddable":true,"hreflang":"fr","title":"French","href":"https:\/\/kinsta.com\/pt\/wp-json\/kinsta\/v1\/posts\/44109\/translations\/fr"},{"embeddable":true,"hreflang":"es","title":"Spanish","href":"https:\/\/kinsta.com\/pt\/wp-json\/kinsta\/v1\/posts\/44109\/translations\/es"},{"embeddable":true,"hreflang":"pt","title":"Portuguese","href":"https:\/\/kinsta.com\/pt\/wp-json\/kinsta\/v1\/posts\/44109\/translations\/pt"},{"embeddable":true,"hreflang":"de","title":"German","href":"https:\/\/kinsta.com\/pt\/wp-json\/kinsta\/v1\/posts\/44109\/translations\/de"},{"embeddable":true,"hreflang":"nl","title":"Dutch","href":"https:\/\/kinsta.com\/pt\/wp-json\/kinsta\/v1\/posts\/44109\/translations\/nl"},{"href":"https:\/\/kinsta.com\/pt\/wp-json\/kinsta\/v1\/posts\/44109\/tree"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/kinsta.com\/pt\/wp-json\/wp\/v2\/media\/44113"}],"wp:attachment":[{"href":"https:\/\/kinsta.com\/pt\/wp-json\/wp\/v2\/media?parent=44109"}],"wp:term":[{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/kinsta.com\/pt\/wp-json\/wp\/v2\/tags?post=44109"},{"taxonomy":"topic","embeddable":true,"href":"https:\/\/kinsta.com\/pt\/wp-json\/wp\/v2\/topic?post=44109"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}