web-dev-qa-db-fra.com

Utiliser la variable d'un filtre dans un autre filtre

J'ai un filtre pour le Shortcode de la galerie où je récupère les identifiants des images utilisées dans une publication et les identifiant je récupère leurs métadonnées. Maintenant, j'ai besoin d'un moyen d'utiliser la variable $copyright dans un filtre pour récupérer post_content afin de pouvoir faire écho au contenu de cette variable.

Existe-t-il un moyen de réutiliser une variable dans un filtre différent ou peut-être existe-t-il un meilleur moyen d'accomplir ce que j'essaie d'accomplir?

function wpse_get_full_size_gallery_images( $gallery, $post, $galleries ) { 
    $ids        = explode( ',', $galleries['include'] );
    $copyright  = array();

    foreach( $ids as $id )
        $copyright[] = get_post_meta( $id, 'wiki_copyright', true );

    return $gallery;
}
add_filter( 'shortcode_atts_gallery', 'wpse_get_full_size_gallery_images', 10, 3 );

function my_the_content_filter( $content ) {
    //pass here the copyright array and append it at the end
    $content .= $copyright;

    return $content;
}
add_filter( 'the_content', 'my_the_content_filter', 20 );
3
Ivan Topić

C'est probablement un bon cas pour une variable globale. Assurez-vous simplement qu'il est défini sur un tableau avant de l'ajouter et également quand il faut essayer de générer le contenu. Convertissez le tableau en chaîne avant de l'ajouter au contenu.

Assurez-vous également que les métadonnées existent avant de les ajouter au tableau. Ainsi, vous n'ajouterez pas de valeurs de copyright vides.

VERSION GLOBALE

function wpse_get_full_size_gallery_images($gallery, $post, $galleries) {

    // reference the global variable
    global $copyright;

    // make sure it's set
    if( ! isset($copyright)) $copyright = array();

    // grab the IDS
    $ids = explode(',', $galleries[ 'include' ]);

    foreach($ids as $id) {
       // get the possible meta
       $meta = get_post_meta($id, 'wiki_copyright', true);

       // add them to the copyright array   
       // make sure to only add if it exists
       if( !empty($meta)) $copyright[] = $meta;
    }

    return $gallery;
}

add_filter('shortcode_atts_gallery', 'wpse_get_full_size_gallery_images', 10, 3);

function my_the_content_filter($content) {

    // reference the global variable
    global $copyright;

    // add copyright array converted to string if we have content
    if( ! empty($copyright)) $content .= implode(',', $copyright);

    return $content;
}

add_filter('the_content', 'my_the_content_filter', 20);

VERSION STATIQUE

Si vous n'aimez pas utiliser les globales, pour une raison quelconque , alors considérez un statique comme alternative variable scope en PHP.

Une autre caractéristique importante de la portée des variables est la variable statique. Une variable statique n'existe que dans l'étendue d'une fonction locale, mais elle ne perd pas sa valeur lorsque l'exécution du programme quitte cette étendue.

Étant donné que la variable persistante est liée à une portée de fonction unique, nous devons créer la fonction en dehors de toute boucle, puis la réutiliser pour ajouter des valeurs en plus de la récupération de ces valeurs.

Si vous passez une nouvelle valeur; ajoutez-le . Si vous ne passez pas de valeur; récupère toutes les valeurs .

if( ! function_exists('copyrights')) {
    function copyrights($value = '') {

        // only this function has access to $_copyrights
        static $_copyrights;

        // expressions can't be assigned as defaults
        // but we still want to initialize the value
        if( ! isset($_copyrights)) {
            $_copyrights = array();
        }

        // if we're passing new values then add them
        if( ! empty($value)) {
            $_copyrights[] = $value;

            return true; // success
        }
        else {
            // otherwise return uniques
            $unique_list = array_unique($_copyrights);

            // convert to string before they leave
            return implode(", ", $unique_list);
        }
    }
}

add_filter('shortcode_atts_gallery', function($gallery, $post, $galleries) {
    $ids = explode(',', $galleries[ 'include' ]);
    foreach($ids as $id) 
        if( ! empty($meta = get_post_meta($id, 'wiki_copyright', true)))
            copyrights($meta);

    return $gallery;
}, 10, 3);

add_filter('the_content', function($content) {
    return $content . copyrights();
}, 20);

ESSAI

copyrights ( 123 );
copyrights ( 223 );
copyrights ( 333 );
copyrights ( 123 );
copyrights ( 111 );
copyrights ( 111 );
copyrights ( 111 );

echo ( copyrights() ); // 123, 223, 333, 111

VERSION DE SINGLETON

En fait, je n'utilise jamais de globales car un motif singleton est ma méthode préférée.

L'idée est que vous placez toutes vos méthodes sur une instance d'une classe mais n'y accédez que par une méthode statique. Ce faisant, la classe s'assure qu'il n'y a jamais qu'une seule instance créée.

