Filtre ve eylem işlevlerine parametre geçirme


52

İşlev için kendi parametreleri aktarmak için bir yol var mı add_filterya add_action. Örneğin, aşağıdaki koda bir göz atın:

function my_content($content, $my_param)
{
do something...
using $my_param here ...
return $content;
}
add_filter('the_content', 'my_content', 10, 1);

Kendi parametremi geçebilir miyim? gibi bir şey:

add_filter('the_content', 'my_content($my_param)', 10, 1)

veya

add_filter('the_content', 'my_content', 10, 1, $my_param)

Yanıtlar:


78

Varsayılan olarak bu mümkün değildir. OOP yöntemiyle yaparsanız, geçici çözümler vardır.
Daha sonra kullanmak istediğiniz değerleri depolamak için bir sınıf oluşturabilirsiniz.

Örnek:

/**
 * Stores a value and calls any existing function with this value.
 */
class WPSE_Filter_Storage
{
    /**
     * Filled by __construct(). Used by __call().
     *
     * @type mixed Any type you need.
     */
    private $values;

    /**
     * Stores the values for later use.
     *
     * @param  mixed $values
     */
    public function __construct( $values )
    {
        $this->values = $values;
    }

    /**
     * Catches all function calls except __construct().
     *
     * Be aware: Even if the function is called with just one string as an
     * argument it will be sent as an array.
     *
     * @param  string $callback Function name
     * @param  array  $arguments
     * @return mixed
     * @throws InvalidArgumentException
     */
    public function __call( $callback, $arguments )
    {
        if ( is_callable( $callback ) )
            return call_user_func( $callback, $arguments, $this->values );

        // Wrong function called.
        throw new InvalidArgumentException(
            sprintf( 'File: %1$s<br>Line %2$d<br>Not callable: %3$s',
                __FILE__, __LINE__, print_r( $callback, TRUE )
            )
        );
    }
}

Artık sınıfı istediğiniz herhangi bir işlevle çağırabilirsiniz - işlev bir yerde varsa, depolanmış parametrelerinizle çağrılır.

Bir demo işlevi oluşturalım…

/**
 * Filter function.
 * @param  array $content
 * @param  array $numbers
 * @return string
 */
function wpse_45901_add_numbers( $args, $numbers )
{
    $content = $args[0];
    return $content . '<p>' . implode( ', ', $numbers ) . '</p>';
}

… Ve bir kez kullanın…

add_filter(
    'the_content',
    array (
        new WPSE_Filter_Storage( array ( 1, 3, 5 ) ),
        'wpse_45901_add_numbers'
    )
);

… ve yeniden …

add_filter(
    'the_content',
    array (
        new WPSE_Filter_Storage( array ( 2, 4, 6 ) ),
        'wpse_45901_add_numbers'
    )
);

Çıktı:

görüntü tanımını buraya girin

Anahtar yeniden kullanılabilirliktir : Sınıfı yeniden kullanabilirsiniz (ve örneklerimizde de fonksiyon).

PHP 5.3+

PHP sürüm 5.3 veya daha yeni bir kapak kullanıyorsanız , bunu çok daha kolay hale getirir:

$param1 = '<p>This works!</p>';
$param2 = 'This works too!';

add_action( 'wp_footer', function() use ( $param1 ) {
        echo $param1;
    }, 11 
);
add_filter( 'the_content', function( $content ) use ( $param2 ) {
        return t5_param_test( $content, $param2 );
    }, 12
);

/**
 * Add a string to post content
 *
 * @param  string $content
 * @param  string $string This is $param2 in our example.
 * @return string
 */
function t5_param_test( $content, $string )
{
    return "$content <p><b>$string</b></p>";
}

Dezavantajı, kapanışlar için birim testleri yazamamanızdır. 


17
WP çekirdeğinde yerleşik bir çözüme sahip olması gereken bir soruna yalnızca kaliteli bir cevap almak için oy kullanmakla kalmaz, cevabınızı PHP 5.3+ kapatma örneğiyle güncellemek için beş ay sonra geri döndüğünüzden birini alırsınız.
Adam

1
Mükemmel cevap! Ancak bu adsız işlev tarafından oluşturulan bu filtreyi daha sonra kaldırmak için nasıl yapabilirim?
Vinicius Tavares,

2
@ViniciusTavares Yapamazsın. Kullanmadan önce düşün. :)
fuxia

5
Anonim işlevi bir değişkene (örneğin $func = function() use ( $param1 ) { $param1; };ve add_action( $func, 11);) remove_action( $func, 11 );
kaydederseniz

1
Ancak, dünyaya bıraktığınız eklentiler veya temalarda adsız işlevler kullanmanız önerilmez (bunları kendi projelerinizde kullanabilirsiniz). Bununla ilgili sorun şu ki, onları çözemezsiniz. Gitmeye karar verdiğiniz yaklaşımın daha sonra çözülemez olması gerekir.
Mueyiwa Moses Ikomi,

1

Bir işlevi döndüren gerekli argümanlarla bir işlev oluşturun. Bu işlevi (kapatma olarak da bilinen adsız işlev) wp kancasına geçirin.

