Lập trình thêm widget vào sidebars


62

Tôi muốn lập trình thêm các widget vào hai thanh bên mà tôi đã có. Tôi không thể tìm thấy bất kỳ cách chính thức để làm điều đó?

Tôi bắt đầu tìm kiếm trong cơ sở dữ liệu. Tôi đã thấy rằng đó là tùy chọn 'sidebars_widgets', đặt các widget trên sidebars. Khi nhìn vào các tùy chọn, tên của widget có một số được thêm vào cuối như: widget_name-6. Con số đó đến từ đâu?

Còn ý tưởng nào để sửa cái này nữa không?


6
Bạn nên thêm câu trả lời của mình xuống đó để trả lời câu hỏi của riêng bạn :)
helenhousandi

Để có một danh sách tuyệt vời trên các tiện ích thanh bên, hãy xem bài viết này: justintadlock.com/archives/2010/11/08/sidebars-in-wordpress .
Joshua

Theo dõi tham số hành động của lệnh gọi ajax được thực hiện khi một tiện ích được thêm vào, sau đó tìm mã liên quan đến móc hành động ajax đó và xem cách thực hiện trong lõi. Đơn giản! ;)
Ashfame

5
Vui lòng đăng lại giải pháp của bạn dưới dạng câu trả lời và chấp nhận nó là "câu trả lời" cho vấn đề của bạn.
EAMann

Câu trả lời:


91

Khi tôi bắt đầu câu trả lời này, nó chỉ là một ghi chú nhỏ. Chà, tôi đã thất bại. Lấy làm tiếc! Ở lại với tôi, có một điều tốt đẹp ẩn sâu xuống

Cách các widget WordPress được lưu trữ

Danh sách các widget được lưu trữ trong một tùy chọn có tên 'sidebars_widgets'. A var_export()có thể cung cấp một cái gì đó như sau:

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

Bỏ qua 'wp_inactive_widgets''array_version'. Chúng ta không cần phải quan tâm đến những điều đó.
Các khóa khác là định danh cho các thanh bên đã đăng ký. Trong trường hợp này, các thanh bên có thể đã được đăng ký với mã này:

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

Theo mặc định, các sidebars trống sau khi đăng ký. Tất nhiên.

Đối với mỗi lớp widget đã đăng ký, một tùy chọn riêng biệt được tạo, chứa tất cả các tùy chọn cần thiết. Tùy chọn được tiền tố bởi chuỗi widget_. Để có được các tùy chọn cho tất cả các tiện ích RSS đang hoạt động, chúng tôi phải tìm hiểu về

get_option( 'widget_rss' );

Sản lượng có thể:

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

Lưu ý số 2 . Các đối số cho nhiều trường hợp đều được lưu trữ trong tùy chọn này được sắp xếp theo số.

Để xem các lớp widget nào đã được WordPress biết đến, hãy wp-admin/options.phpcuộn xuống và cuộn xuống cho đến khi bạn thấy một cái gì đó như thế này:

ảnh chụp màn hình của các tùy chọn widget nối tiếp

Có, dữ liệu nối tiếp. Không, bạn không thể đọc chúng ở đây. Đừng lo lắng, bạn không cần phải làm vậy.

Một widget demo

Để minh họa các hoạt động bên trong tốt hơn tôi đã viết một tiện ích demo rất đơn giản:

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

Lưu ý hàm tạo: 't5_demo_widget'$id_base, định danh cho widget này. Như bạn có thể thấy trong màn hình, các đối số của nó được lưu trong tùy chọn widget_t5_demo_widget. Tất cả các vật dụng tùy chỉnh của bạn sẽ được đối xử như thế này. Bạn không cần phải đoán tên. Và vì bạn đã viết các widget của mình (có thể), bạn biết tất cả các đối số từ các $instancetham số của lớp .

Chủ đề cơ bản

