問題描述

我已經嘗試了一些研究,但還沒有找到任何堅實的東西。我有一個我正在工作的插件,在最後一個版本和新版本之間,我們對更改某些設置名稱 (在後端) 的窗口小工具進行了一些更新,我無法創建升級例程來執行此操作。

到目前為止,我所做的這個 (大部分) 工作是這樣的:

$widget = get_option( 'widget_name' );

if( is_array( $widget ) && ! empty( $widget ) ) {
    foreach( $widget as $a => $b ) {
        if( ! is_array( $b ) ) {
            continue;
        }

        foreach( $b as $k => $v ) {
            $widget[$a]['setting1'] = $widget[$a]['oldsetting1'];
            $widget[$a]['setting2'] = $widget[$a]['oldsetting2'];
        }
    }

    update_option( 'widget_name', $widget );
}

在我的大部分測試中,這樣做的確可以,但是問題就是舊的 widget 不再顯示它的輸出。只會顯示小工具的標題。我可以通過去保存每個單獨的小工具來解決這個問題,然後它會正常工作,但是我不想讓我的用户做到這一點。

我以為這樣的事情可能會起作用:

$settings = $widgets->get_settings();

foreach( $settings as $s ) {

    $s['setting1'] = $s['oldsetting1'];
    $s['setting2'] = $s['oldsetting2'];

    $widgets->save_settings( $s );

}

但是,似乎 save_settings()調用必須是錯誤的,因為這會完全刪除該窗口。

我無法找到任何這樣的標準,只是想聽到任何想法,想法或鏈接,你可能要做這樣的事情。

提前感謝任何幫助。

編輯:

這實際上並不是關於追蹤許可證密鑰或升級不在 WP repo 上託管的插件的問題。這更重要的是在用户升級時更新 2 版本的插件之間的設置。

例:

版本 1.0.0 有一個設置字段 name

在 1.1.0 版本中,我們決定我們需要使用第一個和最後一個名字,所以我們將舊的設置改為 first_name,然後添加一個新的設置 last_name

如果將這些選項保存為自定義帖子類型的後期元數據,則不會出現問題:

$old_name = get_post_meta( $post->ID, 'name', true );
$first_name = update_post_meta ( $post->ID, 'first_name', true );
delete_post_meta( $post->ID, 'name' );

所以這部分很容易。我遇到麻煩,似乎並不容易做同樣的事情,但 WIDGET 設置。

希望這將清除任何混亂和幫助,使這更容易回答。

編輯 2:

來自第一代碼塊的 echo '<pre>' . print_r( $widget, true ) . '</pre>'; 的結果:

Array
(
[2] => Array
    (
        [title] => Class Schedule
        [id] => 23
        [display_type] => grid
        [order] => asc
        [display_title_text] => Events on
        [paging] => 1
        [list_max_num] => 7
        [list_max_length] => days
        [list_start_offset_num] => 0
        [list_start_offset_direction] => back
        [gce_per_page_num] => 7
        [gce_events_per_page] => days
    )

[3] => Array
    (
        [title] => Examples
        [id] => 24
        [display_type] => grid
        [order] => asc
        [display_title_text] => Events on
        [paging] => 1
        [list_max_num] => 7
        [list_max_length] => days
        [list_start_offset_num] => 0
        [list_start_offset_direction] => back
        [gce_per_page_num] => 7
        [gce_events_per_page] => days
    )

[_multiwidget] => 1
)

最佳解決方案

我已經做了一個快速測試,只是改變選項,它似乎工作。

我所做的是:

  1. 寫了一個只有 2 個字段的小工具:”Title” 和”Name” 。將這個小工具的幾個實例添加到我的側邊欄。確保它們在前端正確顯示。

  2. 編輯該類使用 3 個字段:”Title” 和”First Name”(替換”Name”) 並添加”Last Name” 。

  3. 編輯在'widgets_init'上註冊窗口小工具以調用更新窗口小工具選項的功能的功能:

    add_action( 'widgets_init', 'my_example_widget_register' );
    
    function my_example_widget_register() {
    
      $widget_name = 'my_example_widget';  // <-- You will probably replace this
    
      $options = get_option("widget_{$widget_name}");
    
      // if the widget is not updated, run a function that updates it
      if ($options && ! get_option("is_{$widget_name}_updated")) {
          // use class below to update options
          $updater = new MyExampleWidgetUpdater($widget_name, $options);
          $updater->update();
      }
    
      register_widget('My_Example_Widget'); // <-- You will probably replace this
    }
    
  4. 寫了一個簡單的類來更新小工具選項:

    class MyExampleWidgetUpdater
    {
    
      private $name;
      private $options;
    
      public function __construct($name, $options) {
         $this->name = $name;
         $this->options = $options;
      }
    
      public function update() {
        // loop all the options
        array_walk($this->options, function(&$option, $key) {
            if (is_array($option) && is_numeric($key)) {
              $option = $this->getOption($option);
            }
        });
        // update all options in DB
        update_option("widget_{$this->name}", $this->options);
        // set the widget as updated
        update_option("is_{$this->name}_updated", 1);
      }
    
      private function getOption($options) {
        if (!isset($options['name'])) {
           return $options;
        }
        $options['first_name'] = $options['name'];
        $options['last_name'] = '';
        unset($options['name']);
        return $options;
      }
    }
    
  5. 我編輯了窗口小工具類,以便將"is_{$widget_name}_updated"選項保存在 update()方法中,這樣就不會為沒有安裝舊窗口小工具的新用户調用 updater 類

    class My_Example_Widget {
    
        ...
    
        public function update($new_instance, $old_instance) {
            ...
    
            $widget_name = 'my_example_widget';
            update_option("is_{$widget_name}_updated", 1);
        }
    }
    
  6. 我訪問了我的網站,使用舊選項保存的小工具顯示沒有問題使用新的選項。 (當然”last name” 一直是空的) 。

一個好主意可能是替換"is_{$widget_name}_updated"選項,並具有存儲實際版本的小工具的選項,這樣,下次您需要更新時將會很方便。

參考文獻

注:本文內容整合自 Google/Baidu/Bing 輔助翻譯的英文資料結果。如果您對結果不滿意,可以加入我們改善翻譯效果:薇曉朵技術論壇。