Caricamento automatico e spazi dei nomi nei plugin e nei temi di WordPress: può funzionare?


70

Qualcuno ha usato gli spazi dei nomi di caricamento automatico e / o PHP all'interno di un plugin o tema?

Pensi di usarli? Alcun danno? Le insidie?

Nota: gli spazi dei nomi sono solo PHP 5.3+. Supponiamo, per questa domanda, che sai che avrai a che fare con server che conosci avere PHP 5.3 o versioni successive.

Risposte:


88

Va bene, ho avuto due grandi progetti in cui ho avuto il controllo del server abbastanza per lo spazio dei nomi e fare affidamento sul caricamento automatico.

Innanzitutto. Il caricamento automatico è fantastico. Non preoccuparti è una cosa relativamente buona.

Ecco un caricatore che ho usato su alcuni progetti. Verifica per prima cosa che la classe si trovi nello spazio dei nomi corrente, quindi in caso contrario esegue il bail. Da lì è solo un po 'di manipolazione delle stringhe per trovare la classe.

<?php
spl_autoload_register(__NAMESPACE__ . '\\autoload');
function autoload($cls)
{
    $cls = ltrim($cls, '\\');
    if(strpos($cls, __NAMESPACE__) !== 0)
        return;

    $cls = str_replace(__NAMESPACE__, '', $cls);

    $path = PLUGIN_PATH_PATH . 'inc' . 
        str_replace('\\', DIRECTORY_SEPARATOR, $cls) . '.php';

    require_once($path);
}

Si potrebbe facilmente adattare questo per l'uso senza spazi dei nomi. Supponendo che il prefisso sia uniformemente inserito nelle classi del tema / del plugin, si potrebbe semplicemente verificare quel prefisso. Quindi utilizzare i trattini bassi nel nome della classe come segnaposto per i separatori di directory. Se stai usando molte classi, probabilmente vorrai usare una sorta di caricatore automatico di classmap.

Spazi dei nomi e ganci

Il sistema di hook di WordPress funziona usando call_user_func(e call_user_func_array), che prende i nomi delle funzioni come stringhe e li chiama quando viene effettuata la chiamata do_action(e, successivamente, call_user_func) della funzione.

Con gli spazi dei nomi, ciò significa che dovrai passare nomi di funzioni completi che includono lo spazio dei nomi in hook.

<?php
namespace WPSE\SomeNameSpace;

add_filter('some_filter', 'WPSE\\SomeNameSpace\\the_function');
function the_function()
{
   return 'did stuff';
}

Probabilmente sarebbe meglio fare un uso liberale della __NAMESPACE__costante magica se vuoi farlo.

<?php
namespace WPSE\SomeNameSpace;

add_filter('some_filter', __NAMESPACE__ . '\\the_function');
function the_function()
{
   return 'did stuff';
}

Se metti sempre i tuoi ganci in classe, è più facile. Lo standard crea l'istanza di una classe e tutti gli hook nel costruttore con $thisfunzionano bene.

<?php
namespace WPSE\SomeNameSpace;

new Plugin;

class Plugin
{
    function __construct()
    {
        add_action('plugins_loaded', array($this, 'loaded'));
    }

    function loaded()
    {
        // this works!
    }
}

Se usi metodi statici come voglio fare, dovrai passare il nome completo della classe come primo argomento dell'array. È un sacco di lavoro, quindi puoi semplicemente usare la __CLASS__costante magica o get_class.

<?php
namespace WPSE\SomeNameSpace;

Plugin::init();

class Plugin
{
    public static function init()
    {
        add_action('plugins_loaded', array(__CLASS__, 'loaded'));
        // OR: add_action('plugins_loaded', array(get_class(), 'loaded'));
    }

    public static function loaded()
    {
        // this works!
    }
}

Utilizzo delle classi principali