Đầu tiên bạn phải đăng ký một số thanh bên và widget tùy chỉnh. Các hành động thích hợp cho điều này là dễ nhớ : 'widgets_init'. Đặt mọi thứ vào một thùng chứa - một lớp hoặc một chức năng. Để đơn giản, tôi sẽ sử dụng một hàm có tên t5_default_widget_demo().

Tất cả các mã sau đây đi vào functions.php. Các lớp T5_Demo_Widgetnên được tải. Tôi chỉ cần đặt nó vào cùng một tập tin

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

Cho đến nay, rất đơn giản. Chủ đề của chúng tôi bây giờ là widget đã sẵn sàng, tiện ích demo được biết đến. Bây giờ là niềm vui.

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

Bạn thực sự không muốn phá hủy cài đặt người dùng. Nếu đã có một số nội dung trong thanh bên, mã của bạn không nên chạy qua nó. Đó là lý do tại sao chúng ta dừng lại trong trường hợp này.

Được rồi, giả sử các thanh bên là trống rỗng, chúng tôi cần một bộ đếm:

$counter = 1;

Các widget được đánh số . Những con số này là định danh thứ hai cho WordPress.

Hãy lấy mảng để thay đổi nó:

$active_widgets = get_option( 'sidebars_widgets' );

Chúng ta cũng cần một bộ đếm (nhiều hơn về điều đó sau):

$counter = 1;

