Secara terprogram tambahkan widget ke sidebar


62

Saya ingin secara terprogram menambahkan widget ke dua sidebar yang saya miliki. Saya tidak dapat menemukan cara resmi untuk melakukannya?

Saya mulai mencari di database. Saya telah menemukan bahwa itu adalah opsi 'sidebars_widgets' yang menempatkan widget di sidebars. Saat melihat opsi, nama widget memiliki nomor yang ditambahkan di akhir seperti: widget_name-6. Dari mana angka itu berasal?

ada ide untuk memperbaiki ini?


6
Anda harus menambahkan jawaban Anda di sana untuk menjawab pertanyaan Anda sendiri :)
helenhousandi

Untuk ikhtisar yang bagus tentang widget bilah samping, lihat artikel ini: justintadlock.com/archives/2010/11/08/sidebars-in-wordpress .
Joshua

Pantau parameter aksi panggilan ajax yang dibuat saat widget ditambahkan, dan kemudian cari kode yang terkait dengan tindakan itu, kait ajax dan lihat bagaimana hal itu dilakukan pada intinya. Sederhana! ;)
Ashfame

5
Harap memposting ulang solusi Anda sebagai jawaban dan menerimanya sebagai jawaban "the" untuk masalah Anda.
EAMann

Jawaban:


91

Ketika saya memulai jawaban ini, itu seharusnya hanya sebuah catatan kecil. Yah, saya gagal. Maaf! Tetap bersamaku, ada yang tersembunyi di dalam hati ...

Bagaimana widget WordPress disimpan

Daftar widget disimpan dalam opsi bernama 'sidebars_widgets'. A var_export()dapat memberikan sesuatu seperti berikut:

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

Abaikan 'wp_inactive_widgets'dan 'array_version'. Kami tidak perlu peduli tentang itu.
Kunci lainnya adalah pengidentifikasi untuk bilah samping yang terdaftar. Dalam hal ini bilah sisi mungkin telah terdaftar dengan kode ini:

// 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'  => ''
        )
    );
}

Secara default, sidebar kosong setelah pendaftaran. Tentu saja.

Untuk setiap kelas widget terdaftar, opsi terpisah dibuat, berisi semua opsi yang diperlukan. Opsi diawali oleh string widget_. Untuk mendapatkan opsi untuk semua widget RSS aktif, kita harus melihat ke ...

get_option( 'widget_rss' );

Output yang mungkin:

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,
  ),
)

Catat angka 2 . Argumen untuk beberapa instance semuanya disimpan dalam opsi yang diurutkan berdasarkan angka.

Untuk melihat kelas widget mana yang sudah diketahui oleh WordPress, buka wp-admin/options.phpdan gulir ke bawah sampai Anda melihat sesuatu seperti ini:

tangkapan layar dari opsi widget serial

Ya, data serial. Tidak, Anda tidak dapat membacanya di sini. Jangan khawatir, kamu tidak harus.

Widget demo

Untuk menggambarkan pekerjaan dalam yang lebih baik, saya telah menulis widget demo yang sangat sederhana:

