Kenar çubuğuna programsal olarak widget ekleyin


62

Programlı olarak sahip olduğum iki kenar çubuğuma widget eklemek istiyorum. Resmi bir yol bulamadım mı?

Veritabanına bakmaya başladım. Bunun, kenar çubuklarına widget koyan 'sidebars_widgets' seçeneğinin olduğunu gördüm. Seçeneklere bakıldığında, widget adlarının sonuna benzer bir numarası var: widget_name-6. Bu numara nereden geliyor?

Bunun nasıl düzeltileceği hakkında bir fikrin var mı?


6
Kendi sorunuza cevap vermek için cevabınızı oraya eklemelisiniz :)
helenhousandi

Kenar çubuğu widget'ları hakkında ayrıntılı bilgi için bu makaleye göz atın : justintadlock.com/archives/2010/11/08/sidebars-in-wordpress .
Joshua,

Bir widget eklendiğinde yapılan ajax çağrısının eylem parametresini izleyin ve ardından bu eylem ajax kancası ile ilgili kodu bulun ve çekirdekte nasıl yapıldığını görün. Basit! ;)
Ashfame

5
Lütfen çözümünüzü bir cevap olarak tekrar gönderin ve sorunun cevabını "" "olarak kabul edin.
EAMann

Yanıtlar:


91

Bu cevabı başlattığımda sadece küçük bir not olmalı. Ben başarısız oldum. Üzgünüm! Benimle kal, derinlerde saklı bir şeref var ...

WordPress widget'ları nasıl depolanır?

Widget listesi adlı bir seçenek içinde saklanır 'sidebars_widgets'. A var_export(), aşağıdaki gibi bir şey verebilir:

array (
  'wp_inactive_widgets' => 
  array (
  ),
  'top-widget' => 
  array (
  ),
  'bottom-widget' => 
  array (
  ),
  'array_version' => 3,
)

Yoksay 'wp_inactive_widgets've 'array_version'. Bunlarla ilgilenmek zorunda değiliz.
Diğer tuşlar kayıtlı kenar çubukları için tanımlayıcıdır. Bu durumda kenar çubukları bu koda kaydedilmiş olabilir:

// Register two sidebars.
$sidebars = array ( 'a' => 'top-widget', 'b' => 'bottom-widget' );
foreach ( $sidebars as $sidebar )
{
    register_sidebar(
        array (
            'name'          => $sidebar,
            'id'            => $sidebar,
            'before_widget' => '',
            'after_widget'  => ''
        )
    );
}

Varsayılan olarak kenar çubukları kayıttan sonra boştur. Tabii ki.

Kayıtlı her widget sınıfı için, gerekli tüm seçenekleri içeren ayrı bir seçenek oluşturulur. Bu seçenek dizge tarafından ön eklenmiştir widget_. Tüm aktif RSS widget'larının seçeneklerini görmek için araştırmamız gereken…

get_option( 'widget_rss' );

Mümkün çıktı:

array (
  2 => 
  array (
    'title' => 'WordPress Stack Exchange',
    'url' => 'http://wordpress.stackexchange.com/feeds',
    'link' => 'http://wordpress.stackexchange.com/questions',
    'items' => 5,
    'show_summary' => 1,
    'show_author' => 0,
    'show_date' => 0,
  ),
)

2 numaraya dikkat edin . Birden fazla örnek için olan argümanların tümü, sayılara göre sıralanmış bir seçenekte saklanır.

Hangi widget sınıflarının zaten WordPress tarafından bilindiğini görmek için şuna gidin wp-admin/options.phpve aşağıdakine benzer bir şey görünceye kadar aşağı kaydırın:

serileştirilmiş widget seçeneklerinin ekran görüntüsü

Evet, serileştirilmiş veri. Hayır, burada okuyamazsın. Endişelenme, zorunda değilsin.

Bir demo widget

İç işleri daha iyi göstermek için çok basit bir demo widget'ı yazdım:

/**
 * Super simple widget.
 */
class T5_Demo_Widget extends WP_Widget
{
    public function __construct()
    {                      // id_base        ,  visible name
        parent::__construct( 't5_demo_widget', 'T5 Demo Widget' );
    }

