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);
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);
}
}
User Contributed Notes 2
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???
Leave a comment
If you have any questions, please ask in the forum instead.
Join the conversation to share a note.