Và đây là cách chúng ta sử dụng bộ đếm, tên thanh bên và các đối số widget (tốt, chúng ta chỉ có một đối số 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++;

Lưu ý cách định danh widget được tạo: the id_base, trừ -và bộ đếm. Các nội dung của widget được lưu trữ trong một biến khác $demo_widget_content. Đây là bộ đếm khóa và các đối số widget được lưu trữ trong một mảng.

Chúng tôi tăng bộ đếm lên một khi chúng tôi hoàn thành để tránh va chạm.

Điều đó thật dễ dàng. Bây giờ là một tiện ích RSS. Nhiều lĩnh vực hơn, vui hơn!

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

Đây là một điều mới: update_option()điều này sẽ lưu trữ đối số tiện ích RSS trong một tùy chọn riêng. WordPress sẽ tự động tìm những thứ này sau.
Chúng tôi đã không lưu các đối số tiện ích demo vì chúng tôi thêm phiên bản thứ hai vào thanh bên thứ hai của chúng tôi ngay bây giờ

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

Càng và lưu tất cả các đối số cho t5_demo_widgettrong một vội vàng. Không cần phải cập nhật cùng một tùy chọn hai lần.

Chà, đủ vật dụng cho ngày hôm nay, chúng ta hãy lưu lại sidebars_widgets:

update_option( 'sidebars_widgets', $active_widgets );

Bây giờ WordPress sẽ biết rằng có một số widget đã đăng ký và nơi lưu trữ các đối số cho mỗi widget. Một var_export()trên sidebar_widgets sẽ trông như thế này:

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

Các hoàn chỉnh đang một lần nữa:

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

Nếu bạn đi đến wp-admin/widgets.phpbây giờ bạn sẽ thấy ba widget được cài đặt sẵn:

ảnh chụp màn hình của các vật dụng đang hoạt động

Và đó là nó. Sử dụng …

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

Để in các widget ra.

Có một trục trặc nhỏ: Bạn phải tải front-end hai lần cho đăng ký ban đầu. Nếu ai đó có thể giúp đỡ ở đây tôi sẽ rất biết ơn.


Điều này thực sự thú vị .. nhưng sẽ mã này thêm một tiện ích "mới" trong mỗi lần tải trang `? Ngoài ra, một vấn đề thú vị khác là làm thế nào người ta có thể kiểm soát các vật dụng đó, bao gồm nội dung của chúng từ bên trong một plugin trái ngược với chủ đề (tải trước đó?)
krembo99

1
@ krembo99 Các widget không được thêm vào khi các thanh bên không trống. Mã này hoạt động trong một plugin chính xác theo cùng một cách.
fuxia

Điều gì widget_t5_demo_widgetđề cập đến ở đây : update_option( 'widget_t5_demo_widget', $demo_widget_content );?
Snowcrash

@SnowCrash Đó chỉ là một tên tùy chọn, không liên quan đến bất cứ điều gì khác.
fuxia

3

Cảm ơn đã chia sẻ giải pháp của bạn. Tôi đã sử dụng những gì đã được mô tả trong câu hỏi này để tạo ra một đoạn mã có thể được sử dụng để khởi tạo sidebars rất dễ dàng. Nó rất linh hoạt, bạn có thể tạo bao nhiêu widget mà bạn muốn mà không phải sửa đổi mã nào cả. Chỉ cần sử dụng các móc lọc và chuyển các đối số trong một mảng. Đây là mã nhận xét:

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

  }

}

Đây là chức năng trợ giúp kiểm tra xem thanh bên đã có nội dung chưa:

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;

}

Bây giờ chúng ta cần tạo một hàm được nối với hành động '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 ) );

}

Và bây giờ khởi tạo 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 );

  }

}

Hành động cuối cùng là tạo các widget trong mỗi thanh bên:

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;

  }

}

Hàm này được sử dụng để theo dõi có bao nhiêu phiên bản của một widget cụ thể đã được xác định:

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;

}

Điều cuối cùng chúng ta cần làm là thực sự gán giá trị. Sử dụng các chức năng lọc này:

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;

}

Và:

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

}

Lý tưởng nhất là bạn sẽ gọi initize_sidebars trong một chức năng thiết lập được gọi là kích hoạt plugin hoặc chủ đề như thế này: Kích hoạt chủ đề:

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

Kích hoạt plugin:

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

Để tóm tắt việc sử dụng tập hợp hàm này:

  1. tạo một hàm khởi tạo các thanh bên được nối với bộ lọc 'notify_initialization_sidebars'.

  2. tạo một hàm cho mỗi thanh bên mà bạn vừa thêm, được nối với bộ lọc 'notify_initialization_widgets_ $ sidebarname'. Thay thế $ sidebarname bằng tên của mỗi thanh bên bạn đã tạo ở bước 1.

Bạn cũng có thể chỉ cần sao chép mã chưa được mã hóa này vào tệp chức năng của mình và bắt đầu tạo chức năng lọc ngay lập tức: Mã trên pastie (không có chức năng lọc khởi tạo)


2

Trước hết, cảm ơn @toscho cho câu trả lời chi tiết.

Đây là một ví dụ đơn giản cho những người đang tìm kiếm một giải pháp đơn giản và các tùy chọn widget mặc định:

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

Lưu ý 1: Bạn có thể sidebar-idvào menu widget và kiểm tra thanh bên mong muốn. Là người đầu tiên <div id="widgets-holder-wrap">của <div>đứa trẻ cósidebar-id .

Lưu ý 2: Bạn có thể widget_namevào menu widget và kiểm tra widget mong muốn. Bạn sẽ thấy một cái gì đó như <div id="widget-6_widget_name-__i__" class="widget ui-draggable">.

Tôi muốn nó giúp.


0

Đây là cách bạn làm điều đó:

(CẢNH BÁO, điều này có thể XÓA tất cả các vật dụng trước đó nếu bạn không đặt lại các vật dụng ban đầu vào widgetsmảng.)

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

-Số có thể được sử dụng nếu sau này bạn muốn thêm tùy chọn vào tiện ích với nội dung như sau:

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

1
ĐỪNG SAU NÀY, TÔI KHÔNG THỂ TẢI XUỐNG NÀY. TẤT CẢ CÁC WIDGET CỦA TÔI BỊ XÓA SAU KHI SỬ DỤNG MÃ NÀY.
EresDev

Trước tiên, bạn cần phải lấy mảng widget hiện có nếu không bạn sẽ xóa tất cả chúng như nhận xét ở trên đã nêu. $widgets = get_option( 'sidebars_widgets' );
cowgill
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.