{"id":47366,"date":"2021-09-06T11:09:17","date_gmt":"2021-09-06T09:09:17","guid":{"rendered":"https:\/\/kinsta.com\/?p=100908"},"modified":"2023-03-14T13:38:01","modified_gmt":"2023-03-14T12:38:01","slug":"plugin-astrazione-wordpress","status":"publish","type":"post","link":"https:\/\/kinsta.com\/it\/blog\/plugin-astrazione-wordpress\/","title":{"rendered":"Astrazione di WordPress: Best Practice e Plugin per l&#8217;Astrazione di WordPress"},"content":{"rendered":"<p>WordPress \u00e8 un CMS che ha ormai qualche anno, ma \u00e8 anche il <a href=\"https:\/\/kinsta.com\/it\/quota-di-mercato-di-wordpress\/\" target=\"_blank\" rel=\"noopener noreferrer\">pi\u00f9 utilizzato<\/a>. C\u2019\u00e8 il tema del supporto di versioni PHP obsolete e del codice datato, e mancano anche certe prassi di programmazione moderna: l&#8217;astrazione di WordPress ne \u00e8 un esempio.<\/p>\n<p>Sarebbe molto meglio dividere la base di codice del core di WordPress in pacchetti gestiti da Composer. O magari, auto-caricare le classi di WordPress dai percorsi dei file.<\/p>\n<p>Questo articolo vi spiegher\u00e0 come astrarre il codice di WordPress manualmente e utilizzare le capacit\u00e0 astratte dei plugin di 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>Problemi con l&#8217;Integrazione di WordPress e gli Strumenti PHP<\/h2>\n<p>A causa della sua architettura datata, a volte sorgono problemi quando integriamo WordPress con strumenti per il codice PHP, come l&#8217;analizzatore statico <a href=\"https:\/\/phpstan.org\/\" target=\"_blank\" rel=\"noopener noreferrer\">PHPStan<\/a>, la libreria di test unitari <a href=\"https:\/\/phpunit.de\/\" target=\"_blank\" rel=\"noopener noreferrer\">PHPUnit<\/a> e la libreria di namespace-scoping <a href=\"https:\/\/github.com\/humbug\/php-scoper\" target=\"_blank\" rel=\"noopener noreferrer\">PHP-Scoper<\/a>. Per esempio, considerate i seguenti casi:<\/p>\n<ul>\n<li>In anticipo su <a href=\"https:\/\/kinsta.com\/it\/blog\/wordpress-5-6\/\">WordPress 5.6<\/a> con il supporto di <a href=\"https:\/\/kinsta.com\/it\/blog\/php-8\/\">PHP 8.0<\/a>, un rapporto di Yoast descriveva come l&#8217;esecuzione di PHPStan sul core di WordPress avrebbe prodotto <a href=\"https:\/\/developer.yoast.com\/blog\/the-2020-wordpress-and-php-8-compatibility-report\/#h-scanning-wordpress-with-phpstan\" target=\"_blank\" rel=\"noopener noreferrer\">migliaia di problemi<\/a>.<\/li>\n<li>Dato che supporta ancora PHP 5.6, le suite di test di WordPress attualmente <a href=\"https:\/\/core.trac.wordpress.org\/ticket\/46149\" target=\"_blank\" rel=\"noopener noreferrer\">supportano PHPUnit solo fino alla versione 7.5<\/a>, che per\u00f2 ha gi\u00e0 raggiunto il suo fine vita.<\/li>\n<li>Scoprire i plugin di WordPress tramite PHP-Scoper <a href=\"https:\/\/github.com\/humbug\/php-scoper#wordpress\" target=\"_blank\" rel=\"noopener noreferrer\">\u00e8 molto impegnativo<\/a>.<\/li>\n<\/ul>\n<p>Il codice di WordPress all&#8217;interno dei nostri progetti sar\u00e0 solo una frazione del totale; il progetto conterr\u00e0 anche codice aziendale agnostico rispetto al CMS sottostante. Eppure, solo per il fatto di avere del codice WordPress, il progetto potrebbe non integrarsi correttamente con gli strumenti.<\/p>\n<p>Per questo, potrebbe avere senso dividere il progetto in pacchetti, alcuni dei quali contengono codice WordPress e altri hanno solo codice aziendale che usano PHP &#8220;vanilla&#8221; e nessun codice WordPress. In questo modo, questi ultimi pacchetti non saranno affetti dai problemi descritti sopra ma potranno essere perfettamente integrati con gli strumenti.<\/p>\n<h2>Cosa Si Intende per Astrazione del Codice?<\/h2>\n<p>L&#8217;astrazione del codice rimuove le dipendenze fisse dal codice, producendo pacchetti che interagiscono tra loro tramite contratti. Questi pacchetti possono poi essere aggiunti a diverse applicazioni con diversi stack, massimizzando la loro usabilit\u00e0. Il risultato dell&#8217;astrazione del codice \u00e8 una codebase disaccoppiato in modo pulito e basato sui seguenti pilastri:<\/p>\n<ol>\n<li>Prograzione sulle interfacce, non sulle implementazioni.<\/li>\n<li>Creazione di pacchetti e distribuzione tramite Composer.<\/li>\n<li>Unione di tutte le parti insieme tramite dependency injection.<\/li>\n<\/ol>\n\n<h2>Programmare Sulle Interfacce, Non Sulle Implementazioni<\/h2>\n<p>Programmare sulle interfacce significa utilizzare contratti per far interagire tra loro frammenti di codice. Un contratto \u00e8 semplicemente un&#8217;interfaccia PHP (o qualsiasi altro linguaggio) che definisce le funzioni disponibili e le loro firme, cio\u00e8 l&#8217;input che ricevono e il loro output.<\/p>\n<p>Un&#8217;interfaccia dichiara l&#8217;intento della funzionalit\u00e0 senza spiegare come la funzionalit\u00e0 sar\u00e0 implementata. Accedendo alle funzionalit\u00e0 attraverso le interfacce, la nostra <a href=\"https:\/\/kinsta.com\/it\/blog\/monitoraggio-prestazioni-applicazioni\/\">applicazione<\/a> pu\u00f2 contare su pezzi di codice autonomi che realizzano un obiettivo specifico senza sapere, o preoccuparsi, di come lo fanno. In questo modo, l&#8217;applicazione non ha bisogno di essere adattata per passare a un altro pezzo di codice che realizza lo stesso obiettivo (provenendo, per esempio, da un fornitore diverso).<\/p>\n<h3>Esempio di Contratti<\/h3>\n<p>Il seguente codice usa il contratto di Symfony <a href=\"https:\/\/github.com\/symfony\/symfony\/blob\/302b844\/src\/Symfony\/Contracts\/Cache\/CacheInterface.php\"><code>CacheInterface<\/code><\/a> e il contratto PHP Standard Recommendation (PSR) <a href=\"https:\/\/github.com\/php-fig\/cache\/blob\/0a7c67d\/src\/CacheItemInterface.php\"><code>CacheItemInterface<\/code><\/a> per implementare la funzionalit\u00e0 di caching:<\/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});\n<\/code><\/pre>\n<p><code>$cache<\/code> implementa <code>CacheInterface<\/code>, che definisce il metodo <code>get<\/code> per recuperare un oggetto dalla cache. Accedendo a questa funzionalit\u00e0 attraverso il contratto, l&#8217;applicazione pu\u00f2 ignorare dove si trova la cache sia essa nella memoria, nel disco, nel database, nella rete o in qualsiasi altro posto. Tuttavia, deve eseguire la funzione.<br \/>\n<code>CacheItemInterface<\/code> definisce il metodo <code>expiresAfter<\/code> per dichiarare per quanto tempo l&#8217;elemento deve essere tenuto nella cache. L&#8217;applicazione pu\u00f2 invocare questo metodo senza preoccuparsi di cosa sia l&#8217;oggetto in cache; si preoccupa solo di quanto tempo debba essere tenuto in cache.<\/p>\n<h2>Programmare Sulle Interfacce in WordPress<\/h2>\n<p>Poich\u00e9 stiamo astraendo il codice di WordPress, il risultato sar\u00e0 che l&#8217;applicazione non far\u00e0 direttamente riferimento al <a href=\"https:\/\/kinsta.com\/it\/blog\/modificare-codice-wordpress\/\">codice di WordPress<\/a>, ma sempre attraverso un&#8217;interfaccia. Per esempio, la funzione <code>get_posts<\/code> di WordPress presenta questa firma:<\/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>Invece di invocare direttamente questo metodo, possiamo accedervi tramite il contratto <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}\n<\/code><\/pre>\n<p>Notate che la funzione <code>get_posts<\/code> di WordPress pu\u00f2 restituire oggetti della classe <code>WP_Post<\/code>, che \u00e8 specifica di WordPress. Quando si astrae il codice, dobbiamo rimuovere questo tipo di dipendenza fissa. Il metodo <code>get_posts<\/code> nel contratto restituisce oggetti del tipo <code>PostInterface<\/code>, permettendovi di fare riferimento alla classe <code>WP_Post<\/code> senza essere esplicito al riguardo.<\/p>\n<p>La classe <code>PostInterface<\/code> dovr\u00e0 fornire accesso a tutti i metodi e attributi di <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>L&#8217;esecuzione di questa strategia pu\u00f2 cambiare la nostra comprensione del punto in cui WordPress si inserisce nel nostro stack. Invece di pensare a WordPress come all&#8217;applicazione stessa (su cui installiamo temi e plugin), possiamo pensarlo semplicemente come un&#8217;altra dipendenza all&#8217;interno dell&#8217;applicazione, sostituibile come qualsiasi altro componente. (Anche se non sostituiremo WordPress nella pratica, \u00e8 comunque sostituibile da un punto di vista concettuale.)<\/p>\n<h2>Creare e Distribuire i Pacchetti<\/h2>\n<p><a href=\"https:\/\/getcomposer.org\/\" target=\"_blank\" rel=\"noopener noreferrer\">Composer<\/a> \u00e8 un gestore di pacchetti per PHP. Permette alle applicazioni PHP di recuperare i pacchetti (cio\u00e8 pezzi di codice) da un repository e installarli come dipendenze. Per disaccoppiare l&#8217;applicazione da WordPress, dobbiamo distribuire il suo codice in pacchetti di due tipi diversi: quelli che contengono codice WordPress e gli altri che contengono la logica di business (cio\u00e8 nessun codice WordPress).<\/p>\n<p>Infine, aggiungiamo tutti i pacchetti come dipendenze nell&#8217;applicazione e li installiamo tramite Composer. Dato che gli strumenti saranno applicati ai pacchetti di codice di business, questi devono contenere la maggior parte del codice dell&#8217;applicazione; pi\u00f9 alta \u00e8 la percentuale, meglio \u00e8. Far loro gestire circa il 90% del codice complessivo \u00e8 un buon obiettivo.<\/p>\n<h2>Estrarre il Codice WordPress nei Pacchetti<\/h2>\n<p>Seguendo l&#8217;esempio di prima, i contratti <code>PostAPIInterface<\/code> e <code>PostInterface<\/code> saranno aggiunti al pacchetto contenente il codice aziendale mentre un altro pacchetto includer\u00e0 l&#8217;implementazione di WordPress di questi contratti. Per soddisfare <code>PostInterface<\/code>, creiamo una classe <code>PostWrapper<\/code> che recuperer\u00e0 tutti gli attributi da un oggetto <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}\n<\/code><\/pre>\n<p>Quando si implementa <code>PostAPI<\/code>, poich\u00e9 il metodo <code>get_posts<\/code> restituisce <code>PostInterface[]<\/code>, dobbiamo convertire gli oggetti da <code>WP_Post<\/code> a <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>Usare la Dependency Injection<\/h2>\n<p>L&#8217;iniezione delle dipendenze \u00e8 un pattern di progettazione che vi permette di incollare tutte le parti dell&#8217;applicazione in modo accoppiato e senza blocchi. Con la dependency injection, l&#8217;applicazione accede ai servizi tramite i loro contratti e le implementazioni dei contratti vengono &#8220;iniettate&#8221; nell&#8217;applicazione tramite la configurazione.<\/p>\n<p>Con il semplice cambio della configurazione, possiamo facilmente passare da un fornitore di contratti a un altro. Ci sono diverse librerie di dependency injection tra cui possiamo scegliere. Consigliamo di sceglierne una che aderisca alle <a href=\"https:\/\/www.php-fig.org\/\" target=\"_blank\" rel=\"noopener noreferrer\">raccomandazioni standard di PHP<\/a> (spesso indicate come &#8220;PSR&#8221;), cos\u00ec possiamo facilmente sostituire la libreria con un&#8217;altra in caso di necessit\u00e0. Per quanto riguarda l&#8217;iniezione delle dipendenze, la libreria deve soddisfare la <a href=\"https:\/\/www.php-fig.org\/psr\/psr-11\/\" target=\"_blank\" rel=\"noopener noreferrer\">PSR-11<\/a>, che fornisce le specifiche per una &#8220;interfaccia contenitore&#8221;.<br \/>\nTra le altre, le seguenti librerie sono conformi al PSR-11:<\/p>\n<ul>\n<li><a href=\"https:\/\/github.com\/symfony\/dependency-injection\" target=\"_blank\" rel=\"noopener noreferrer\">DependencyInjection di Symfony<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/PHP-DI\/PHP-DI\" target=\"_blank\" rel=\"noopener noreferrer\">PHP-DI<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/auraphp\/Aura.Di\" target=\"_blank\" rel=\"noopener noreferrer\">Aura.Di<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/thephpleague\/container\" target=\"_blank\" rel=\"noopener noreferrer\">Container (Dependency Injection)<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/yiisoft\/di\" target=\"_blank\" rel=\"noopener noreferrer\">DependencyInjection di Yii<\/a><\/li>\n<\/ul>\n<h3>Accesso ai Servizi Attraverso il Container di Servizi<\/h3>\n<p>La libreria di dependency injection metter\u00e0 a disposizione un &#8220;container di servizi&#8221;, che risolve un contratto nella sua corrispondente classe di implementazione. L&#8217;applicazione deve fare affidamento sul contenitore di servizi per accedere a tutte le funzionalit\u00e0. Per esempio, mentre in genere invochiamo direttamente le funzioni di WordPress:<\/p>\n<pre><code class=\"language-php\">$posts = get_posts();\n<\/code><\/pre>\n<p>&#8230;con il container di servizi, dobbiamo prima ottenere il servizio che soddisfa <code>PostAPIInterface<\/code> ed eseguire la funzionalit\u00e0 attraverso di esso:<\/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>Usare DependencyInjection di Symfony<\/h3>\n<p>Il <a href=\"https:\/\/symfony.com\/doc\/current\/components\/dependency_injection.html\" target=\"_blank\" rel=\"noopener noreferrer\">componente DependencyInjection di Symfony<\/a> \u00e8 attualmente la libreria di dependency injection pi\u00f9 popolare. Vi permette di configurare il contenitore di servizi tramite codice PHP, YAML o XML. Per esempio, per definire che il contratto <code>PostAPIInterface<\/code> \u00e8 soddisfatto tramite la classe <code>PostAPI<\/code>, la configurazione in YAML \u00e8 la seguente:<\/p>\n<pre><code class=\"language-yaml\">services:\n  Owner\\MyApp\\Contracts\\PostAPIInterface:\n    class: \\Owner\\MyAppForWP\\ContractImplementations\\PostAPI\n<\/code><\/pre>\n<p>DependencyInjection di Symfony permette anche alle istanze di un servizio di essere automaticamente iniettate (o &#8220;autowired&#8221;) in qualsiasi altro servizio che dipende da esso. Inoltre, rende facile definire che una classe \u00e8 un&#8217;implementazione del proprio servizio.<br \/>\nPer esempio, considerate la <a href=\"https:\/\/github.com\/leoloso\/PoP\/blob\/8602e9041ac92f4683966eed5c4a90686b9395fa\/layers\/GraphQLAPIForWP\/plugins\/graphql-api-for-wp\/config\/hybrid-services.yaml\" target=\"_blank\" rel=\"noopener noreferrer\">seguente configurazione 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>Questa configurazione definisce quanto segue:<\/p>\n<ul>\n<li style=\"list-style-type: none\">\n<ul>\n<li>Il contratto <code>UserAuthorizationSchemeRegistryInterface<\/code> \u00e8 soddisfatto dalla classe <code>UserAuthorizationSchemeRegistry<\/code><\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p>.<\/p>\n<ul>\n<li>Il contratto <code>UserAuthorizationInterface<\/code> \u00e8 soddisfatto dalla classe <code>UserAuthorization<\/code>.<\/li>\n<li>Tutte le classi sotto la cartella <code>UserAuthorizationSchemes\/<\/code> sono un&#8217;implementazione di se stesse.<\/li>\n<li>I servizi devono essere iniettati automaticamente l&#8217;uno nell&#8217;altro<code>(autowire: true<\/code>).<\/li>\n<\/ul>\n<p>Vediamo come funziona l&#8217;autowiring. La classe <a href=\"https:\/\/github.com\/leoloso\/PoP\/blob\/bd56f23b52a3e02966fdcbde4bc58f246a47a6e5\/layers\/GraphQLAPIForWP\/plugins\/graphql-api-for-wp\/src\/Security\/UserAuthorization.php\"><code>UserAuthorization<\/code><\/a> dipende dal servizio con contratto <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}\n<\/code><\/pre>\n<p>Grazie a <code>autowire: true<\/code>, il componente DependencyInjection far\u00e0 ricevere automaticamente al servizio <code>UserAuthorization<\/code> la sua dipendenza richiesta, che \u00e8 un&#8217;istanza di <code>UserAuthorizationSchemeRegistry<\/code>.<\/p>\n<h2>Quando Passare all\u2019Astrazione<\/h2>\n<p>L&#8217;astrazione del codice potrebbe consumare tempo e sforzi considerevoli, quindi dovremmo intraprenderla solo quando i suoi benefici superano i costi. Quelli che seguono sono suggerimenti per capire quando conviene astrarre il codice. Potete farlo usando gli snippet di codice in questo articolo o i plugin WordPress astratti suggeriti qui sotto.<\/p>\n<h3>Ottenere l&#8217;Accesso agli Strumenti<\/h3>\n<p>Come menzionato in precedenza, <a href=\"https:\/\/github.com\/humbug\/php-scoper\/issues\/303\" target=\"_blank\" rel=\"noopener noreferrer\">eseguire PHP-Scoper su WordPress \u00e8 difficile<\/a>. Disaccoppiando il codice di WordPress in pacchetti distinti, diventa possibile eseguire direttamente <a href=\"https:\/\/graphql-api.com\/blog\/graphql-api-for-wp-is-now-scoped-thanks-to-php-scoper\/\" target=\"_blank\" rel=\"noopener noreferrer\">un plugin WordPress<\/a>.<\/p>\n<h3>Ridurre le Tempistiche e il Costo degli Strumenti<\/h3>\n<p>L&#8217;esecuzione di una suite di test PHPUnit richiede pi\u00f9 tempo quando deve inizializzare ed eseguire WordPress rispetto a quando non lo fa. Meno tempo pu\u00f2 anche tradursi in meno soldi spesi per eseguire i test: <a href=\"https:\/\/kinsta.com\/it\/blog\/cosa-e-github\/\">GitHub<\/a> Actions, per esempio, fa pagare i runner ospitati da GitHub in base al tempo di utilizzo.<\/p>\n<h3>Non \u00c8 Necessaria una Rifattorizzazione Pesante<\/h3>\n<p>Un progetto esistente pu\u00f2 richiedere un pesante refactoring per introdurre l&#8217;architettura richiesta (dependency injection, suddivisione del codice in pacchetti, ecc.), e rendere cos\u00ec difficile l\u2019estrazione. Astrarre il codice quando si crea un progetto da zero lo rende molto pi\u00f9 gestibile.<\/p>\n<h3>Produrre Codice per Piattaforme Multiple<\/h3>\n<p>Estraendo il 90% del codice in un pacchetto CMS-agnostico, possiamo produrre una versione della libreria che funziona per un CMS o un framework diverso sostituendo solo il 10% del codice base complessivo.<\/p>\n<h3>Migrare a una Piattaforma Diversa<\/h3>\n<p>Se dobbiamo migrare un progetto da <a href=\"https:\/\/kinsta.com\/it\/blog\/wordpress-contro-drupal\/\">Drupal a WordPress<\/a>, da WordPress a <a href=\"https:\/\/kinsta.com\/it\/blog\/laravel-9\/\">Laravel<\/a>, o qualsiasi altra combinazione, allora solo il 10% del codice deve essere riscritto, e questo \u00e8 un risparmio significativo.<\/p>\n<h2>Le Migliori Pratiche<\/h2>\n<p>Mentre progettiamo i contratti per astrarre il nostro codice, ci sono diversi miglioramenti che possiamo applicare alla codebase.<\/p>\n<h3>Adesione al PSR-12<\/h3>\n<p>Quando definiamo l&#8217;interfaccia per accedere ai metodi WordPress, dovremmo aderire al <a href=\"https:\/\/www.php-fig.org\/psr\/psr-12\/\" target=\"_blank\" rel=\"noopener noreferrer\">PSR-12<\/a>. Questa specifica recente mira a ridurre l&#8217;attrito cognitivo quando si analizza il codice di diversi autori. Aderire al PSR-12 implica rinominare le funzioni di WordPress.<\/p>\n<p>WordPress nomina le funzioni usando <strong>snake_case<\/strong>, mentre PSR-12 usa <strong>camelCase<\/strong>. Quindi, la funzione <code>get_posts<\/code> diventer\u00e0 <code>getPosts<\/code>:<\/p>\n<pre><code class=\"language-php\">interface PostAPIInterface\n{\n  <span id=\"urn:enhancement-d2f0267a-1cf3-4107-9841-626b45a98b29\" class=\"textannotation\">public<\/span> <span id=\"urn:enhancement-a6eee24c-bec1-43cc-8f2b-0907e37b6477\" class=\"textannotation\">function<\/span> getPosts(array $<span id=\"urn:enhancement-09c729d0-a53c-4819-86b0-56bb47d514ab\" class=\"textannotation\">args<\/span> = null): PostInterface[]|int[];\n}\n<\/code><\/pre>\n<p>&#8230;e:<\/p>\n<pre><code class=\"language-php\"><span id=\"urn:enhancement-75912282-c90b-49bc-9f0d-4ff862c304cb\" class=\"textannotation\">class<\/span> PostAPI <span id=\"urn:enhancement-e1887e11-b24b-4314-b2e3-73af924b1f40\" class=\"textannotation\">implements<\/span> PostAPIInterface\n{\n  <span id=\"urn:enhancement-21d3230e-7a4f-49a9-bd7e-e50d37a2d2d2\" class=\"textannotation\">public<\/span> <span id=\"urn:enhancement-6cd00a6d-bdad-43d3-a162-9e1d56082ca9\" class=\"textannotation\">function<\/span> getPosts(array $<span id=\"urn:enhancement-cbdc4f7a-4dca-4deb-9b6b-b7058bae2a49\" class=\"textannotation\">args<\/span> = null): PostInterface[]|int[]\n  {\n    \/\/ This var <span id=\"urn:enhancement-f6d8629b-6236-4ffd-a1b9-1f7cb2221d78\" class=\"textannotation\">will<\/span> contain <span id=\"urn:enhancement-9cb83706-ebf2-4b5e-b683-0b4030aeaf8f\" class=\"textannotation\">WP<\/span>_Post[] or int[]\n    $wpPosts = \\get_posts($<span id=\"urn:enhancement-b33ba645-e20c-4399-ab5c-a4bcf4800800\" class=\"textannotation\">args<\/span>);\n\n    \/\/ Rest of the code\n    \/\/ ...\n  }\n}\n<\/code><\/pre>\n<h3>Metodi Split<\/h3>\n<p>I metodi nell&#8217;interfaccia non hanno bisogno di essere una replica di quelli di WordPress. Possiamo trasformarli quando ha senso. Per esempio, la funzione di WordPress <code>get_user_by($field, $value)<\/code> sa come recuperare l&#8217;utente dal database tramite il parametro <code>$field<\/code>, che accetta i valori <code>\"id\"<\/code>, <code>\"ID\"<\/code>, <code>\"slug\"<\/code>, <code>\"email\"<\/code> o <code>\"login\"<\/code>.<br \/>\nQuesto design presenta alcuni problemi:<\/p>\n<ul>\n<li>Non fallir\u00e0 in fase di compilazione se passiamo una stringa sbagliata<\/li>\n<li>Il parametro <code>$value<\/code> deve accettare tutti i tipi diversi per tutte le opzioni, anche se quando si passa <code>\"ID\"<\/code> si aspetta un <code>int<\/code>, e quando si passa <code>\"email\"<\/code> pu\u00f2 solo ricevere un <code>string<\/code><\/li>\n<\/ul>\n<p>Possiamo migliorare questa situazione dividendo la funzione in diverse parti:<\/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>Il contratto viene risolto per WordPress in questo modo (assumendo che abbiamo creato <code>UserWrapper<\/code> e <code>UserInterface<\/code>, come spiegato in precedenza):<\/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>Rimuovere i Dettagli di Implementazione dalla Firma della Funzione<\/h3>\n<p>Le funzioni in WordPress possono fornire informazioni su come sono implementate nella loro firma. Queste informazioni possono essere rimosse quando si valuta la funzione da una prospettiva astratta. Per esempio, per ottenere il cognome dell&#8217;utente in WordPress si chiama la funzione <code>get_the_author_meta<\/code>, rendendo esplicito che il cognome di un utente \u00e8 memorizzato come un valore &#8220;meta&#8221; (sulla tabella <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>Non dovete trasmettere questa informazione al contratto. Le interfacce si preoccupano solo del cosa, non del come. Quindi, il contratto pu\u00f2 invece avere un metodo:<\/p>\n<pre><code class=\"language-php\">interface UserAPIInterface\n{\n  public function getUserLastname(UserWrapper $userWrapper): string;\n  ...\n}\n<\/code><\/pre>\n<h3>Aggiungere Tipi Pi\u00f9 Rigidi<\/h3>\n<p>Alcune funzioni di WordPress possono ricevere parametri in modi diversi, portando all&#8217;ambiguit\u00e0. Per esempio, la funzione <code>add_query_arg<\/code> pu\u00f2 ricevere una singola chiave e un valore:<\/p>\n<pre><code class=\"language-php\">$url = add_query_arg('id', 5, $url);\n<\/code><\/pre>\n<p>&#8230; o un array di <code>chiave =&gt; valore<\/code>:<\/p>\n<pre><code class=\"language-php\">$url = add_query_arg(['id' =&gt; 5], $url);\n<\/code><\/pre>\n<p>La nostra interfaccia pu\u00f2 definire un intento pi\u00f9 comprensibile dividendo tali funzioni in diverse funzioni separate, ognuna delle quali accetta una combinazione unica di input:<\/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>Eliminare il Debito Tecnico<\/h3>\n<p>La funzione <code>get_posts<\/code> di WordPress restituisce non solo &#8220;post&#8221; ma anche &#8220;pagine&#8221; o qualsiasi entit\u00e0 di tipo &#8220;post personalizzati&#8221;, e queste entit\u00e0 non sono intercambiabili. Sia i post che le pagine sono post personalizzati, ma un post personalizzato non \u00e8 un post n\u00e9 una pagina. Pertanto, l&#8217;esecuzione di <code>get_posts<\/code> pu\u00f2 restituire delle pagine. Questo comportamento \u00e8 una discrepanza concettuale.<\/p>\n<p>Per correggerlo, <code>get_posts<\/code> dovrebbe invece essere chiamato <code>get_customposts<\/code>, ma non \u00e8 mai stato rinominato nel core di WordPress. Questo \u00e8 un problema comune con la maggior parte dei software di lunga data ed \u00e8 chiamato &#8220;debito tecnico&#8221;, cio\u00e8 un codice che ha dei problemi, ma che non viene mai corretto perch\u00e9 introdurrebbe dei cambiamenti di rottura.<\/p>\n<p>Quando creiamo i nostri contratti, per\u00f2, abbiamo l&#8217;opportunit\u00e0 di evitare questo tipo di debito tecnico. In questo caso, possiamo creare una nuova interfaccia <code>ModelAPIInterface<\/code> che pu\u00f2 trattare con entit\u00e0 di diversi tipi, e creiamo diversi metodi, ognuno per trattare un tipo diverso:<\/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>In questo modo la discrepanza non si verificher\u00e0 pi\u00f9 e vedrete questi risultati:<\/p>\n<ul>\n<li><code>getPosts<\/code> restituisce solo i post<\/li>\n<li><code>getPages<\/code> restituisce solo le pagine<\/li>\n<li><code>getCustomPosts<\/code> restituisce sia i post che le pagine<\/li>\n<\/ul>\n<h2>Vantaggi dell&#8217;Astrazione del Codice<\/h2>\n<p>I principali vantaggi dell&#8217;astrazione del codice di un&#8217;applicazione sono:<\/p>\n<ul>\n<li>Gli strumenti che funzionano su pacchetti che contengono solo codice commerciale sono pi\u00f9 facili da impostare e richiedono meno tempo (e meno soldi) per funzionare.<\/li>\n<li>Possiamo usare strumenti che non funzionano con WordPress, come lo scoping di un plugin con PHP-Scoper.<\/li>\n<li>I pacchetti che produciamo possono essere autonomi per essere usati con facilit\u00e0 in altre applicazioni.<\/li>\n<li>Migrare un&#8217;applicazione su altre piattaforme diventa pi\u00f9 facile.<\/li>\n<li>Possiamo smettere di pensare in termini di WordPress e ragionare in termini di logica di business.<\/li>\n<li>I contratti descrivono l&#8217;intento dell&#8217;applicazione, rendendola pi\u00f9 comprensibile.<\/li>\n<li>L&#8217;applicazione viene organizzata attraverso pacchetti, creando un&#8217;applicazione snella che contiene il minimo indispensabile e migliorandola progressivamente secondo le necessit\u00e0.<\/li>\n<li>Possiamo eliminare il debito tecnico.<\/li>\n<\/ul>\n<h2>Problemi con l&#8217;Astrazione del Codice<\/h2>\n<p>Gli svantaggi di astrarre il codice di un&#8217;applicazione sono:<\/p>\n<ul>\n<li>Inizialmente comporta una notevole quantit\u00e0 di lavoro.<\/li>\n<li>Il codice diventa pi\u00f9 prolisso; si aggiungono ulteriori strati di codice per ottenere lo stesso risultato.<\/li>\n<li>Potreste finire per produrre <a href=\"https:\/\/graphql-api.com\/blog\/why-to-support-cms-agnosticism-the-graphql-api-split-to-around-90-packages\/\" target=\"_blank\" rel=\"noopener noreferrer\">dozzine di pacchetti<\/a> che devono poi essere gestiti e mantenuti.<\/li>\n<li>Potreste aver bisogno di un monorepo per gestire tutti i pacchetti insieme.<\/li>\n<li>La dependency injection potrebbe essere eccessiva per applicazioni semplici (rendimenti decrescenti).<\/li>\n<li>L&#8217;astrazione del codice non sar\u00e0 mai completamente realizzata poich\u00e9 c&#8217;\u00e8 tipicamente una preferenza generale implicita nell&#8217;architettura del CMS.<\/li>\n<\/ul>\n<h2>Opzioni dei Plugin WordPress Astratti<\/h2>\n<p>Anche se \u00e8 generalmente pi\u00f9 saggio estrarre il vostro codice in un <a href=\"https:\/\/kinsta.com\/it\/blog\/installare-wordpress-in-locale\/\">ambiente locale<\/a> prima di lavorarci sopra, alcuni plugin di WordPress possono aiutarvi a raggiungere i vostri obiettivi di astrazione. Queste sono le scelte migliori secondo noi.<\/p>\n<h3>1. WPide<\/h3>\n<p>Prodotto da WebFactory Ltd, il popolare <a href=\"https:\/\/wordpress.org\/plugins\/wpide\/\" target=\"_blank\" rel=\"noopener noreferrer\">plugin WPide<\/a> estende notevolmente la funzionalit\u00e0 dell&#8217;editor di codice predefinito di WordPress. Funziona come un plugin WordPress astratto e vi permette di visualizzare il vostro codice in situ per visualizzare meglio ci\u00f2 che necessita di attenzione.<\/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=\"Il plugin WPide.\" width=\"900\" height=\"291\"><figcaption class=\"wp-caption-text\">Il plugin WPide.<\/figcaption><\/figure><\/figure>\n<p>WPide ha anche una funzione di ricerca e sostituzione per individuare rapidamente il codice obsoleto o scaduto e sostituirlo con una versione aggiornata.<\/p>\n<p>Oltre a questo, WPide fornisce un sacco di funzioni extra, tra cui:<\/p>\n<ul>\n<li>Evidenziazione della sintassi e dei blocchi.<\/li>\n<li><a href=\"https:\/\/kinsta.com\/it\/docs\/hosting-wordpress\/wordpress-backup\/#wordpress-backup\">Backup automatici.<\/a><\/li>\n<li>Creazione di file e cartelle.<\/li>\n<li>Browser completo dell&#8217;alberatura dei file.<\/li>\n<li>Accesso al filesystem API di WordPress.<\/li>\n<\/ul>\n<h3>2. Ultimate DB Manager<\/h3>\n<p>Il <a href=\"https:\/\/wordpress.org\/plugins\/ultimate-db-manager-lite\/\" target=\"_blank\" rel=\"noopener noreferrer\">plugin Ultimate WP DB Manager<\/a> di WPHobby vi offre uno strumento veloce per scaricare completamente i vostri database per l&#8217;estrazione e il refactoring.<\/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=\"Il plugin Ultimate DB Manager.\" width=\"900\" height=\"250\"><figcaption class=\"wp-caption-text\">Il plugin Ultimate DB Manager.<\/figcaption><\/figure><\/figure>\n<p>Naturalmente, i plugin di questo tipo non sono necessari per gli utenti Kinsta, poich\u00e9 Kinsta offre un <a href=\"https:\/\/kinsta.com\/it\/docs\/hosting-wordpress\/gestione-database\/accesso-database-wordpress\/\">accesso diretto al database<\/a> a tutti i clienti. Tuttavia, se non avete sufficiente accesso al database attraverso il vostro fornitore di hosting, Ultimate DB Manager potrebbe essere utile come plugin astratto per WordPress.<\/p>\n<h3>3. Il Vostro Plugin Personalizzato per l\u2019Astrazione di WordPress<\/h3>\n<p>Alla fine, la scelta migliore per l&#8217;astrazione sar\u00e0 sempre quella di creare il vostro plugin. Pu\u00f2 sembrare una grande impresa, ma se avete dei limiti per la gestione diretta dei vostri file principali di WordPress, questo \u00e8 buon espediente per realizzare l&#8217;astrazione.<\/p>\n<p>Farlo ha dei chiari vantaggi:<\/p>\n<ul>\n<li>Estrae le vostre funzioni dai file del vostro tema.<\/li>\n<li>Preserva il vostro codice attraverso le modifiche del tema e gli aggiornamenti del database.<\/li>\n<\/ul>\n<p>Potete imparare come creare il vostro plugin WordPress astratto attraverso il <a href=\"https:\/\/developer.wordpress.org\/plugins\/\" target=\"_blank\" rel=\"noopener noreferrer\">WordPress\u2019 Plugin Developer Handbook<\/a>.<\/p>\n\n<h2>Riepilogo<\/h2>\n<p>\u00c8 necessario astrarre il codice nelle nostre applicazioni? Come per ogni cosa, non c&#8217;\u00e8 una &#8220;risposta giusta&#8221; sempre valida, perch\u00e9 le cose cambiano da progetto a progetto. Quei progetti che richiedono un&#8217;enorme quantit\u00e0 di tempo di analisi con PHPUnit o PHPStan possono trarne il massimo beneficio, ma lo sforzo necessario per realizzarlo potrebbe non valerne sempre la pena.<\/p>\n<p>In questo articolo avete imparato tutto quello che c\u2019\u00e8 sapere per iniziare ad astrarre il codice di WordPress.<\/p>\n<p><em>Avete intenzione di implementare questa strategia nel vostro progetto? Se s\u00ec, userete un plugin WordPress astratto? Fatecelo sapere nella sezione dei commenti!<\/em><\/p>\n","protected":false},"excerpt":{"rendered":"<p>WordPress \u00e8 un CMS che ha ormai qualche anno, ma \u00e8 anche il pi\u00f9 utilizzato. C\u2019\u00e8 il tema del supporto di versioni PHP obsolete e del &#8230;<\/p>\n","protected":false},"author":196,"featured_media":47369,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_kinsta_gated_content":false,"_kinsta_gated_content_redirect":"","footnotes":""},"tags":[19973,15892],"topic":[25900,25873],"class_list":["post-47366","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","tag-code","tag-web-development","topic-plugin-wordpress","topic-sviluppo-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>Astrazione di WordPress: Best Practice e Plugin per l&#039;Astrazione di WordPress<\/title>\n<meta name=\"description\" content=\"Scopri come utilizzare snippet di codice o un plugin per l&#039;astrazione di WordPress per rimuovere le dipendenze fisse dal codice e produrre pacchetti interattivi.\" \/>\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\/it\/blog\/plugin-astrazione-wordpress\/\" \/>\n<meta property=\"og:locale\" content=\"it_IT\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Astrazione di WordPress: Best Practice e Plugin per l&#039;Astrazione di WordPress\" \/>\n<meta property=\"og:description\" content=\"Scopri come utilizzare snippet di codice o un plugin per l&#039;astrazione di WordPress per rimuovere le dipendenze fisse dal codice e produrre pacchetti interattivi.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/kinsta.com\/it\/blog\/plugin-astrazione-wordpress\/\" \/>\n<meta property=\"og:site_name\" content=\"Kinsta\u00ae\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/kinstaitalia\/\" \/>\n<meta property=\"article:published_time\" content=\"2021-09-06T09:09:17+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2023-03-14T12:38:01+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/kinsta.com\/it\/wp-content\/uploads\/sites\/2\/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=\"Scopri come utilizzare snippet di codice o un plugin per l&#039;astrazione di WordPress per rimuovere le dipendenze fisse dal codice e produrre pacchetti interattivi.\" \/>\n<meta name=\"twitter:image\" content=\"https:\/\/kinsta.com\/it\/wp-content\/uploads\/sites\/2\/2021\/09\/abstract-wordpress-plugin.jpeg\" \/>\n<meta name=\"twitter:creator\" content=\"@losoviz\" \/>\n<meta name=\"twitter:site\" content=\"@Kinsta_IT\" \/>\n<meta name=\"twitter:label1\" content=\"Scritto da\" \/>\n\t<meta name=\"twitter:data1\" content=\"Leonardo Losoviz\" \/>\n\t<meta name=\"twitter:label2\" content=\"Tempo di lettura stimato\" \/>\n\t<meta name=\"twitter:data2\" content=\"15 minuti\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/kinsta.com\/it\/blog\/plugin-astrazione-wordpress\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/kinsta.com\/it\/blog\/plugin-astrazione-wordpress\/\"},\"author\":{\"name\":\"Leonardo Losoviz\",\"@id\":\"https:\/\/kinsta.com\/it\/#\/schema\/person\/c382de1885cc21b079ec1e71d7faf238\"},\"headline\":\"Astrazione di WordPress: Best Practice e Plugin per l&#8217;Astrazione di WordPress\",\"datePublished\":\"2021-09-06T09:09:17+00:00\",\"dateModified\":\"2023-03-14T12:38:01+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/kinsta.com\/it\/blog\/plugin-astrazione-wordpress\/\"},\"wordCount\":2884,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/kinsta.com\/it\/#organization\"},\"image\":{\"@id\":\"https:\/\/kinsta.com\/it\/blog\/plugin-astrazione-wordpress\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/kinsta.com\/it\/wp-content\/uploads\/sites\/2\/2021\/09\/abstract-wordpress-plugin.jpeg\",\"keywords\":[\"code\",\"web development\"],\"articleSection\":[\"I Migliori Tutorial su WordPress\"],\"inLanguage\":\"it-IT\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/kinsta.com\/it\/blog\/plugin-astrazione-wordpress\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/kinsta.com\/it\/blog\/plugin-astrazione-wordpress\/\",\"url\":\"https:\/\/kinsta.com\/it\/blog\/plugin-astrazione-wordpress\/\",\"name\":\"Astrazione di WordPress: Best Practice e Plugin per l'Astrazione di WordPress\",\"isPartOf\":{\"@id\":\"https:\/\/kinsta.com\/it\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/kinsta.com\/it\/blog\/plugin-astrazione-wordpress\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/kinsta.com\/it\/blog\/plugin-astrazione-wordpress\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/kinsta.com\/it\/wp-content\/uploads\/sites\/2\/2021\/09\/abstract-wordpress-plugin.jpeg\",\"datePublished\":\"2021-09-06T09:09:17+00:00\",\"dateModified\":\"2023-03-14T12:38:01+00:00\",\"description\":\"Scopri come utilizzare snippet di codice o un plugin per l'astrazione di WordPress per rimuovere le dipendenze fisse dal codice e produrre pacchetti interattivi.\",\"breadcrumb\":{\"@id\":\"https:\/\/kinsta.com\/it\/blog\/plugin-astrazione-wordpress\/#breadcrumb\"},\"inLanguage\":\"it-IT\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/kinsta.com\/it\/blog\/plugin-astrazione-wordpress\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"it-IT\",\"@id\":\"https:\/\/kinsta.com\/it\/blog\/plugin-astrazione-wordpress\/#primaryimage\",\"url\":\"https:\/\/kinsta.com\/it\/wp-content\/uploads\/sites\/2\/2021\/09\/abstract-wordpress-plugin.jpeg\",\"contentUrl\":\"https:\/\/kinsta.com\/it\/wp-content\/uploads\/sites\/2\/2021\/09\/abstract-wordpress-plugin.jpeg\",\"width\":1460,\"height\":730,\"caption\":\"Astrazione di WordPress\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/kinsta.com\/it\/blog\/plugin-astrazione-wordpress\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/kinsta.com\/it\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Plugin WordPress\",\"item\":\"https:\/\/kinsta.com\/it\/argomenti\/plugin-wordpress\/\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Astrazione di WordPress: Best Practice e Plugin per l&#8217;Astrazione di WordPress\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/kinsta.com\/it\/#website\",\"url\":\"https:\/\/kinsta.com\/it\/\",\"name\":\"Kinsta\u00ae\",\"description\":\"Soluzioni di hosting premium, veloci e sicure\",\"publisher\":{\"@id\":\"https:\/\/kinsta.com\/it\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/kinsta.com\/it\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"it-IT\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/kinsta.com\/it\/#organization\",\"name\":\"Kinsta\",\"url\":\"https:\/\/kinsta.com\/it\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"it-IT\",\"@id\":\"https:\/\/kinsta.com\/it\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/kinsta.com\/it\/wp-content\/uploads\/sites\/2\/2023\/12\/kinsta-logo.jpeg\",\"contentUrl\":\"https:\/\/kinsta.com\/it\/wp-content\/uploads\/sites\/2\/2023\/12\/kinsta-logo.jpeg\",\"width\":500,\"height\":500,\"caption\":\"Kinsta\"},\"image\":{\"@id\":\"https:\/\/kinsta.com\/it\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/www.facebook.com\/kinstaitalia\/\",\"https:\/\/x.com\/Kinsta_IT\",\"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\/it\/#\/schema\/person\/c382de1885cc21b079ec1e71d7faf238\",\"name\":\"Leonardo Losoviz\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"it-IT\",\"@id\":\"https:\/\/kinsta.com\/it\/#\/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\/it\/blog\/author\/leonardolosoviz\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Astrazione di WordPress: Best Practice e Plugin per l'Astrazione di WordPress","description":"Scopri come utilizzare snippet di codice o un plugin per l'astrazione di WordPress per rimuovere le dipendenze fisse dal codice e produrre pacchetti interattivi.","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\/it\/blog\/plugin-astrazione-wordpress\/","og_locale":"it_IT","og_type":"article","og_title":"Astrazione di WordPress: Best Practice e Plugin per l'Astrazione di WordPress","og_description":"Scopri come utilizzare snippet di codice o un plugin per l'astrazione di WordPress per rimuovere le dipendenze fisse dal codice e produrre pacchetti interattivi.","og_url":"https:\/\/kinsta.com\/it\/blog\/plugin-astrazione-wordpress\/","og_site_name":"Kinsta\u00ae","article_publisher":"https:\/\/www.facebook.com\/kinstaitalia\/","article_published_time":"2021-09-06T09:09:17+00:00","article_modified_time":"2023-03-14T12:38:01+00:00","og_image":[{"width":1460,"height":730,"url":"https:\/\/kinsta.com\/it\/wp-content\/uploads\/sites\/2\/2021\/09\/abstract-wordpress-plugin.jpeg","type":"image\/jpeg"}],"author":"Leonardo Losoviz","twitter_card":"summary_large_image","twitter_description":"Scopri come utilizzare snippet di codice o un plugin per l'astrazione di WordPress per rimuovere le dipendenze fisse dal codice e produrre pacchetti interattivi.","twitter_image":"https:\/\/kinsta.com\/it\/wp-content\/uploads\/sites\/2\/2021\/09\/abstract-wordpress-plugin.jpeg","twitter_creator":"@losoviz","twitter_site":"@Kinsta_IT","twitter_misc":{"Scritto da":"Leonardo Losoviz","Tempo di lettura stimato":"15 minuti"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/kinsta.com\/it\/blog\/plugin-astrazione-wordpress\/#article","isPartOf":{"@id":"https:\/\/kinsta.com\/it\/blog\/plugin-astrazione-wordpress\/"},"author":{"name":"Leonardo Losoviz","@id":"https:\/\/kinsta.com\/it\/#\/schema\/person\/c382de1885cc21b079ec1e71d7faf238"},"headline":"Astrazione di WordPress: Best Practice e Plugin per l&#8217;Astrazione di WordPress","datePublished":"2021-09-06T09:09:17+00:00","dateModified":"2023-03-14T12:38:01+00:00","mainEntityOfPage":{"@id":"https:\/\/kinsta.com\/it\/blog\/plugin-astrazione-wordpress\/"},"wordCount":2884,"commentCount":0,"publisher":{"@id":"https:\/\/kinsta.com\/it\/#organization"},"image":{"@id":"https:\/\/kinsta.com\/it\/blog\/plugin-astrazione-wordpress\/#primaryimage"},"thumbnailUrl":"https:\/\/kinsta.com\/it\/wp-content\/uploads\/sites\/2\/2021\/09\/abstract-wordpress-plugin.jpeg","keywords":["code","web development"],"articleSection":["I Migliori Tutorial su WordPress"],"inLanguage":"it-IT","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/kinsta.com\/it\/blog\/plugin-astrazione-wordpress\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/kinsta.com\/it\/blog\/plugin-astrazione-wordpress\/","url":"https:\/\/kinsta.com\/it\/blog\/plugin-astrazione-wordpress\/","name":"Astrazione di WordPress: Best Practice e Plugin per l'Astrazione di WordPress","isPartOf":{"@id":"https:\/\/kinsta.com\/it\/#website"},"primaryImageOfPage":{"@id":"https:\/\/kinsta.com\/it\/blog\/plugin-astrazione-wordpress\/#primaryimage"},"image":{"@id":"https:\/\/kinsta.com\/it\/blog\/plugin-astrazione-wordpress\/#primaryimage"},"thumbnailUrl":"https:\/\/kinsta.com\/it\/wp-content\/uploads\/sites\/2\/2021\/09\/abstract-wordpress-plugin.jpeg","datePublished":"2021-09-06T09:09:17+00:00","dateModified":"2023-03-14T12:38:01+00:00","description":"Scopri come utilizzare snippet di codice o un plugin per l'astrazione di WordPress per rimuovere le dipendenze fisse dal codice e produrre pacchetti interattivi.","breadcrumb":{"@id":"https:\/\/kinsta.com\/it\/blog\/plugin-astrazione-wordpress\/#breadcrumb"},"inLanguage":"it-IT","potentialAction":[{"@type":"ReadAction","target":["https:\/\/kinsta.com\/it\/blog\/plugin-astrazione-wordpress\/"]}]},{"@type":"ImageObject","inLanguage":"it-IT","@id":"https:\/\/kinsta.com\/it\/blog\/plugin-astrazione-wordpress\/#primaryimage","url":"https:\/\/kinsta.com\/it\/wp-content\/uploads\/sites\/2\/2021\/09\/abstract-wordpress-plugin.jpeg","contentUrl":"https:\/\/kinsta.com\/it\/wp-content\/uploads\/sites\/2\/2021\/09\/abstract-wordpress-plugin.jpeg","width":1460,"height":730,"caption":"Astrazione di WordPress"},{"@type":"BreadcrumbList","@id":"https:\/\/kinsta.com\/it\/blog\/plugin-astrazione-wordpress\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/kinsta.com\/it\/"},{"@type":"ListItem","position":2,"name":"Plugin WordPress","item":"https:\/\/kinsta.com\/it\/argomenti\/plugin-wordpress\/"},{"@type":"ListItem","position":3,"name":"Astrazione di WordPress: Best Practice e Plugin per l&#8217;Astrazione di WordPress"}]},{"@type":"WebSite","@id":"https:\/\/kinsta.com\/it\/#website","url":"https:\/\/kinsta.com\/it\/","name":"Kinsta\u00ae","description":"Soluzioni di hosting premium, veloci e sicure","publisher":{"@id":"https:\/\/kinsta.com\/it\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/kinsta.com\/it\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"it-IT"},{"@type":"Organization","@id":"https:\/\/kinsta.com\/it\/#organization","name":"Kinsta","url":"https:\/\/kinsta.com\/it\/","logo":{"@type":"ImageObject","inLanguage":"it-IT","@id":"https:\/\/kinsta.com\/it\/#\/schema\/logo\/image\/","url":"https:\/\/kinsta.com\/it\/wp-content\/uploads\/sites\/2\/2023\/12\/kinsta-logo.jpeg","contentUrl":"https:\/\/kinsta.com\/it\/wp-content\/uploads\/sites\/2\/2023\/12\/kinsta-logo.jpeg","width":500,"height":500,"caption":"Kinsta"},"image":{"@id":"https:\/\/kinsta.com\/it\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/kinstaitalia\/","https:\/\/x.com\/Kinsta_IT","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\/it\/#\/schema\/person\/c382de1885cc21b079ec1e71d7faf238","name":"Leonardo Losoviz","image":{"@type":"ImageObject","inLanguage":"it-IT","@id":"https:\/\/kinsta.com\/it\/#\/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\/it\/blog\/author\/leonardolosoviz\/"}]}},"acf":[],"_links":{"self":[{"href":"https:\/\/kinsta.com\/it\/wp-json\/wp\/v2\/posts\/47366","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/kinsta.com\/it\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/kinsta.com\/it\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/kinsta.com\/it\/wp-json\/wp\/v2\/users\/196"}],"replies":[{"embeddable":true,"href":"https:\/\/kinsta.com\/it\/wp-json\/wp\/v2\/comments?post=47366"}],"version-history":[{"count":16,"href":"https:\/\/kinsta.com\/it\/wp-json\/wp\/v2\/posts\/47366\/revisions"}],"predecessor-version":[{"id":66864,"href":"https:\/\/kinsta.com\/it\/wp-json\/wp\/v2\/posts\/47366\/revisions\/66864"}],"alternate":[{"embeddable":true,"hreflang":"en","title":"English","href":"https:\/\/kinsta.com\/it\/wp-json\/kinsta\/v1\/posts\/47366\/translations\/en"},{"embeddable":true,"hreflang":"it","title":"Italian","href":"https:\/\/kinsta.com\/it\/wp-json\/kinsta\/v1\/posts\/47366\/translations\/it"},{"embeddable":true,"hreflang":"fr","title":"French","href":"https:\/\/kinsta.com\/it\/wp-json\/kinsta\/v1\/posts\/47366\/translations\/fr"},{"embeddable":true,"hreflang":"es","title":"Spanish","href":"https:\/\/kinsta.com\/it\/wp-json\/kinsta\/v1\/posts\/47366\/translations\/es"},{"embeddable":true,"hreflang":"pt","title":"Portuguese","href":"https:\/\/kinsta.com\/it\/wp-json\/kinsta\/v1\/posts\/47366\/translations\/pt"},{"embeddable":true,"hreflang":"de","title":"German","href":"https:\/\/kinsta.com\/it\/wp-json\/kinsta\/v1\/posts\/47366\/translations\/de"},{"embeddable":true,"hreflang":"nl","title":"Dutch","href":"https:\/\/kinsta.com\/it\/wp-json\/kinsta\/v1\/posts\/47366\/translations\/nl"},{"href":"https:\/\/kinsta.com\/it\/wp-json\/kinsta\/v1\/posts\/47366\/tree"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/kinsta.com\/it\/wp-json\/wp\/v2\/media\/47369"}],"wp:attachment":[{"href":"https:\/\/kinsta.com\/it\/wp-json\/wp\/v2\/media?parent=47366"}],"wp:term":[{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/kinsta.com\/it\/wp-json\/wp\/v2\/tags?post=47366"},{"taxonomy":"topic","embeddable":true,"href":"https:\/\/kinsta.com\/it\/wp-json\/wp\/v2\/topic?post=47366"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}