if( ! class_exists('Copyrights')) {
    class Copyrights {

        private        $copyrights;
        private static $instance;

        // PRIVATE CONSTRUCTOR

        private function __construct() {

            // initialize the array
            $this->copyrights = array();
        }

        // STATIC SINGLETON

        public static function getInstance() {
            if(is_null(self::$instance)) {
                self::$instance = new self();
            }

            return self::$instance;
        }

        // PUBLIC METHODS

        public function toString() {
            $unique_list = array_unique($this->copyrights);

            return implode(", ", $unique_list);
        }

        public function add($value = '') {
            if( ! empty($value)) {
                $this->copyrights[] = $value;
            }
        }
    }
}

add_filter('shortcode_atts_gallery', function($gallery, $post, $galleries) {

    $ids = explode(',', $galleries[ 'include' ]);

    foreach($ids as $id)
        if( ! empty($meta = get_post_meta($id, 'wiki_copyright', true))) 
            Copyrights::getInstance()->add($meta);

    return $gallery;
}, 10, 3);

add_filter('the_content', function($content) {
    return $content . Copyrights::getInstance()->toString();
}, 20);

ESSAI

Copyrights::getInstance()->add ( 123 );
Copyrights::getInstance()->add ( 223 );
Copyrights::getInstance()->add ( 333 );
Copyrights::getInstance()->add ( 123 );
Copyrights::getInstance()->add ( 111 );
Copyrights::getInstance()->add ( 111 );
Copyrights::getInstance()->add ( 111 );

echo Copyrights::getInstance()->toString(); // 123, 223, 333, 111

SINGLETON PER POST VERSION

Peut-être que l’aspect le plus important unique qui a été négligé dans le débat sur global contre the sky is falling est la solution ci-dessus ( et les alternatives proposées ) un seul post. Si vous vouliez ajouter vos droits d'auteur dans une boucle, vous seriez foutu parce que tous les posts seraient ajoutés à un seul tableau.

Avec la classe singleton, ajouter un singleton par ID est un gâteau et constitue sans doute la meilleure option possible .

if( ! class_exists('Copyrights')) {
    class Copyrights {

        private static $instance;
        private        $copyrights;
        public         $post_id;

        // PRIVATE CONSTRUCTOR

        private function __construct($post_id) {

            // save the id
            $this->post_id = $post_id;

            // initialize the array
            $this->copyrights = array();
        }

        // SINGLETON

        public static function getInstance($post_id = 'NO ID') {
            if(is_null(self::$instance)) self::$instance = array();
            if(is_null(self::$instance[ $post_id ])) {
                self::$instance[ $post_id ] = new self($post_id);
            }

            return self::$instance[ $post_id ];
        }

        // PUBLIC METHODS

        public function toString() {
            $unique_list = array_unique($this->copyrights);

            return implode(", ", $unique_list);
        }

        public function add($value = '') {
            if( ! empty($value)) {
                $this->copyrights[] = $value;
            }
        }
    }
}

add_filter('shortcode_atts_gallery', function($gallery, $post, $galleries) {

    $ids = explode(',', $galleries[ 'include' ]);

    foreach($ids as $id)
        if( ! empty($meta = get_post_meta($id, 'wiki_copyright', true)))
            Copyrights::getInstance($post->ID)->add($meta);

    return $gallery;
}, 10, 3);

add_filter('the_content', function($content) {
    global $post;
    return $content . Copyrights::getInstance($post->ID)->toString();
}, 20);

ESSAI

Comme vous pouvez le constater, l'utilisation de l'option pour utiliser ID comme clé permet de garder la flexibilité.

Copyrights::getInstance( 1 )->add ( 123 );
Copyrights::getInstance( 1 )->add ( 223 );
Copyrights::getInstance( 2 )->add ( 333 );
Copyrights::getInstance( 2 )->add ( 123 );
Copyrights::getInstance( 2 )->add ( 111 );
Copyrights::getInstance( 2 )->add ( 111 );
Copyrights::getInstance( 2 )->add ( 111 );
Copyrights::getInstance()->add ( 111 );
Copyrights::getInstance()->add ( 444 );
Copyrights::getInstance()->add ( 555 );
Copyrights::getInstance()->add ( 888 );

echo Copyrights::getInstance( 1 )->toString(); // 123, 223
echo Copyrights::getInstance( 2 )->toString(); // 333, 123, 111
echo Copyrights::getInstance()->toString(); // 111, 444, 555, 888

Au moment où quelqu'un pense que c'est une bonne idée de stocker une valeur temporaire dans la base de données car ils ne comprennent pas PHP, puis c'est un bon moment pour repenser le problème.


UPDATE

J'ai résolu la question à l'aide d'une variable globale mais en repensant le problème, vous pouvez Éliminez beaucoup de complexités en utilisant uniquement le crochet de filtre de contenu , ce qui permet de localiser le problème.

