You are viewing revision #7 of this wiki article.
This version may not be up to date with the latest version.
You may want to view the differences to the latest version.
Yii have a CJuiProgressBar, but it is static. If we want a dynamic progress bar to show the percentage or status, we have to do more things. I make it successfully and am glad to share it with you.
There are 6 files changed or added (to get zip file or any question,mail me by hehbhehb#163.com)
- 1 Component(or model) file
ProgressBar.php
<?php
class ProgressBar
{
private $key;
private $running;
private $total;
private $done;
public function __construct($key)
{
$this->key = $key;
}
public function start($total)
{
$this->running = 1;
$this->done = 0;
$this->total = $total;
$this->put();
}
public function stop()
{
$this->running = 0;
$this->put();
}
public function inc($step=1)
{
$this->done += $step;
$this->put();
}
public function put()
{
$ret = Yii::app()->cache->set($this->key, array('running'=>$this->running, 'total'=>$this->total, 'done'=>$this->done));
}
public static function get($key)
{
$test = 1;
//$test = 0;
if ($test)
{
$data = Yii::app()->cache->get($key);
if($data === false)
{
$data = array('running'=>1, 'total'=>119, 'done'=>0);
}
$data['done'] = $data['done'] + 10;
if ($data['done'] > 119)
{
$data['running'] = 0;
}
Yii::app()->cache->set($key, $data, 1*60);
return $data;
}
$data = Yii::app()->cache->get($key);
if($data === false)
{
$data = array('running' =>1, 'total'=>100, 'done'=>0);
}
return $data;
}
}
- 2 Controller files
MyController.php
<?php
class MyController extends Controller
{
public function actions()
{
return array(
'GetProgressBarData'=>array(
'class'=>'ActionGetProgressBarData',
),
);
}
public function actionBatchHandle()
{
...
if(isset($_POST))
{
$post = $_POST;
$id = uniqid();
$filename = Yii::app()->getRuntimePath().DIRECTORY_SEPARATOR."{$id}";
file_put_contents($filename, json_encode($post));
$command = 'php ' . Yii::app()->getBasePath().DIRECTORY_SEPARATOR.'yiic.php ' . "cli BatchHandle --id=$id > /dev/null 2>&1 &";
exec($command);
}
$this->render('form',array('model'=>$model));
}
}
ActionGetProgressBarData.php, which is also placed under /controllers directory
<?php
class ActionGetProgressBarData extends CAction
{
public function run($key)
{
$response = ProgressBar::get($key);
Util::set_expires(0);
echo json_encode($response);
}
}
?>
- 2 View files
form.php
<div class="form">
<?php $form=$this->beginWidget('CActiveForm', array(
'id'=>'form_id',
)); ?>
...
<div class="row buttons">
<?php echo CHtml::submitButton('Batch Process', array('name'=>'Batch')); ?>
<?php echo CHtml::hiddenField('progress_key', uniqid(), array('id'=>'progress_key')); ?>
</div>
<?php $this->endWidget(); ?>
</div>
<?php
$js_code=<<<EOD
jQuery('#form_id input[type=submit]').on('click', function() {
$('#progress_key').val(uniqid());
open_progress_bar();
return true;
});
EOD;
Yii::app()->getClientScript()->registerScript(__CLASS__.'#'.'form_id', $js_code);
?>
<?php
$this->widget('zii.widgets.jui.CJuiButton',array('name'=>'just_for_include_jqeuryui_css','htmlOptions'=>array('style'=>'display:none;')));
$this->renderPartial('VProgressBar'); // include the progress bar here, should we wrap it into a CJuiWidget?
?>
VProgressBar.php
<script type="text/javascript">
function open_progress_bar()
{
my_title = 'Processing, please wait...';
$('#modalDivProgress').dialog({
autoOpen: true,
width: 800,
height:150,
modal: true,
title: my_title
});
$("#progressbar").progressbar({value: 0});
show_progress();
}
function show_progress()
{
var url = '<?php echo Yii::app()->controller->createUrl("GetProgressBarData"); ?>';
var progress_key = $('#progress_key').val();
$.getJSON(url + "&key=" + progress_key, function(data) {
var done = parseInt(data.done);
var total = parseInt(data.total);
var percentage = Math.floor(100 * done / total);
if (percentage > 100)
percentage = 100;
$("#progressbar").progressbar( "value", percentage);
var percentage_txt = percentage + "%" + " [" + done + "/" + total + "]";
$("#percentage").text(percentage_txt);
if (percentage == 100) {
alert('Done');
$("#progressbar").progressbar( "destroy");
$("#modalDivProgress").dialog("close");
} else {
setTimeout("show_progress()", 5000);
}
});
}
function uniqid (prefix, more_entropy) {
// + original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
// + revised by: Kankrelune (http://www.webfaktory.info/)
// % note 1: Uses an internal counter (in php_js global) to avoid collision
// * example 1: uniqid();
// * returns 1: 'a30285b160c14'
// * example 2: uniqid('foo');
// * returns 2: 'fooa30285b1cd361'
// * example 3: uniqid('bar', true);
// * returns 3: 'bara20285b23dfd1.31879087'
if (typeof prefix === 'undefined') {
prefix = "";
}
var retId;
var formatSeed = function (seed, reqWidth) {
seed = parseInt(seed, 10).toString(16); // to hex str
if (reqWidth < seed.length) { // so long we split
return seed.slice(seed.length - reqWidth);
}
if (reqWidth > seed.length) { // so short we pad
return Array(1 + (reqWidth - seed.length)).join('0') + seed;
}
return seed;
};
// BEGIN REDUNDANT
if (!this.php_js) {
this.php_js = {};
}
// END REDUNDANT
if (!this.php_js.uniqidSeed) { // init seed with big random int
this.php_js.uniqidSeed = Math.floor(Math.random() * 0x75bcd15);
}
this.php_js.uniqidSeed++;
retId = prefix; // start with prefix, add current milliseconds hex string
retId += formatSeed(parseInt(new Date().getTime() / 1000, 10), 8);
retId += formatSeed(this.php_js.uniqidSeed, 5); // add seed hex string
if (more_entropy) {
// for more entropy we add a float lower to 10
retId += (Math.random() * 10).toFixed(8).toString();
}
return retId;
}
</script>
<div id="modalDivProgress" style="margin: 20px auto;">
<div id="progressbar" style="width:780px;"></div>
<div id="percentage" style="margin-top: -22px;margin-left:310px;"></div>
</div>
- 1 Command file CliCommand.php
<?php
class CliCommand extends CConsoleCommand
{
public function actionBatchHandle($id)
{
set_time_limit(0);
$filename = Yii::app()->getRuntimePath().DIRECTORY_SEPARATOR."{$id}";
$post = file_get_contents($filename);
$post = json_decode($post, true);
//$criteria = getCriteria($post);
...
$total = Yii::app()->db->getCommandBuilder()->createCountCommand('table_name', $criteria)->queryScalar();
$progress = new ProgressBar($post['progress_key']);
$progress->start($total);
$dataReader = Yii::app()->db->getCommandBuilder()->createFindCommand('table_name', $criteria)->query();
while(($row=$dataReader->read())!==false)
{
// process one record
...
$progress->inc();
}
$progress->stop();
unlink($filename);
}
}
Too good but .....plz provide Video tutorial as well
I like this tutorial but video can make well for YII popularity issue.
Please Tell where to put VProgressBar.php
and CliCommand.php in controller, views or model???
If you have any questions, please ask in the forum instead.
Signup or Login in order to comment.