    public function widget( $args, $instance )
    {
        echo $args['before_widget'], wpautop( $instance['text'] ), $args['after_widget'];
    }

    public function form( $instance )
    {
        $text = isset ( $instance['text'] )
            ? esc_textarea( $instance['text'] ) : '';
        printf(
            '<textarea class="widefat" rows="7" cols="20" id="%1$s" name="%2$s">%3$s</textarea>',
            $this->get_field_id( 'text' ),
            $this->get_field_name( 'text' ),
            $text
        );
    }
}

Yapıcısı Not: 't5_demo_widget'olup $id_base, bu widget için tanımlayıcı. Ekran görüntüsünde de görebileceğiniz gibi argümanlar seçeneklerinde saklanır widget_t5_demo_widget. Tüm özel aletleriniz bu şekilde ele alınacaktır. Adı tahmin etmek zorunda değilsin. Beri sen Widget'larınızı yazdım (muhtemelen) Eğer sınıf dan tüm argümanları biliyorum $instanceparametreler.

Tema temelleri

Önce bazı kenar çubuklarını ve özel widget'ı kaydetmeniz gerekir. Bunun için uygun eylem hatırlamak kolaydır: 'widgets_init'. Her şeyi bir kaba yerleştirin - bir sınıf veya işlev. Basit olması için adlı bir işlev kullanacağım t5_default_widget_demo().

Aşağıdaki kodun tümü içine gider functions.php. Sınıf T5_Demo_Widgetönceden yüklenmiş olmalı. Sadece aynı dosyaya koydum…

add_action( 'widgets_init', 't5_default_widget_demo' );

