Skripte / Stile in die Warteschlange stellen, wenn ein Shortcode vorhanden ist

54

Wie können Skripte und / oder Stile für die Verwendung in Plugins registriert / in die Warteschlange gestellt werden?

Ich habe vor kurzem ein einfaches Plugin-Plugin gemacht , um den Benutzer Avatar / Gravatar mit einem Shortcode hinzuzufügen. Ich habe verschiedene Stiloptionen für die Anzeige des Avatars (quadratisch, rund usw.) und habe mich entschieden, die CSS direkt in den Shortcode selbst einzufügen.

Jetzt ist mir jedoch klar, dass dies kein guter Ansatz ist, da der CSS-Code jedes Mal wiederholt wird, wenn der Shortcode auf einer Seite verwendet wird. Ich habe mehrere andere Ansätze auf dieser Site gesehen und der wp-Codex hat sogar zwei eigene Beispiele, so dass es schwierig ist zu wissen, welcher Ansatz am konsistentesten und schnellsten ist.

Hier sind die Methoden, die mir derzeit bekannt sind:

Methode 1: Direkt in den Shortcode aufnehmen - Dies ist das, was ich derzeit im Plugin mache, aber es scheint nicht gut zu sein, da es den Code wiederholt.

class My_Shortcode {
function handle_shortcode( $atts, $content="" ) {
/* simply enqueue or print the scripts/styles in the shortcode itself */
?>
<style type="text/css">

</style>
<?php
    return "$content";
     }
}
add_shortcode( 'myshortcode', array( 'My_Shortcode', 'handle_shortcode' ) );

Methode 2: Verwenden Sie die Klasse, um Skripts oder Stile bedingt in die Warteschlange zu stellen

class My_Shortcode {
    static $add_script;
    static function init() {
        add_shortcode('myshortcode', array(__CLASS__, 'handle_shortcode'));
        add_action('init', array(__CLASS__, 'register_script'));
        add_action('wp_footer', array(__CLASS__, 'print_script'));
    }
    static function handle_shortcode($atts) {
        self::$add_script = true;
        // shortcode handling here
    }
    static function register_script() {
        wp_register_script('my-script', plugins_url('my-script.js', __FILE__), array('jquery'), '1.0', true);
    }
    static function print_script() {
        if ( ! self::$add_script )
            return;
        wp_print_scripts('my-script');
    }
}
My_Shortcode::init();

Methode 3: Verwenden von get_shortcode_regex();

function your_prefix_detect_shortcode() {

    global $wp_query;   
    $posts = $wp_query->posts;
    $pattern = get_shortcode_regex();

    foreach ($posts as $post){
        if (   preg_match_all( '/'. $pattern .'/s', $post->post_content, $matches )
            && array_key_exists( 2, $matches )
            && in_array( 'myshortcode', $matches[2] ) )
        {
            // css/js 
            break;  
        }    
    }
}
add_action( 'wp', 'your_prefix_detect_shortcode' );

Methode 4: Verwenden von has_shortcode();

function custom_shortcode_scripts() {
    global $post;
    if( is_a( $post, 'WP_Post' ) && has_shortcode( $post->post_content, 'myshortcode') ) {
        wp_enqueue_script( 'my-script');
    }
}
add_action( 'wp_enqueue_scripts', 'custom_shortcode_scripts');
Bryan Willis
quelle
Ich denke, es Method 4: Using has_shortcode();ist am besten, weil es sicherstellt, dass Skripte und Stile einmal geladen werden, wenn der Inhalt des Beitrags einen Shortcode enthält, unabhängig von der mehrfachen Verwendung des Shortcodes. Obwohl es möglicherweise nicht für Shortcode-Anwendungen in Widgets oder in der Seitenleiste funktioniert, bin ich mir nicht sicher. Wenn es sich um ein Plugin handelt, würde ich Ihnen nicht empfehlen, Skripte mit einem Shortcode zu verknüpfen, da einige möglicherweise Ihre Funktion anstelle des Shortcodes aufrufen, um die gewünschte Ausgabe zu erhalten.
Robert Hue

Antworten:

45

Ich habe einen anderen Weg gefunden, der für mich gut funktioniert:

Hier ist ein Beispiel-Plugin mit dieser Methode, mit dem Sie get_avatar als Shortcode verwenden können. Das Stylesheet wird nur in die Warteschlange gestellt, wenn der Shortcode vorhanden ist.

Verwendung (ID ist standardmäßig der aktuelle Benutzer):

[get_avatar id="" size="32" default="mystery" alt="Profile Photo" class="round"]

function wpse_165754_avatar_shortcode_wp_enqueue_scripts() {
    wp_register_style( 'get-avatar-style', plugins_url( '/css/style.css', __FILE__ ), array(), '1.0.0', 'all' );
}