Wordpress arka ucunda bir yönetici bildirimi için burada gösterilir.

public function admin_notice_func( $message = '')
{
$class = 'error';
    $output = sprintf('<div class="%s"><p>%s</p></div>',$class, $message);
    $func = function() use($output) { print $output; };
    return $func;
}
$func = admin_notice_func('Message');
add_action('admin_notices', $func);

1

PHP Anonim İşlevlerini Kullan :

$my_param = 'my theme name';
add_filter('the_content', function ($content) use ($my_param) {
    //$my_param is available for you now
    if (is_page()) {
        $content = $my_param . ':<br>' . $content;
    }
    return $content;
}, 10, 1);

1

Zamanın geçtiğini biliyorum, ancak add_filter'daki 4. parametrenin değiştirilecek içerik de dahil olmak üzere geçirilen parametrelerin sayısı olduğunu bulana dek kendi parametremi geçirirken bazı sorunlar yaşadım . Öyleyse 1 ek parametre geçerseniz, durum 2’de 2 değil 1 olmalıdır

add_filter('the_content', 'my_content', 10, 2, $my_param)

ve kullanma

function my_content($content, $my_param) {...}

1

WP filtreleri ve eylemlere argümanlar ne olursa olsun sayısını geçme, doğru gerçekten kısa ve en verimli şekilde @Wesam Alalem dan buraya kapatılması kullanır.

Sadece asıl doer yöntemini anonim kapatmadan ayırarak daha da net ve çok daha esnek hale getirebileceğinizi ekleyeceğim. Bunun için kapatma yöntemini aşağıdaki gibi çağırmanız yeterlidir (@Wesam Alalem cevabından değiştirilmiş örnek).

Bu şekilde asıl dolandırıcıyı çağırmak için kullandığınız kapatmanın dışında, dilediğiniz kadar karmaşık veya uzun bir mantık yazabilirsiniz.

// ... inside some class

private function myMethod() {
    $my_param = 'my theme name';
    add_filter('the_content', function ($content) use ($my_param) {
        // This is the anonymous closure that allows to pass 
        // whatever number of parameters you want via 'use' keyword.
        // This is just oneliner.
        // $my_param is available for you now via 'use' keyword above
        return $this->doThings($content, $my_param);
    }, 10, 2);
}

private function doThings($content, $my_param) {
    // Call here some other method to do some more things
    // however complicated you want.
    $morethings = '';
    if ($content = 'some more things') {
        $morethings = (new MoreClass())->get();
    }
    return $my_param . ':<br>' . $content . $morethings;
}

0

kendi kancanızı yaratırsanız, işte örnek.

// lets say we have three parameters  [ https://codex.wordpress.org/Function_Reference/add_filter ]
add_filter( 'filter_name', 'my_func', 10, 3 );
my_func( $first, $second, $third ) {
  // code
}

sonra kancayı takın:

// [ https://codex.wordpress.org/Function_Reference/apply_filters ]
echo apply_filters( 'filter_name', $first, $second, $third );

Bu, kayıttan geri aramaya bilgi aktarmaz. Geri aramanın kaç parametre kabul edebileceğini yazıyor.
fuxia

@fuxia, bilginin iletilmesi için basit bir değişiklik önerebilir misiniz? İnsan sadece param değerleri üzerine yapışır 3mıydı?
SherylHohman

0

Her zaman global kullanabilirsiniz, değil mi?

  global $my_param;

Bu soruya bir cevap vermiyor. Yeterli üne sahip olduğunuzda , herhangi bir gönderi hakkında yorum yapabileceksiniz ; bunun yerine, askerden açıklama gerektirmeyen cevaplar sağlayın . - Şu kaynaktan
cjbj

@cjbj Aslında öyle. Soru parametreler, add_filter veya add_action içindeki "fonksiyon" a iletilebilir. Kullanıcının, varsayım olsa bile add_filter veya add_action işlevinde iletmek isteyip istemediği belli değildi. :)
samjco

0

Bir işlevi doğrudan çağırmanıza rağmen, bunu daha zarif bir şekilde yapın: adsız bir işlevi geri arama olarak geçirin.

Örneğin:

Yazılarımın başlığını, içeriğini ve alıntılarını çevirmek için tek bir işleve sahibim. Bu yüzden, bu ana fonksiyona kimin aradığını söyleyen bazı argümanlara geçmem gerekiyor.

add_filter( 'the_title', function( $text ) { 
    return translate_text( $text, 'title', 'pl' );
});

add_filter( 'the_content', function( $text ) { 
    return translate_text( $text, 'content', 'pl' );
});

add_filter( 'the_excerpt', function( $text ) { 
    return translate_text( $text, 'excerpt', 'pl' );
});

Dolayısıyla, ana işlev translate_textistediğim kadar parametre alır, çünkü geri çağırmak için adsız bir işlevi geçtim.


-1

Aynı şeyi umuyordum ama mümkün olmadığından basit bir çözüm gibi farklı bir işlevi çağırmak sanırım add_filter('the_content', 'my_content_filter', 10, 1);

o zaman my_content_filter () istediği herhangi bir argümanı geçerek sadece my_content () 'i çağırabilir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.