<?php
require_once( dirname(__FILE__) . '/shared.php');
function tabelle_holen_hosters( $condition = "" ) {
global $wpdb;
$sql = "SELECT * FROM whatever" . $condition;
if( $table = $wpdb->get_results( $sql, ARRAY_A ) ) {
return $table;
} else {
echo "SQL ERROR in tabelle_holen()";
var_dump( $table );
return false;
}
}
$test = tabelle_holen_hosters( " WHERE working=1 AND alexacheck=0 LIMIT 200" );
?>
<table>
<tbody>
<?php
foreach ( $test as $row ){
$rank = (int) alexaRank( $row['hoster'] );
if ($rank == 0)
$rank = 999999999;
echo '<tr>';
echo '<td>' . $row['hoster_id'] . '</td>';
echo '<td>' . $row['hoster'] . '</td>';
echo '<td>' . $rank . '<td>';
echo '</tr>';
$wpdb->update(
'fhw_filehosters',
array(
'alexa' => $rank,
'alexacheck' => 1
),
array( 'hoster_id' => $row['hoster_id'] ),
array(
'%d',
'%d'
),
array( '%d' )
);
flush(); // <----- NOT working.
}
?>
</tbody>
</table>
<?php
function alexaRank( $url ) {
$request_url = "http://data.alexa.com/data?cli=10&url=".$url;
$xml = simplexml_load_file($request_url) or die("feed not loading");
return $xml->SD->POPULARITY['TEXT'];
}
我有这个脚本,我使用wordpress数据库类没有wordpress。我将行限制为200,因为否则我会遇到像页面加载需要数年的问题,也许php执行时间从alexa函数的xml需要很长时间。数据库中有很多url需要检查,我想用一个动作全部更新,也就是删除200限制。我要怎么做才能让它一次做50个,然后输出,然后继续?Ajax吗?我该怎么做呢?更新1:正如我在评论中所说的,我正在寻找一些东西来使这种情况发生(在后台)我的网站,我实际上不太确定是否涉及php执行时间限制在这一点上,但对于"一次性"的解决方案,我只是在队列结束时测试了flush(),它不工作!
但是我正在寻找一个例程函数,现在我更新了问题,答案是非常通用的,我不是那个经验。我很想看到一些实际的代码。如果这太多了,并倾向于"给我写一个程序",那么我必须通过挖掘一些时间来弄清楚这一点。那么我就接受最有效的答案。
您的直接问题(如何在脚本运行时开始输出)很容易回答:
flush();
但是如果PHP的执行时间限制了你,那么这并不能解决你的问题。那么剩下的就是AJAX:
- 将脚本分成两个文件:一个带有空
<table>
和JavaScript,另一个将通过AJAX调用,执行实际处理并返回表行。 - 像这样限制处理的行数:
LIMIT $start, 50
,其中$start
通过GET/POST参数 提供 - 在JavaScript中,首先调用start=0的PHP脚本,然后在处理完响应后,再次调用start增加50。重复,直到响应为空。
首先将工作与基础和前端代码分开,所以:
-
ajax.getdata.php//这里我们根据给定的参数获取数据
$page = $_GET["page"]; // I skip the validation, you should do it be yourself require_once( dirname(__FILE__) . '/shared.php'); function tabelle_holen_hosters( $condition = "" ) { global $wpdb; $sql = "SELECT * FROM whatever" . $condition; if( $table = $wpdb->get_results( $sql, ARRAY_A ) ) { return $table; } else { echo "SQL ERROR in tabelle_holen()"; var_dump( $table ); return false; } } function alexaRank( $url ) { $request_url = "http://data.alexa.com/data?cli=10&url=".$url; $xml = simplexml_load_file($request_url) or die("feed not loading"); return $xml->SD->POPULARITY['TEXT']; } $limit = 200; $start= $page*$limit; $test = tabelle_holen_hosters( " WHERE working=1 AND alexacheck=0 LIMIT $start,$limit" ); $str = '<table>'; foreach ( $test as $row ){ $rank = (int) alexaRank( $row['hoster'] ); if ($rank == 0) $rank = 999999999; $str.= '<tr>'; $str.= '<td>' . $row['hoster_id'] . '</td>'; $str.= '<td>' . $row['hoster'] . '</td>'; $str.= '<td>' . $rank . '<td>'; $str.= '</tr>'; $wpdb->update( 'fhw_filehosters', array( 'alexa' => $rank, 'alexacheck' => 1 ), array( 'hoster_id' => $row['hoster_id'] ), array( '%d', '%d' ), array( '%d' ) ); } $str.='</table>'; echo $str; exit; ?>
-
index.html//构建前端视图,并向服务器发送ajax请求。
<div id="content"> </div> <div id="controls"> <span onCLick="goPrev()"> Prev </span> <span onCLick="goNext()"> Next </span> </div> <script> var page=0; //this functions can be moved to separate file function goNext(){ page++; //here should be some limit for max page readData(); } function goPrev(){ if(page==0) return false; page--; readData(); } function readData(){ $.ajax({ "url":"/path/to/ajax.getdata.php?page="+page, }).done(function(data){ $("#content").html(data); }); } readData(); </script> </body> </html>
所以现在你可以定义自己有多少记录在一个时间你会显示,并可以去下一页或上一页的控制点击。
如果你只是想更新行,你想知道哪些项目被更新了,你不需要一个web服务器。您可以使用logger -> KLogger将更新信息写入磁盘,而不是'echo'。在这种情况下,使用PHP CLI具有优势。可以设置max_execution_time(0)并增加memory_limit。此外,我认为它比使用apache或nginx快一点。你想批量更新吗?看看这篇文章。或者,您可以使用MySQL。如果在工作和alexacheck上有很多不同的状态,不要忘记对它们进行索引。
像这样长时间运行的进程可能是作业队列的候选者。
- 一次将50个url排队到一个队列。
- 让每个作业队列worker在完成后将结果发送到主应用程序。
- 你的应用程序将在结果从队列进入时处理结果的显示。
这些都应该异步完成。
当应用程序进入"维护"模式时。您仍然可以使用相同的作业队列。就像前面提到的一个评论一样,您甚至可以有一个cron作业,它每天向队列发送两次作业。
你应该这样考虑:
- 创建一个大的上帝母亲循环。 保留一个$total计数器和一个$temp计数器。
- 循环迭代100 (n)次,每次增加计数器。
- 一旦你达到100个数字限制(或50或200或其他),你重置温度计数器。
- 你让程序进入睡眠3秒(或类似的东西)。
- 你再次迭代n次temp变量,但你请求的数据与$total计数器相对应。
或
- 创建一个大的上帝母亲循环。
- 有一个计数器
- 在每次循环迭代中增加计数器。 一旦计数器达到你定义的最大值,你重置它。睡眠
- 。
- 重复。
都有利润
现在,由于您需要一些代码和一些解释:
PHP手册说:
int sleep ( int $seconds )
"Delays the program execution for the given number of seconds."
所以程序的执行是延迟的,如果你延迟了执行时间,你就不能达到限制。
你可以这样写:
$i = 0;
$max = 50;
$sleepTime = 3;
foreach ( $test as $row ){
$rank = (int) alexaRank( $row['hoster'] );
if ($rank == 0)
$rank = 999999999;
echo '<tr>';
echo '<td>' . $row['hoster_id'] . '</td>';
echo '<td>' . $row['hoster'] . '</td>';
echo '<td>' . $rank . '<td>';
echo '</tr>';
$wpdb->update('fhw_filehosters', array(
'alexa' => $rank,
'alexacheck' => 1
),
array(
'hoster_id' => $row['hoster_id']
),
array(
'%d',
'%d'
),
array( '%d' )
);
ii($i === $max)
{
$i = -1;
sleep($sleepTime);
}
$i++;
}
至少尝试一下,最好的学习方法是实验。
我通常使用ob_start和ob_flush函数。
另一种思考方式是:是否只能为访问站点的单个用户更新某些行?为了给人一种正在更新的错觉。
在网络浏览器游戏中,这种情况非常普遍。它们给人一种一切都是最新的错觉,但实际上只是玩家的信息被更新了。
或者你可以看看你的服务器主机是否有一个"预定脚本"的选项,我知道一些允许这样做。它将触发脚本在一天的间隔或特定时间运行。