La risoluzione del nome classe di PHP è un po 'traballante. Se hai intenzione di utilizzare le classi WP di base ( WP_Widgetnell'esempio seguente) devi fornire usedichiarazioni.

use \WP_Widget;

class MyWidget extends WP_Widget
{
   // ...
}

Oppure puoi usare il nome di classe completo, in pratica semplicemente aggiungerlo con una barra rovesciata.

<?php
namespace WPSE\SomeNameSpace;

class MyWidget extends \WP_Widget
{
   // ...
}

definisce

Questo è PHP più generale, ma mi ha morso, quindi eccolo qui.

Potresti voler definire cose che userai spesso, come il percorso del tuo plugin. L'uso dell'istruzione define mette le cose nello spazio dei nomi root a meno che non passi esplicitamente lo spazio dei nomi nel primo argomento di define.

<?php
namespace WPSE\SomeNameSpace;

// root namespace
define('WPSE_63668_PATH', plugin_dir_path(__FILE__));

// in the current namespace
define(__NAMESPACE__ . '\\PATH', plugin_dir_path(__FILE__));

Puoi anche usare la constparola chiave on nel livello principale di un file con PHP 5.3 plus. constssono sempre nello spazio dei nomi corrente, ma sono meno flessibili di una definechiamata.

<?php
namespace WPSE\SomeNameSpace;

// in the current namespace
const MY_CONST = 1;

// this won't work!
const MY_PATH = plugin_dir_path(__FILE__);

Sentiti libero di aggiungere altri suggerimenti che potresti avere!


16

Ecco una risposta per il 2017.

Il caricamento automatico è fantastico. Il namespace è fantastico.

Anche se puoi farlo da solo, nel 2017 ha più senso usare il magnifico e onnipresente compositore per gestire i tuoi requisiti PHP. Composer supporta sia il caricamento automatico PSR-0 che PSR-4 , ma il primo è stato deprecato dal 2014, quindi usa PSR-4. Riduce la complessità delle tue directory.

Conserviamo ciascuno dei nostri plugin / temi nel proprio repository Github, ognuno con il proprio composer.jsonfile e composer.lockfile.

Ecco la struttura di directory che utilizziamo per i nostri plugin. (Non abbiamo un plugin chiamato awesome-plugin, ma dovremmo.)