Dans ce cas, lorsque the_content est exécuté, nous vérifions toutes les galeries et ne produisons que les données pertinentes .

Pas besoin de globaux, de statiques, de singletons, d'options ou de fonctions supplémentaires.

Mieux encore, cela fonctionnera en boucle sans complication.

add_filter('the_content', 'add_copyright_to_content');

function add_copyright_to_content($content) {

    //  pull all galleries from the post
    $galleries = get_post_galleries(get_post(), false);

    //  no gallery? then let's get out of here
    if(empty($galleries)) return $content;

    $all = '';

    //  gather all ids
    foreach($galleries as $gallery) $all .= $gallery[ 'ids' ] . ',';

    //  convert them to an array with unique ids
    $all = array_unique(array_filter(explode(',', $all)));

    //  replace id for copyright info on the image meta
    foreach($all as $key => $id) $all [ $key ] = get_post_meta($id, 'wiki_copyright', true);

    //  return non-empty values to the end of the content
    return $content . implode(', ', array_filter($all));
}
5
jgraup

... Peut-être y a-t-il une meilleure solution pour ce que j'essaie d'accomplir?

Il y a toujours des options supplémentaires à prendre en compte. Globaliser une variable n'en est certainement pas une et vous devriez éviter de le faire. La globalisation est un moyen facile de résoudre n'importe quel problème, mais croyez-moi, vous passerez des jours à déboguer un problème qui ne vous donnera aucune erreur de débogage lorsque quelque chose brise votre problème global.

WordPress a déjà fait un énorme bazar avec les globals. Il suffit de parcourir les questions et réponses sur ce site et de vérifier combien utilisent les variables globales $wp_query, $posts et $post en tant que variables locales.

Personnellement, j'utilise $copyright comme variable pour conserver les informations de date. Si nous globalisons $copyright avec une chaîne d'id, comme dans votre cas, ma variable va casser le global ou le global va casser ma variable. Le pire est que je n’aurais aucune erreur de débogage et je ne saurais pas où mes valeurs ont changé. Donc, ne jamais globaliser les variables, à mon humble avis, c’est vraiment une mauvaise pratique car il existe de nombreuses autres options

Une option rapide qui me vient à l’esprit est le stockage de vos données avec l’API Options. C'est facile et ne nécessite pas d'énormes frais généraux car les options sont mises en cache et sont sauvegardées.

Essayons ce qui suit: ( NOTE: Tout le code n'a pas été testé, donc assurez-vous de le tester d'abord sur l'installation locale. Le code nécessite également PHP 5.4 + )

add_filter( 'shortcode_atts_gallery', function ( $gallery, $post, $galleries ) 
{ 
    // Get all the ids
    $ids = $galleries['include'];
    // Instead of overloading the shortcode, lets just save the id's for later use
    if ( !$ids ) // Always make sure we have values
        return $gallery;

    // Add our ids in an option
    $option = get_option( 'custom_copyright_ids' );
    if (    false !== $option // Make sure that the option does not yet exist
         || $option !== $ids // We only want the update if $id's change
    ) {
        // Lets update or add our option
        update_option( 'custom_copyright_ids', $ids );
    }

    return $gallery;
}, 10, 3 );

Nous pouvons maintenant créer une fonction "globale" que nous pouvons transporter et utiliser ( en toute sécurité ) où vouloir l'utiliser. ( La fonction ci-dessous est statique, vous pouvez la rendre dynamique )

function get_global_copyright_ids()
{
    $output = '';

    // Get our ids
    $ids = get_option( 'custom_copyright_ids' );

    // Make sure we have a value for $option, either return an empty string
    if ( false === $ids )
        return $output;

    // We have ids, lets continue
    // We expect $ids to be an array, so lets turn the string into an array
    $ids = explode( ',', trim( $ids ) );

    foreach ( $ids as $id ) {
        // Get our post meta
        $meta = get_post_meta( $id, 'wiki_copyright', true );
        if ( !$meta )
            continue;
        // We have meta, add it to our $output string. Add any markup here
        $output .= $meta
    } // endforeach $ids

    // Return our string of post meta
    return $output;
}

Nous pouvons maintenant utiliser get_global_copyright_ids() partout où nous voulons

add_filter( 'the_content', function ( $content )
{
    // Get our content to add from our "global" function
    $extra = '';
    if ( function_exists( 'get_global_copyright_ids' ) ) {
        $extra = get_global_copyright_ids();
    }

    if ( !$extra )
        return $content;

    // Append $extra to $content
    return $content . $extra;
}):

Et là vous avez un système bien meilleur et plus sûr qui est vraiment facile à déboguer et le meilleur de tous VOUS AVEZ GARDÉ LA PORTÉE GLOBALE PROPRE !!!

3
Pieter Goosen