function t5_default_widget_demo()
{
    // Register our own widget.
    register_widget( 'T5_Demo_Widget' );

    // Register two sidebars.
    $sidebars = array ( 'a' => 'top-widget', 'b' => 'bottom-widget' );
    foreach ( $sidebars as $sidebar )
    {
        register_sidebar(
            array (
                'name'          => $sidebar,
                'id'            => $sidebar,
                'before_widget' => '',
                'after_widget'  => ''
            )
        );
    }

Şimdiye kadar, çok basit. Bizim tema artık widget hazır, demo widget biliniyor. Şimdi eğlence.

$active_widgets = get_option( 'sidebars_widgets' );

if ( ! empty ( $active_widgets[ $sidebars['a'] ] )
    or ! empty ( $active_widgets[ $sidebars['b'] ] )
)
{   // Okay, no fun anymore. There is already some content.
    return;
}

Gerçekten kullanıcı ayarlarını yok etmek istemezsin. Kenar çubuklarında zaten içerik varsa, kodunuz üzerinde çalışmamalıdır. Bu yüzden bu durumda duruyoruz.

Tamam, kenar çubuklarının boş olduğu varsayılıyor… bir sayaca ihtiyacımız var:

$counter = 1;

Widget'lar numaralandırılmıştır . Bu sayılar WordPress için ikinci tanımlayıcıdır.

Bunu değiştirmek için diziyi alalım:

$active_widgets = get_option( 'sidebars_widgets' );

Bir sayaca da ihtiyacımız var (daha fazlası için):

$counter = 1;

Ve işte sayacı, kenar çubuğu isimlerini ve widget argümanlarını nasıl kullanacağımız text.

// Add a 'demo' widget to the top sidebar …
$active_widgets[ $sidebars['a'] ][0] = 't5_demo_widget-' . $counter;
// … and write some text into it:
$demo_widget_content[ $counter ] = array ( 'text' => "This works!\n\nAmazing!" );

$counter++;

Widget tanımlayıcısının nasıl oluşturulduğuna dikkat edin: id_baseeksi -ve sayaç. İçerik aracının başka bir değişken olarak depolanır $demo_widget_content. Burada sayaç ve anahtar değişkenleri argümanlar bir dizide saklanır.

Çarpışmaları önlemek için işlem bittiğinde sayacı birer birer artırıyoruz.

Kolaydı. Şimdi bir RSS gereci. Daha fazla alan, daha eğlenceli!

$active_widgets[ $sidebars['a'] ][] = 'rss-' . $counter;
// The latest 15 questions from WordPress Stack Exchange.
$rss_content[ $counter ] = array (
    'title'        => 'WordPress Stack Exchange',
    'url'          => 'http://wordpress.stackexchange.com/feeds',
    'link'         => 'http://wordpress.stackexchange.com/questions',
    'items'        => 15,
    'show_summary' => 0,
    'show_author'  => 1,
    'show_date'    => 1,
);
update_option( 'widget_rss', $rss_content );

$counter++;

İşte yeni bir şey: update_option()bu, RSS widget argümanını ayrı bir seçenekte saklayacaktır. WordPress bunları daha sonra otomatik olarak bulacaktır.
Demo widget değişkenlerini kaydetmedik çünkü şimdi ikinci kenar çubuğumuza ikinci bir örnek ekledik…

// Okay, now to our second sidebar. We make it short.
$active_widgets[ $sidebars['b'] ][] = 't5_demo_widget-' . $counter;
#$demo_widget_content = get_option( 'widget_t5_demo_widget', array() );
$demo_widget_content[ $counter ] = array ( 'text' => 'The second instance of our amazing demo widget.' );
update_option( 'widget_t5_demo_widget', $demo_widget_content );

… Ve t5_demo_widgettek bir acele için tüm argümanları kaydedin . Aynı seçeneği iki kez güncellemeye gerek yok.

Pekala, bugün için yeterince alet, hadi de sidebars_widgetskurtaralım:

update_option( 'sidebars_widgets', $active_widgets );

Şimdi WordPress bazı kayıtlı widget'lar olduğunu ve her widget için argümanların nerede saklandığını bilecek. var_export()Sidebar_widgets üzerindeki A şunun gibi görünecektir:

array (
  'wp_inactive_widgets' => 
  array (
  ),
  'top-widget' => 
  array (
    0 => 't5_demo_widget-1',
    1 => 'rss-2',
  ),
  'bottom-widget' => 
  array (
    0 => 't5_demo_widget-3',
  ),
  'array_version' => 3,
)

Tam kod tekrar:

add_action( 'widgets_init', 't5_default_widget_demo' );

function t5_default_widget_demo()
{
    // Register our own widget.
    register_widget( 'T5_Demo_Widget' );

    // Register two sidebars.
    $sidebars = array ( 'a' => 'top-widget', 'b' => 'bottom-widget' );
    foreach ( $sidebars as $sidebar )
    {
        register_sidebar(
            array (
                'name'          => $sidebar,
                'id'            => $sidebar,
                'before_widget' => '',
                'after_widget'  => ''
            )
        );
    }

    // Okay, now the funny part.

    // We don't want to undo user changes, so we look for changes first.
    $active_widgets = get_option( 'sidebars_widgets' );

    if ( ! empty ( $active_widgets[ $sidebars['a'] ] )
        or ! empty ( $active_widgets[ $sidebars['b'] ] )
    )
    {   // Okay, no fun anymore. There is already some content.
        return;
    }

    // The sidebars are empty, let's put something into them.
    // How about a RSS widget and two instances of our demo widget?

    // Note that widgets are numbered. We need a counter:
    $counter = 1;

    // Add a 'demo' widget to the top sidebar …
    $active_widgets[ $sidebars['a'] ][0] = 't5_demo_widget-' . $counter;
    // … and write some text into it:
    $demo_widget_content[ $counter ] = array ( 'text' => "This works!\n\nAmazing!" );
    #update_option( 'widget_t5_demo_widget', $demo_widget_content );

    $counter++;

    // That was easy. Now a RSS widget. More fields, more fun!
    $active_widgets[ $sidebars['a'] ][] = 'rss-' . $counter;
    // The latest 15 questions from WordPress Stack Exchange.
    $rss_content[ $counter ] = array (
        'title'        => 'WordPress Stack Exchange',
        'url'          => 'http://wordpress.stackexchange.com/feeds',
        'link'         => 'http://wordpress.stackexchange.com/questions',
        'items'        => 15,
        'show_summary' => 0,
        'show_author'  => 1,
        'show_date'    => 1,
    );
    update_option( 'widget_rss', $rss_content );

    $counter++;

    // Okay, now to our second sidebar. We make it short.
    $active_widgets[ $sidebars['b'] ][] = 't5_demo_widget-' . $counter;
    #$demo_widget_content = get_option( 'widget_t5_demo_widget', array() );
    $demo_widget_content[ $counter ] = array ( 'text' => 'The second instance of our amazing demo widget.' );
    update_option( 'widget_t5_demo_widget', $demo_widget_content );

    // Now save the $active_widgets array.
    update_option( 'sidebars_widgets', $active_widgets );
}

Eğer giderseniz wp-admin/widgets.phpşimdi üç ön ayarlı widget'lar göreceksiniz:

aktif gereçlerin ekran görüntüsü

Ve bu kadar. Kullan…

dynamic_sidebar( 'top-widget' );
dynamic_sidebar( 'bottom-widget' );

… Gereçleri yazdırmak için.

Küçük bir aksaklık var: İlk kayıt için ön ucu iki kez yüklemelisiniz. Biri burada yardım edebilirse çok minnettar olacağım.


Bu gerçekten ilginç .. ama bu kod her sayfa yüklenme işleminde "yeni" bir widget eklemeyecek mi? Ayrıca, ilginç olan bir başka konu da, bu widget'lerin içeriğini temanın tersine bir eklenti içerisinden de dahil olmak üzere (daha önce yüklenenler) nasıl kontrol edebileceğidir
krembo99

1
@ krembo99 Kenar çubukları boş olmadığı zaman pencere öğeleri eklenmez. Kod tam olarak aynı şekilde bir eklentide çalışır.
fuxia

Ne gelmez widget_t5_demo_widgetburaya bakınız: update_option( 'widget_t5_demo_widget', $demo_widget_content );?
Snowcrash

@SnowCrash Bu sadece bir seçenek adı, başka hiçbir şeye referans yok.
fuxia

3

Çözümünüzü paylaştığınız için teşekkür ederiz. Kenar çubuğunu çok kolay başlatmak için kullanılabilecek bir kod parçası oluşturmak için bu soruda açıklananları kullandım. Çok esnektir, kodu değiştirmek zorunda kalmadan istediğiniz kadar widget oluşturabilirsiniz. Sadece filtre kancalarını kullanın ve bir dizideki argümanları iletin. Yorumlanan kod:

function initialize_sidebars(){

  $sidebars = array();
  // Supply the sidebars you want to initialize in a filter
  $sidebars = apply_filters( 'alter_initialization_sidebars', $sidebars );

  $active_widgets = get_option('sidebars_widgets');

  $args = array(
    'sidebars' => $sidebars,
    'active_widgets' => $active_widgets,
    'update_widget_content' => array(),
  );

  foreach ( $sidebars as $current_sidebar_short_name => $current_sidebar_id ) {

    $args['current_sidebar_short_name'] = $current_sidebar_short_name;
    // we are passing our arguments as a reference, so we can modify their contents
    do_action( 'your_plugin_sidebar_init', array( &$args ) );

  }
  // we only need to update sidebars, if the sidebars are not initialized yet
  // and we also have data to initialize the sidebars with
  if ( ! empty( $args['update_widget_content'] ) ) {

    foreach ( $args['update_widget_content'] as $widget => $widget_occurence ) {

      // the update_widget_content array stores all widget instances of each widget
      update_option( 'widget_' . $widget, $args['update_widget_content'][ $widget ] );

    }
    // after we have updated all the widgets, we update the active_widgets array
    update_option( 'sidebars_widgets', $args['active_widgets'] );

  }

}

Bu, kenar çubuğunun içinde içerik olup olmadığını kontrol eden yardımcı bir işlevdir:

function check_sidebar_content( $active_widgets, $sidebars, $sidebar_name ) {

  $sidebar_contents = $active_widgets[ $sidebars[ $sidebar_name ] ];

  if ( ! empty( $sidebar_contents ) ) {

    return $sidebar_contents;

  }

  return false;

}

Şimdi 'sidebar_init' eylemine bağlı bir işlev yaratmamız gerekiyor.

add_action( 'your_plugin_sidebar_init', 'add_widgets_to_sidebar' );

function add_widgets_to_sidebar( $args ) {

  extract( $args[0] );

  // We check if the current sidebar already has content and if it does we exit
  $sidebar_element = check_sidebar_content( $active_widgets, $sidebars, $current_sidebar_short_name );

  if ( $sidebar_element !== false  ) {

    return;

  }

  do_action( 'your_plugin_widget_init', array( &$args ) );

}

Ve şimdi widget başlatma:

add_action( 'your_plugin_widget_init', 'your_plugin_initialize_widgets' );

function your_plugin_initialize_widgets( $args ) {

  extract( $args[0][0] );

  $widgets = array();

  // Here the widgets previously defined in filter functions are initialized,
  // but only those corresponding to the current sidebar 
  $widgets = apply_filters( 'alter_initialization_widgets_' . $current_sidebar_short_name, $widgets );

  if ( ! empty( $widgets ) ) {

    do_action( 'create_widgets_for_sidebar', array( &$args ), $widgets );

  }

}

Son eylem, her kenar çubuğunda widget oluşturmaktır:

add_action( 'create_widgets_for_sidebar', 'your_plugin_create_widgets', 10, 2 );

function your_plugin_create_widgets( $args, $widgets ) {

  extract( $args[0][0][0] );

  foreach ( $widgets as $widget => $widget_content ) {

    // The counter is increased on a widget basis. For instance, if you had three widgets,
    // two of them being the archives widget and one of the being a custom widget, then the
    // correct counter appended to each one of them would be archive-1, archive-2 and custom-1.
    // So the widget counter is not a global counter but one which counts the instances (the
    // widget_occurrence as I have called it) of each widget.
    $counter = count_widget_occurence( $widget, $args[0][0][0]['update_widget_content'] );

    // We add each instance to the active widgets...
    $args[0][0][0]['active_widgets'][ $sidebars[ $current_sidebar_short_name ] ][] = $widget . '-' . $counter;

    // ...and also save the content in another associative array.
    $args[0][0][0]['update_widget_content'][ $widget ][ $counter ] = $widget_content;

  }

}

Bu işlev, belirli bir pencere öğesinin kaç örneğinin önceden tanımlanmış olduğunu takip etmek için kullanılır:

function count_widget_occurence( $widget, $update_widget_content ) {

  $widget_occurrence = 0;

  // We look at the update_widget_content array which stores each
  // instance of the current widget with the current counter in an 
  // associative array. The key of this array is the name of the 
  // current widget.
      // Having three archives widgets for instance would look like this:
      // 'update_widget_content'['archives'] => [1][2][3] 
  if ( array_key_exists( $widget, $update_widget_content ) ) {

    $widget_counters = array_keys( $update_widget_content[ $widget ] );

    $widget_occurrence = end( $widget_counters );

  }

  $widget_occurrence++;

  return $widget_occurrence;

}

Yapmamız gereken son şey aslında değer atamak. Bu filtre işlevlerinden yararlanın:

add_filter( 'alter_initialization_sidebars', 'current_initialization_sidebars' ) ;
// Use this filter hook to specify which sidebars you want to initialize
function current_initialization_sidebars( $sidebars ) {

  // The sidebars are assigned in this manner.
  // The array key is very important because it is used as a suffix in the initialization function
  // for each sidebar. The value is what is used in the html attributes.
  $sidebars['info'] = 'info-sidebar';

  return $sidebars;

}

Ve:

add_filter( 'alter_initialization_widgets_info', 'current_info_widgets' );
// Add a filter hook for each sidebar you have. The hook name is derived from
// the array keys passed in the alter_initialization_sidebars filter. 
// Each filter has a name of 'alter_initialization_widgets_' and the array 
// key appended to it.

function current_info_widgets( $widgets ) {
  // This filter function is used to add widgets to the info sidebar. Add each widget
  // you want to assign to this sidebar to an array.

  return $widgets = array(
    // Use the name of the widget as specified in the call to the WP_Widget constructor
    // as the array key.

    // The archives widget is a widget which is shipped with wordpress by default.
    // The arguments used by this widget, as all other default widgets, can be found
    // in wp-includes/default-widgets.php. 

    'archives' => array(
      // Pass in the array options as an array
      'title' => 'Old Content',
      'dropdown' => 'on',
      // The 'on' value is arbitrarily chosen, the widget actually only checks for
      // a non-empty value on both of these options
      'count' => 'on',
    ),
 );

}

İdeal olarak, initialize_sidebars'ı eklenti ya da tema etkinleştirme üzerine çağrılan bir kurulum işlevinde şöyle çağırırsınız: Tema etkinleştirme:

add_action( 'after_switch_theme', 'my_activation_function' );
function my_activation_function() {
  initialize_sidebars();
}

Eklenti aktivasyonu:

register_activation_hook( __FILE__, 'my_activation_function' );
function my_activation_function() {
  initialize_sidebars();
}

Bu işlevler kümesinin kullanımını özetlemek için:

  1. 'alter_initialization_sidebars' filtresine bağlı olan kenar çubuklarını başlatan bir fonksiyon yarat.

  2. 'alter_initialization_widgets_ $ sidebarname' filtresine bağlı yeni eklediğiniz her kenar çubuğu için bir işlev oluşturun. $ Sidebarname değerini 1. adımda oluşturduğunuz her bir kenar çubuğunun adıyla değiştirin.

Ayrıca bu açıklanmamış kodu fonksiyon dosyanıza kopyalayabilir ve filtre fonksiyonlarınızı hemen oluşturmaya başlayabilirsiniz: Pasta üzerine kod (başlatma filtresi fonksiyonları olmadan)


2

Her şeyden önce, ayrıntılı cevap için @toscho teşekkürler.

Bu, basit bir çözüm ve varsayılan widget seçeneklerini arayanlara basit bir örnektir:

$active_sidebars = get_option( 'sidebars_widgets' ); //get all sidebars and widgets
$widget_options = get_option( 'widget_name-1' );
$widget_options[1] = array( 'option1' => 'value', 'option2' => 'value2' );

if(isset($active_sidebars['sidebar-id']) && empty($active_sidebars['sidebar-id'])) { //check if sidebar exists and it is empty

    $active_sidebars['sidebar-id'] = array('widget_name-1'); //add a widget to sidebar
    update_option('widget_name-1', $widget_options); //update widget default options
    update_option('sidebars_widgets', $active_sidebars); //update sidebars
}

Not 1: sidebar-idWidgetler menüsüne gidip istediğiniz kenar çubuğunu kontrol edebilirsiniz. İlk <div id="widgets-holder-wrap">'ın <div>çocuk vardırsidebar-id .

Not 2: widget_nameWidget'lar menüsüne gidip istenen widget'ı kontrol edebilirsiniz. Gibi bir şey göreceksiniz <div id="widget-6_widget_name-__i__" class="widget ui-draggable">.

Keşke yardım ederse.


0

Bu nasıl yapılır:

(UYARI, orijinal widget'leri widgetsdiziye geri koymazsanız, önceki tüm widget'ları ÇIKARABİLİR .)

    $widgets = array(
    'middle-sidebar' => array(
        'widget_name'
    ),
    'right-sidebar' => array(
        'widget2_name-1'
    )
);
update_option('sidebars_widgets', $widgets);

Ardından, widget'a daha sonra böyle bir seçenekle seçenekler eklemek isterseniz:

    update_option('widget_widget_name', array(
    1 => array(
        'title' => 'The tile',
        'number' => 4
    ),
    '_multiwidget' => 1
));

1
BU TAKİP ETMEYİN, BU AŞAĞI DEĞERLENDİREMEZ. BU KODUN KULLANILMASINDAN SONRA TÜM MY WIDGETS YERLEŞTİRDİ.
EresDev

İlk önce varolan widget dizisini almanız gerekir, aksi takdirde hepsini yukarıda belirtilen şekilde silebilirsiniz. $widgets = get_option( 'sidebars_widgets' );
cowgill
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.