plugins/awesome-plugin/bootstrap.php
plugins/awesome-plugin/composer.json
plugins/awesome-plugin/composer.lock
plugins/awesome-plugin/awesome-plugin.php
plugins/awesome-plugin/src/*

plugins/awesome-plugin/vendor/autoload.php
plugins/awesome-plugin/vendor/*

Se si fornisce un composer.jsonfile appropriato , Composer gestisce qui la spaziatura dei nomi e il caricamento automatico.

{
    "name": "awesome-company/awesome-plugin",
    "description": "Wordpress plugin for AwesomeCompany website, providing awesome functionality.",
    "type": "wordpress-plugin",
    "autoload": {
        "psr-4": {
            "AwesomeCompany\\Plugins\\AwesomePlugin\\": "src"
        }
    }
}

Quando esegui composer install, crea la vendordirectory e il vendor/autoload.phpfile, che caricherà automaticamente tutti i tuoi file con spaziatura dei nomi src/e qualsiasi altra libreria che potresti richiedere.

Quindi nella parte superiore del file del plug-in principale (che per noi è awesome-plugin.php), dopo i metadati del plug-in, hai semplicemente bisogno di:

// Composer autoloading.
require_once __DIR__ . '/vendor/autoload.php';

...

Funzione bonus

Non è una necessità, ma utilizziamo la piastra di cottura Bedrock Wordpress per utilizzare Composer sin dall'inizio. Quindi possiamo usare Composer per assemblare i plugin di cui abbiamo bisogno tramite Composer, incluso il tuo plugin che hai scritto sopra. Inoltre, grazie a WPackagist , puoi richiedere qualsiasi altro plugin da Wordpress.org (vedi esempio di cool-themee cool-pluginsotto).

{
  "name": "awesome-company/awesome-website",
  "type": "project",
  "license": "proprietary",
  "description": "WordPress boilerplate with modern development tools, easier configuration, and an improved folder structure",
  "config": {
    "preferred-install": "dist"
  },
  "repositories": [
    {
      "type": "composer",
      "url": "https://wpackagist.org"
    },
    { // Tells Composer to look for our proprietary Awesome Plugin here.
        "url": "https://github.com/awesome-company/awesome-plugin.git",
        "type": "git"
    }
  ],
  "require": {
    "php": ">=5.5",
    "awesome-company/awesome-plugin": "dev-production", // Our plugin!
    "wpackagist-plugin/cool-plugin": "dev-trunk",       // Someone else' plugin
    "wpackagist-theme/cool-theme": "dev-trunk",         // Someone else' theme
    "composer/installers": "~1.2.0",     // Bedrock default
    "vlucas/phpdotenv": "^2.0.1",        // Bedrock default
    "johnpbloch/wordpress": "4.7.5",     // Bedrock default
    "oscarotero/env": "^1.0",            // Bedrock default
    "roots/wp-password-bcrypt": "1.0.0"  // Bedrock default
  },
  "extra": {
    // This is the magic that drops packages with the correct TYPE in the correct location. 
    "installer-paths": {
      "web/app/mu-plugins/{$name}/": ["type:wordpress-muplugin"],
      "web/app/plugins/{$name}/": ["type:wordpress-plugin"],
      "web/app/themes/{$name}/": ["type:wordpress-theme"]
    },
    "wordpress-install-dir": "web/wp"
  },
  "scripts": {
    "test": [
      "vendor/bin/phpcs"
    ]
  }
}

Nota 1: i commenti non sono legali in JSON, ma ho annotato il file sopra per maggiore chiarezza.

Nota 2: per brevità ho eliminato alcuni bit del file Bedrock della piastra di caldaia.

Nota 3: ecco perché il typecampo nel primo composer.jsonfile è significativo. Il compositore lo rilascia automaticamente nella web/app/pluginsdirectory.


Apprezzo la tua risposta, molto utile! Ma sono curioso del "bootstrap.php" a cui ti riferisci. Cosa contiene? :)
INT

1
Avere un file bootstrap.php è una cosa stilistica che faccio nella maggior parte dei miei progetti, dentro o fuori WP. Il mio bootstrapper normalmente controlla solo le impostazioni e le variabili di ambiente; il suo scopo principale è assicurarsi che il mio plugin abbia sempre ciò di cui ha bisogno per funzionare, indipendentemente dal fatto che sia stato eseguito all'interno di WP o come app PHP autonoma.
haz,

4

Uso il caricamento automatico (poiché il mio plug-in ha molte classi, in parte perché include Twig), non ho mai avuto un problema portato alla mia attenzione (plug-in installato> 20.000 volte).

Se sei sicuro che non avrai mai bisogno di usare un'installazione php che non supporta gli spazi dei nomi, di nuovo stai bene (~ 70% degli attuali blog di wordpress non supporta gli spazi dei nomi). Alcune cose da notare:

Mi sembra di ricordare che gli spazi dei nomi non fanno distinzione tra maiuscole e minuscole in php normale, ma lo sono quando si utilizza fastcgi php su iis - questo provoca alcuni mal di testa se si esegue il test su Linux e non si individua una lettera minuscola canaglia.

Inoltre, anche se sei sicuro che il codice che stai attualmente sviluppando verrà utilizzato solo su> 5.3.0, non sarai in grado di riutilizzare alcun codice con progetti che non hanno quel lusso - questo è il motivo principale per cui non ho spazi dei nomi utilizzati nei progetti interni. Ho scoperto che gli spazi dei nomi in realtà non aggiungere che molto se confrontato con la possibile mal di testa di dover rimuovere la dipendenza su di loro.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.