add_action( 'wp_enqueue_scripts', 'wpse_165754_avatar_shortcode_wp_enqueue_scripts' );
if ( function_exists( 'get_avatar' ) ) {
    function wpse_165754_user_avatar_shortcode( $attributes ) {

        global $current_user;
        get_currentuserinfo();

        extract( shortcode_atts(
                     array(
                         "id"      => $current_user->ID,
                         "size"    => 32,
                         "default" => 'mystery',
                         "alt"     => '',
                         "class"   => '',
                     ), $attributes, 'get_avatar' ) );

        $get_avatar = get_avatar( $id, $size, $default, $alt );

        wp_enqueue_style( 'get-avatar-style' );

        return '<span class="get_avatar ' . $class . '">' . $get_avatar . '</span>';
    }

    add_shortcode( 'get_avatar', wpse_165754_user_avatar_shortcode' );
}
jblanche
quelle
Ich habe vergessen, dass ich diese Frage letztes Jahr gestellt habe, aber in vielen Fällen habe ich auch so angefangen. Es ist eine Art Kombination von Methode 1 und 2.
Bryan Willis
4
Diese Methode lädt das CSS in die Fußzeile, was hat sicherlich Einschränkungen?
Jacob Raccuia
1
Dies ist absolut der richtige Weg, um dies zu tun. Verwenden Sie diese Methode, wenn Sie ein Skript oder Stylesheet bedingt laden müssen, wenn der wp_enqueue_scriptsHook bereits aufgetreten ist. (Shortcodes werden analysiert, währenddessen the_contentein Teil des the_postHooks ist. Wenn Sie das Skript nicht bereits registriert haben, ist es zu spät, eine
Warteschlange einzurichten.
26

Bevor ich mit der Beantwortung beginne, muss ich sagen, dass CSS und JS nicht dasselbe sind.

Der Grund ist einfach: Während das Hinzufügen von js zum Hauptteil der Seite (in der Fußzeile) ein gängiger und gültiger Weg ist, muss CSS im <head>Abschnitt der Seite platziert werden: Auch wenn die Mehrheit der Browser CSS in der Seite ordnungsgemäß rendern kann body, das ist kein gültiger HTML-Code.

Wenn ein Shortcode gerendert wird, der <head>Abschnitt bereits gedruckt wurde, bedeutet dies, dass js problemlos in der Fußzeile hinzugefügt werden kann, jedoch muss css hinzugefügt werden, bevor der Shortcode gerendert wird.

Skripte

Wenn Ihr Shortcode nur js benötigt, haben Sie Glück und können nur wp_enqueue_scriptim Rumpf des Shortcode-Rückrufs Folgendes verwenden :

add_shortcode( 'myshortcode', 'my_handle_shortcode' );

function my_handle_shortcode() {
  wp_enqueue_script( 'myshortcodejs', '/path/to/js/file.js' );
  // rest of code here...
}

Dabei wird Ihr Skript nur einmal in die Fußzeile eingefügt, auch wenn der Shortcode mehrmals auf der Seite verwendet wird.

Stile

Wenn Sie für den Code Stile benötigen, müssen Sie vor dem eigentlichen Rendern des Shortcodes handeln .

Hierfür gibt es verschiedene Möglichkeiten:

  1. Sehen Sie sich alle Posts in der aktuellen Abfrage an und fügen Sie bei Bedarf die Shortcode-Stile hinzu. Dies ist, was Sie in Methode 3 und 4 in OP tun. Tatsächlich tun beide Methoden dasselbe, wurden jedoch has_shortcodein WP 3.6 hinzugefügt, obwohl get_shortcode_regexes seit Version 2.5 verfügbar ist. Verwenden get_shortcode_regexSie diese Methode nur, wenn Sie Ihr Plugin mit älteren Versionen kompatibel machen möchten.

  2. Fügen Sie auf allen Seiten immer den Shortcode-Stil hinzu

Probleme

Problem mit # 1 ist die Leistung. Regex sind ziemlich langsame Vorgänge und das Starten von Regex in einer Schleife aller Posts kann die Seite konsistent verlangsamen. Darüber hinaus ist es in Themes eine ziemlich häufige Aufgabe, nur Post-Ausschnitte in Archiven anzuzeigen und vollständigen Inhalt mit Shortcodes nur in einzelnen Ansichten anzuzeigen. In diesem Fall startet Ihr Plugin beim Anzeigen eines Archivs in einer Schleife einen regulären Ausdruck, um einen Stil hinzuzufügen, der niemals verwendet wird: eine unnötige doppelte Auswirkung auf die Leistung: Verlangsamung der Seitengenerierung + zusätzliche unnötige HTTP-Anforderung

Problem mit # 2 ist wieder Leistung. Das Hinzufügen eines Stils zu allen Seiten bedeutet, dass eine zusätzliche HTTP-Anforderung für alle Seiten hinzugefügt wird, auch wenn diese nicht benötigt wird. Auch wenn die Generierungszeit der serverseitigen Seiten nicht beeinflusst wird, gilt dies für die gesamte Renderzeit der Seite und für alle Websiteseiten.

Was sollte ein Plugin-Entwickler also tun?

Ich denke, das Beste ist, eine Optionsseite zum Plugin hinzuzufügen, auf der Benutzer auswählen können, ob der Shortcode nur in der Einzelansicht oder sogar in Archiven behandelt werden soll. In beiden Fällen ist es besser, eine andere Option bereitzustellen, um auszuwählen, für welche Beitragstypen die Kurzwahl aktiviert werden soll.

Auf diese Weise kann ein Hook gesetzt werden "template_redirect", um zu überprüfen, ob die aktuelle Abfrage den Anforderungen entspricht, und in diesem Fall den Stil hinzuzufügen.

Wenn der Benutzer den Shortcode nur in einzelnen Post-Ansichten verwendet, empfiehlt es sich, zu prüfen, ob der Post einen Shortcode enthält oder nicht: Wenn nur eine Regex erforderlich ist, sollte die Seite nicht so stark verlangsamt werden.

Wenn der Benutzer die Verwendung von Shortcode auch in Archiven auswählt , würde ich vermeiden, bei hoher Anzahl von Posts Regex für alle Posts auszuführen und den Stil nur in eine Warteschlange einreihen, wenn die Anforderungen an die Abfragetauglichkeit erfüllt sind.

Was in dieser Hinsicht als "hoch" zu betrachten ist, sollte darin bestehen, einige Leistungstests durchzuführen oder alternativ eine weitere Option hinzuzufügen und den Benutzern eine Auswahl zu geben.

gmazzap
quelle
2
Es ist erwähnenswert, dass <style>Tags im Dokumenttext jetzt gemäß der W3C-Spezifikation gültig sind. w3.org/TR/html52/document-metadata.html#the-style-element
Isaac Lubow
5

Für mein Plugin habe ich festgestellt, dass Benutzer manchmal einen Theme Builder haben, dessen Shortcode in Post-Metadaten gespeichert ist . Hier ist, was ich verwende, um festzustellen, ob mein Plugin-Shortcode in aktuellen Post- oder Post-Metadaten vorhanden ist :

function abcd_load_my_shorcode_resources() {
       global $post, $wpdb;

       // determine whether this page contains "my_shortcode" shortcode
       $shortcode_found = false;
       if ( has_shortcode($post->post_content, 'my_shortcode') ) {
          $shortcode_found = true;
       } else if ( isset($post->ID) ) {
          $result = $wpdb->get_var( $wpdb->prepare(
            "SELECT count(*) FROM $wpdb->postmeta " .
            "WHERE post_id = %d and meta_value LIKE '%%my_shortcode%%'", $post->ID ) );
          $shortcode_found = ! empty( $result );
       }

       if ( $shortcode_found ) {
          wp_enqueue_script(...);
          wp_enqueue_style(...);
       }
}
add_action( 'wp_enqueue_scripts', 'abcd_load_my_shorcode_resources' );
zdenekca
quelle
2

Ich mache so:

class My_Shortcode {

    function __construct() {
        do_action('my_start_shortcode'); // call
....

und catch hook in anderen Funktionen (oder anderen Plugins):

function wpse_3232_load_script(){
    wp_enqueue_script('js-myjs');
}
add_action('my_start_shortcode','wpse_3232_load_script',10);
Wladimir Druzhaev
quelle
1

Ich habe für mein eigenes Plugin herausgefunden, ob der Shortcode im Text-Widget vorhanden ist.

function check_shortcode($text) {

  $pattern = get_shortcode_regex();

   if (   preg_match_all( '/'. $pattern .'/s', $text, $matches )
        && array_key_exists( 2, $matches )
        && in_array( 'myshortcode', $matches[2] ) )
    {
        // myshortcode is being used

        // enque my css and js
        /****** Enqueu RFNB  ******/
        wp_enqueue_style('css-mycss');
        wp_enqueue_script('js-myjs');

        // OPTIONAL ALLOW SHORTCODE TO WORK IN TEXT WIDGET
        add_filter( 'widget_text', 'shortcode_unautop');
        add_filter( 'widget_text', 'do_shortcode'); 

    }

  return $text;

}
add_filter('widget_text', 'check_shortcode');
Gino
quelle
1

WordPress hat eine eingebaute Funktion, um etwas basierend auf einem bestimmten Shortcode-Präsentationsstatus zu tun. Der Funktionsname ist has_shortcode(). Mit dem folgenden Code können Sie Ihren Stil und Ihre Skripte einreihen.

Hier habe ich das benutzt is_a( $post, 'WP_Post' ), um zu überprüfen, ob das $postObjekt zur WP_PostKlasse gehört, und ich habe $post->post_contentden Inhalt des Beitrags überprüft.

if ( is_a( $post, 'WP_Post' ) && has_shortcode( $post->post_content, 'shortcode_tag') ) {
    wp_enqueue_style( 'handle', get_template_directory_uri() . '/your_file_filename.css' );
}
Arif Rahman
quelle
0

Ich habe eine Kombination aus dem Beispielcode der Wordpress-Seite für has_shortcode () und der Antwort, die zndencka gab, erstellt. Mir ist aufgefallen, dass die Funktion has_shortcode in Wordpress 3.6 hinzugefügt wurde. Deshalb überprüfe ich zuerst, ob die Funktion vorhanden ist. Vielleicht ist diese Überprüfung ein bisschen veraltet, da laut wordpress nicht mehr viele Benutzer unter WordPress 3.6 ihre eigenen Statistiken haben.

// This makes sure the styling is already enqueued in the header, so before the shortcode loads in the page/post
function enqueue_shortcode_header_script() {
    global $post;
    if ( function_exists( 'has_shortcode' ) ){  // is added in wordpress 3.6
        // Source: https://codex.wordpress.org/Function_Reference/has_shortcode
        if( is_a( $post, 'WP_Post' ) && has_shortcode( $post->post_content, 'my_shortcode') ) {
            wp_enqueue_style( 'shortcode-css' );
        }
    }
    else if ( isset($post->ID) ) { // Small percentage wordpress users are below 3.6 https://wordpress.org/about/stats/
        global $wpdb;
        $result = $wpdb->get_var(
          $wpdb->prepare(
              "SELECT count(*) FROM $wpdb->postmeta " .
              "WHERE post_id = %d and meta_value LIKE '%%my_shortcode%%'",
               $post->ID )
        );
        if (!empty( $result )) { wp_enqueue_style( 'shortcode-css' ); }
    }
}
add_action( 'wp_enqueue_scripts', 'enqueue_shortcode_header_script');
Vasco
quelle
0

Wir können CSS- und JS-Dateien in der Tat unter bestimmten Bedingungen per Shortcode laden, ohne übermäßig aufwendige Funktionen zu verwenden:

Nehmen wir zunächst an, wir haben alle unsere CSS / JS-Dateien zuvor registriert (möglicherweise beim wp_enqueue_scriptsAusführen).

function prep_css_and_js() {
     wp_register_style('my-css', $_css_url);
     wp_register_script('my-js', $_js_url);
}
add_action( 'wp_enqueue_scripts', 'prep_css_and_js', 5 );

Als nächstes wollen wir unsere Shortcode-Funktion untersuchen:

function my_shortcode_func( $atts, $content = null ) {
  if( ! wp_style_is( "my-css", $list = 'enqueued' ) ) { wp_enqueue_style('my-css'); }
  if( ! wp_script_is( "my-js", $list = 'enqueued' ) ) { wp_enqueue_script('my-js'); }
  ...
}

Einfach. Getan. Ergo: css / js-Dateien können "bedingt" geladen werden (nur wenn [shortcode] ausgeführt wird).

Betrachten wir die folgende Ideologie:

  • Wir möchten bestimmte CSS / JS-Dateien laden (aber nur, wenn der Shortcode ausgelöst wird)
  • Vielleicht möchten wir nicht, dass diese Dateien auf jeder Seite geladen werden, oder überhaupt, wenn der Shortcode nicht auf einer Seite / einem Beitrag verwendet wird. (Leicht)
  • Wir können dies erreichen, indem wir sicherstellen, dass WP ALLE CSS / JS-Dateien registriert, bevor der Shortcode aufgerufen wird und bevor die Enqueue ausgeführt wird.
  • IE: Vielleicht prep_css_and_js()lade ich während meiner Funktion ALLE .css / .js-Dateien, die sich in bestimmten Ordnern befinden ...

Jetzt, da WP sie als registrierte Skripte betrachtet, können wir sie in der Tat bedingt aufrufen, basierend auf einer Reihe von Situationen, einschließlich, aber nicht beschränkt auf my_shortcode_func()

Vorteile: (kein MySQL, keine erweiterten Funktionen und keine Filter erforderlich)

  • Dies ist "WP Orthodix", elegant, schnelles Laden, einfach und unkompliziert
  • Ermöglicht Compilern / Minimierern, solche Skripte zu erkennen
  • benutzt die WP-Funktionen (wp_register_style / wp_register_script)
  • Kompatibel mit mehr Themes / Plugins, die diese Skripte aus verschiedenen Gründen abmelden möchten.
  • wird nicht mehrmals ausgelöst
  • Es ist sehr wenig Verarbeitung oder Code beteiligt

Verweise:

Christian Žagarskas
quelle