如何细分Feed的导入

时间:2013-03-15 作者:urok93

我正在尝试使用fetch\\u feed将大量feed更新到WordPress中。正如所料,当超过50个feed时,服务器开始超时。我仍然希望批量更新feed,但不会使服务器崩溃。

你能建议一种我可以把事情分解的方法吗?也许使用AJAX?这是最好的技术吗?我可以看一些例子吗?

3 个回复
SO网友:Dan Ștefancu

您可以尝试使用wp cron函数,大约每10分钟编写一次feed导入程序,直到队列中什么都没有。

示例代码:

<?php
register_activation_hook( __FILE__, \'wp1903_schedule_cron\' );

function wp1903_schedule_cron() {
    $counter = 0;
    $feeds = array(
        \'http://example.com/feed1\',
        \'http://example.com/feed2\',
        \'http://example.com/feed3\',
        \'http://example.com/feed4\'
    );

    foreach ($feeds as $feed) {
        $counter++;
        // schedule every 10 mins
        $time = time() + (600 * $counter);
        wp_schedule_single_event( $time, \'wp1903_process_feed\', $feed );
    }
}

add_action(\'wp1903_process_feed\', \'wp1903_import_feed\');

function wp1903_import_feed($feed_url = \'\') {
    // do the import
}
必须只在激活挂钩上运行调度程序,否则在每次页面加载时,cron都会被重新调度。

SO网友:Mike Madern

您已尝试通过以下方式延长脚本的最大执行时间set_time_limit()? 这不会导致服务器崩溃(因为它也有内存限制):

set_time_limit( 0 ); // No time limit is imposed
我不知道你说的“分解”剧本是什么意思,你可能想再想一想。

如果feed的XML中有太多行,您可以做什么?您还可以创建自己的导入脚本,并通过逐个处理小部分来处理它。

$xml_handler = new ProductsParser();
$xml_parser  = xml_parser_create();

$source = \'--URL--\';

xml_set_object( $xml_parser, $xml_handler );
xml_parser_set_option( $xml_parser, XML_OPTION_CASE_FOLDING, false );
xml_set_element_handler( $xml_parser, \'startElement\', \'endElement\' );
xml_set_character_data_handler( $xml_parser, \'cdata\' );

$fp = fopen ( $source, \'r\' );
while ( $chunk = fread( $fp, 4096 ) ) {
  xml_parse( $xml_parser, $chunk, feof( $fp ) );
  flush();
}

fclose( $fp );

class ProductsParser {
  public $product; # Holds the record values
  public $elem_key; # Holds the current element key while reading
  public $record; # Holds the record tag

  function __construct( $args ) {
    $this->product  = false;
    $this->elem_key = false;
    $this->record   = \'--RECORD-NAME--\';
  }

  function startElement( $parser, $tag, $attributes ) {
    if ( $this->record == $tag && ! is_array( $this->product ) ) {
      $this->product = array();
    } elseif( is_array( $this->product ) ) {
      $this->elem_key = $tag;
    }
  }

  function endElement( $parser, $tag ) {
    if ( $this->record == $tag && is_array( $this->product ) ) {
      // Process the product row

      $this->product = false;
    } elseif ( is_array( $this->product ) && $this->elem_key != false ) {
      $this->elem_key = false;
    }
  }

  function cdata( $parser, $cdata ) {
    if ( is_array( $this->product ) && $this->elem_key != false ) {
      $this->product[$this->elem_key] = $cdata;
    }
  }
}
有关XML解析器的更多信息,请参阅PHP manual.

SO网友:Bainternet

当涉及到高执行时间脚本时,我通常使用ajax尽可能简单地将其拆分,因此下面是一个概念类,可以让您开始创建管理页面和ajaxed导入循环:

<?php
class Ajax_Import{

    public function __construct(){
        if(is_admin()){
            add_action(\'admin_menu\', array($this, \'add_plugin_page\'));
        }
        add_action(\'wp_ajax_do_feed_import\',array($this,\'do_import\'));
    }

    public function add_plugin_page(){
        // This page will be under "Settings"
        add_options_page(\'ajaxed Import\', \'ajaxed Import\', \'manage_options\', \'test-setting-admin\', array($this, \'create_admin_page\'));
    }

    public function create_admin_page(){
        wp_enqueue_script( \'jquery\');
        ?>
        <div class="wrap">
            <?php screen_icon(); ?>
            <h2><?php _e(\'AJAXed Import\'); ?></h2>          
            <table class="form-table">
                <tbody>
                    <th scope="row">
                        <label for="my-text-field"><?php _e(\'Feeds To Import\'); ?></label>
                    </th>
                    <td>
                        <textarea id="feeds"></textarea>
                        <br>
                        <span class="description"><?php _e(\'Enter Each feed in a new line.\'); ?></span>
                    </td>
                </tbody>
            </table>
            <p class="submit"><input type="submit" id="do_import" value="Save Changes" class="button-primary" name="Submit"></p>
            <div id="import_status" style="display:none"></div>
        </div>
        <?php
        $this->import_loop_js();
    }

    public function do_import(){
        //do your import here ex:
        $rss = fetch_feed(esc_url( $_POST[\'feed_url\']));
        if (!is_wp_error( $rss ) ) {
            $count = $rss->get_item_quantity(); 
            //do actuall import loop or whatever
            echo json_encode(array(\'message\' => \'<div id="message" class="success"><p>imported \' . $count . \' items from \'.esc_url( $_POST[\'feed_url\']).\'</p></div>\'));
        }else{
            echo json_encode(array(\'errors\' => \'<div id="message" class="error"><p>\' . $rss->get_error_message() . \'</p></div>\'));
        }
        die();
    }

    public function import_loop_js(){
        ?>
        <script type="text/javascript">
        jQuery(document).ready(function($){
            var ajax_import = (function(){
                var instantiated;
                var feeds;
                function init (){
                    return {
                        start_import: function(){

                            instantiated.feeds = $("#feeds").val().split(\'\\n\');
                            instantiated.update_status(\'\', true);
                            instantiated.next_feed();
                        },
                        make_ajax_call:function(feed){
                            data = {
                                action: "do_feed_import",
                                feed_url: feed
                            };
                            $.post( 
                                ajaxurl,
                                data, 
                                function(res){
                                    if (res.error){//add error message
                                        instantiated.update_status(res.error);
                                    }else{//add success message
                                        instantiated.update_status(res.message);
                                    }
                                    //call next feed
                                    instantiated.next_feed();
                                }, 
                                \'json\'
                            );
                        },
                        next_feed:function(){
                            if (instantiated.feeds.length > 0) {//if we have feeds in the list starts ajax calls
                                instantiated.make_ajax_call(instantiated.feeds.shift());
                            } else{
                                instantiated.update_status("all Done!!!");
                                $("#do_import").removeAttr("disabled");
                            }
                        },
                        update_status:function(m,clear){
                            clear = clear || false;
                            if (clear)
                                $("#import_status").html(\'\').show();
                            else
                                $("#import_status").append(m);
                        }
                    }
                }

                return {
                    getInstance :function(){
                        if (!instantiated){
                            instantiated = init();
                        }
                        return instantiated; 
                    }
                }
            })();
            $("#do_import").on(\'click\',function(){
                $(this).attr(\'disabled\',\'disabled\');
                ajax_import.getInstance().start_import();
            });
        });
        </script>
        <?php

    }
}

$Ajax_Import = new Ajax_Import();

结束

相关推荐

WordPress二十二主题中是否保留了Front-page.php模板?

我正在写我的第一个“十二个孩子”主题,遇到了(我认为)一个奇怪的怪癖。我修改了头版。php中有一个使用sliderjs的滑块,后来我决定不想将其用作首页模板,所以我更愿意将其称为其他页面的其他内容。令我惊讶的是,我重新命名头版的那一刻。php到文本旋转木马。php并将docblock中的模板名称更改为其他名称。页面将从全宽显示我的内容和下面的小部件更改为类似于我的博客的两列版本,但将小部件分配到首页。所以,这是头版。php十二年保留模板?是否可以将其外观复制到不同的模板中?以下是我的代码供参考:<?