/**
 * 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
        );
    }
}

Perhatikan konstruktor: 't5_demo_widget'adalah $id_base, pengidentifikasi untuk widget ini. Seperti yang Anda lihat di screen shot, argumennya disimpan dalam opsi widget_t5_demo_widget. Semua widget khusus Anda akan diperlakukan seperti ini. Anda tidak perlu menebak namanya. Dan karena Anda telah menulis widget Anda (mungkin), Anda tahu semua argumen dari $instanceparameter kelas Anda .

Dasar-dasar tema

Pertama, Anda harus mendaftarkan beberapa sidebar dan widget khusus. Tindakan yang tepat untuk ini adalah mudah diingat: 'widgets_init'. Masukkan semuanya ke dalam wadah - kelas atau fungsi. Untuk mempermudah saya akan menggunakan fungsi bernamat5_default_widget_demo() .

Semua kode berikut masuk ke functions.php. Kelas T5_Demo_Widgetharus sudah dimuat. Saya hanya memasukkannya ke file yang sama ...

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'  => ''
            )
        );
    }

Sejauh ini, sangat sederhana. Tema kami sekarang widget siap, widget demo dikenal. Sekarang menyenangkan.

$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;
}

Anda benar-benar tidak ingin merusak pengaturan pengguna. Jika sudah ada beberapa konten di sidebar, kode Anda tidak boleh melewatinya. Itu sebabnya kami berhenti dalam kasus ini.

Oke, anggap sidebar kosong ... kita perlu penghitung:

$counter = 1;

Widget diberi nomor . Angka-angka ini adalah pengidentifikasi kedua untuk WordPress.

Mari kita minta array untuk mengubahnya:

$active_widgets = get_option( 'sidebars_widgets' );

Kami juga membutuhkan penghitung (lebih lanjut tentang itu nanti):

$counter = 1;

Dan inilah cara kami menggunakan penghitung, nama bilah sisi, dan argumen widget (well, kami hanya punya satu argumen:) 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++;

Perhatikan bagaimana pengenal widget dibuat: the id_base, a minus -dan the counter. The isi dari widget tersebut disimpan dalam variabel lain $demo_widget_content. Ini adalah counter kuncinya dan argumen widget disimpan dalam array.

Kami menambah penghitung satu demi satu ketika kami selesai untuk menghindari tabrakan.

Itu mudah. Sekarang widget RSS. Lebih banyak bidang, lebih menyenangkan!

$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++;

Ini adalah sesuatu yang baru: update_option()ini akan menyimpan argumen widget RSS dalam opsi terpisah. WordPress akan menemukan ini secara otomatis nanti.
Kami tidak menyimpan argumen widget demo karena kami menambahkan instance kedua ke sidebar kedua kami sekarang ...

// 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 );

... dan simpan semua argumen untuk t5_demo_widgetsatu pencarian. Tidak perlu memperbarui opsi yang sama dua kali.

Nah, cukup widget untuk hari ini, mari kita simpan sidebars_widgetsjuga:

update_option( 'sidebars_widgets', $active_widgets );

Sekarang WordPress akan tahu bahwa ada beberapa widget terdaftar dan di mana argumen untuk setiap widget disimpan. A var_export()di sidebar_widgets akan terlihat seperti ini:

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,
)

The lengkap kode lagi:

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 );
}

Jika Anda masuk ke wp-admin/widgets.phpsekarang Anda akan melihat tiga widget yang telah ditetapkan:

tangkapan layar widget aktif

Dan itu saja. Gunakan ...

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

... untuk mencetak widget.

Ada kesalahan kecil: Anda harus memuat front-end dua kali untuk pendaftaran awal. Jika ada yang bisa membantu di sini saya akan sangat berterima kasih.


Ini sangat menarik .. tetapi bukankah kode ini menambahkan widget "baru" di setiap halaman `? juga, masalah menarik lainnya adalah bagaimana seseorang dapat mengontrol widget tersebut, termasuk kontennya dari dalam sebuah plugin yang bertentangan dengan tema (memuat lebih awal?)
krembo99

1
@ krembo99 Widget tidak ditambahkan ketika sidebar tidak kosong. Kode berfungsi dalam plugin dengan cara yang persis sama.
fuxia

Apa yang dimaksud widget_t5_demo_widgetdengan di sini update_option( 'widget_t5_demo_widget', $demo_widget_content );:?
Snowcrash

@SnowCrash Itu hanya nama opsi, tidak ada referensi ke hal lain.
fuxia

3

Terima kasih telah membagikan solusi Anda. Saya telah menggunakan apa yang telah dijelaskan dalam pertanyaan ini untuk membuat sepotong kode yang dapat digunakan untuk menginisialisasi sidebar dengan sangat mudah. Ini sangat fleksibel, Anda dapat membuat widget sebanyak yang Anda inginkan tanpa harus mengubah kode sama sekali. Cukup gunakan kait saringan dan berikan argumen dalam sebuah array. Berikut adalah kode yang dikomentari:

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'] );

  }

}

Ini adalah fungsi pembantu yang memeriksa apakah bilah samping sudah memiliki konten di dalamnya:

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;

}

Sekarang kita perlu membuat fungsi yang terhubung ke aksi 'sidebar_init'.

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 ) );

}

Dan sekarang inisialisasi widget:

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 );

  }

}

Tindakan terakhir adalah membuat widget di setiap bilah sisi:

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;

  }

}

Fungsi ini digunakan untuk melacak berapa banyak contoh widget tertentu yang telah ditentukan:

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;

}

Hal terakhir yang perlu kita lakukan adalah memberikan nilai. Manfaatkan fungsi filter ini:

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;

}

Dan:

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',
    ),
 );

}

Idealnya Anda akan memanggil initialize_sidebars dalam fungsi pengaturan yang dipanggil pada plugin atau aktivasi tema seperti ini: Aktivasi tema:

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

Aktivasi plugin:

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

Untuk meringkas penggunaan konglomerat fungsi ini:

  1. buat fungsi yang menginisialisasi bilah samping yang terhubung ke filter 'alter_initialization_sidebars'.

  2. buat fungsi untuk setiap sidebar yang baru saja Anda tambahkan yang terhubung ke filter 'alter_initialization_widgets_ $ sidebarname'. Ganti $ sidebarname dengan nama setiap sidebar yang Anda buat pada langkah 1.

Anda juga dapat dengan mudah menyalin kode uncommented ini ke file fungsi Anda dan mulai membuat fungsi filter Anda segera: Kode pada pastie (tanpa fungsi inisialisasi filter)


2

Pertama-tama, terima kasih kepada @toscho untuk jawaban terperinci.

Ini adalah contoh sederhana bagi mereka yang mencari solusi sederhana dan opsi widget standar:

$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
}

Catatan 1: Anda dapat sidebar-idmembuka menu widget dan memeriksa bilah sisi yang diinginkan. Pertama <div id="widgets-holder-wrap">'s <div>anak memilikisidebar-id .

Catatan 2: Anda bisa widget_namemembuka menu widget dan memeriksa widget yang diinginkan. Anda akan melihat sesuatu seperti <div id="widget-6_widget_name-__i__" class="widget ui-draggable">.

Saya harap ini membantu.


0

Inilah cara Anda melakukannya:

(PERINGATAN, ini bisa MENGHAPUS semua widget sebelumnya jika Anda tidak memasukkan kembali widget asli ke dalam widgetsarray.)

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

-Number dapat digunakan jika nanti Anda ingin menambahkan opsi ke widget dengan sesuatu seperti ini:

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

1
JANGAN IKUTI INI, SAYA TIDAK BISA NILAI TURUN. SEMUA WIDGET S MY DISAPPEARED SETELAH MENGGUNAKAN KODE INI.
EresDev

Anda harus mendapatkan array widget yang ada terlebih dahulu jika tidak, Anda akan menghapusnya semua seperti komentar di atas. $widgets = get_option( 'sidebars_widgets' );
cowgill
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.