我正在创建一个能够通过浏览器远程查看记录和报告的应用程序。我已经使用cakePHP来使应用程序和它的工作正常,但我有一个小问题,因为应用程序不执行任何插入它只是读取数据,我想当用户打开一个视图并且已插入记录该表,它应该更新所有打开的客户端,而不是用户刷新页面以获取新记录。 是否有一个cakePHP websocket插件实际上有效吗? 我们的webhost不允许安装程序或添加apache模块,因此nodejs或类似的解决方案不适用于此。
我正在寻找一个纯粹的php和javascript实现 只需将您的应用程序文件上传到Web服务器即可 运行。你不必运行,安装额外的东西或对apache或东西进行任何配置......在上传文件之后
这是我的一个控制器(BooksController.php)中的一个函数,它将数据检索到视图
public function list_books()
{
$this->Books->recursive = 0;
$this->paginate = array('order' => array('Serial_No' => 'DESC'));
$this->set('All_Books', $this->paginate());
}
这是我的一个视图(list_books.ctp),它在分页的表中显示数据。
<div class="row-fluid">
<div class="span12">
<?php echo $this->Session->flash() ?>
<h4><?php echo __('All Books') ?></h4>
<hr>
<table class="table table-bordered">
<thead>
<tr> <th><?php echo __('Serial No') ?></th>
<th><?php echo __('Title') ?></th>
<th><?php echo __('Author') ?></th>
<th><?php echo __('Publisher') ?></th>
<th><?php echo __('Category') ?></th>
<th><?php echo __('Section') ?></th>
<th><?php echo __('Available') ?></th>
</tr>
</thead>
<tbody>
<?php foreach( $All_Books as $book ){ ?>
<tr>
<td><?php echo $this->Html->link(__($book['Book']['Serial_No']),'/books/view/'.$book['Book']['Serial_No']) ?></td>
<td><?php echo $book['Book']['Title'] ?></td>
<td><?php echo $book['Book']['Author'] ?></td>
<td><?php echo $book['Book']['Publisher'] ?></td>
<td><?php echo $book['Book']['Category'] ?></td>
<td><?php echo $book['Book']['Section'] ?></td>
<td><?php echo $book['Book']['Available'] ?></td>
</tr>
<?php } ?>
</tbody>
</table>
<?php echo $this->Paginator->prev('« Previous', null, null, array('class' => 'disabled'));
echo $this->Paginator->numbers();
echo $this->Paginator->next('Next »', null, null, array('class' => 'disabled'));
echo $this->Paginator->counter(array(
'format' => 'Page {:page} of {:pages}, showing {:current} records out of
{:count} total, starting on record {:start}, ending on {:end}'
));
?>
</div>
</div>
我可以在视图或控制器或模型上添加什么,以使视图自动更新? 这可以用ajax实现吗?
答案 0 :(得分:0)
您可以使用AJAX轮询器或(HTML5)websockets(例如使用Pusher)进行推送通知。
答案 1 :(得分:0)
你已经提到过它,AJAX。这是完成此类操作的最简单方法,只需通过AJAX在后台进行检查,并在必要时重新加载页面,或者再次使用AJAX请求更新受影响的部分。
根据数据量,您当然可以直接加载数据,而不是先检查更新。
更新我误解了这个问题,如果插入/ udpates来自您没有直接控制的外部来源,如评论中所述,我可以选择的唯一选项考虑检查是否有必要更新视图,将检查UPDATE_TIME
information schema(仅适用于MyISAM),使用triggers更新可以检查的自定义信息模式,或者计算行数,但后者只会覆盖插入行。
所有方法都将获取特定视图的控制器操作中的比较值(更新时间或行数),并将该值传递给随后在AJAX调用中使用的视图。 AJAX调用调用一个控制器方法,将传递的值与当前时间/计数值进行比较,以确定是否需要更新。
请注意,这些示例未经测试!
最简单的方法是检查UPDATE_TIME
信息架构,但是如上所述,这仅适用于MyISAM表:
<强>型号:强>
public function getUpdateTime()
{
$db = $this->getDataSource();
$result = $db->fetchAll('
SELECT
UNIX_TIMESTAMP(UPDATE_TIME) AS update_time
FROM
information_schema.tables
WHERE
TABLE_SCHEMA = ?
AND
TABLE_NAME = ?',
array
(
$db->config['database'],
$this->table
)
);
if(empty($result) || !isset($result[0][0]['update_time']))
{
return false;
}
return (int)$result[0][0]['update_time'];
}
<强>控制器:强>
public function list_books()
{
$this->set('lastUpdate', $this->Books->getUpdateTime());
$this->Books->recursive = 0;
$this->paginate = array('order' => array('Serial_No' => 'DESC'));
$this->set('All_Books', $this->paginate());
}
public function checkForUpdate($time)
{
$updateNecessary = $this->Books->getUpdateTime() > (int)$time;
return new CakeResponse(array('body' => json_encode($updateNecessary)));
}
查看:强>
<script>
jQuery(function($)
{
var lastUpdate = <?php echo $lastUpdate; ?>;
function checkForUpdate()
{
$.get('/books/checkForUpdate', {time: lastUpdate}, function(updateNecessary)
{
if(updateNecessary === true)
{
alert('update necessary');
// now reload the page or use an additional AJAX request for updating the content
}
else
{
queueUpdateCheck();
}
},
'json');
}
function queueUpdateCheck()
{
setTimeout(checkForUpdate, 5000);
}
queueUpdateCheck();
});
</script>
另一种选择是使用triggers。您需要一个额外的表来连接表和时间值,例如使用表名和两个触发器,一个用于插入,一个用于更新。然后,这些触发器可以更新自定义信息表。
信息表
CREATE TABLE IF NOT EXISTS `table_stats` (
`table_name` varchar(255) NOT NULL,
`update_time` datetime NOT NULL,
PRIMARY KEY (`table_name`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
INSERT INTO `table_stats` (`table_name`, `update_time`)
VALUES ('books', NOW());
<强>触发器强>
CREATE TRIGGER `update_time_after_insert` AFTER INSERT ON `books`
FOR EACH ROW
UPDATE `table_stats` SET `update_time` = NOW() WHERE `table_name` = 'books';
CREATE TRIGGER `update_time_after_update` AFTER UPDATE ON `books`
FOR EACH ROW
UPDATE `table_stats` SET `update_time` = NOW() WHERE `table_name` = 'books';
<强>型号:强>
public function getUpdateTime()
{
$db = $this->getDataSource();
$result = $db->fetchAll('
SELECT
UNIX_TIMESTAMP(update_time) AS update_time
FROM
`table_stats`
WHERE
`table_name` = ?',
array
(
$this->table
)
);
if(empty($result) || !isset($result[0][0]['update_time']))
{
return false;
}
return (int)$result[0][0]['update_time'];
}
控制器和查看与上一个示例相同。
现在最后一个选项是比较行数,这当然只适用于插入。在此示例中,模型将保持不变。
<强>控制器:强>
public function list_books()
{
$this->set('rowCount', $this->Books->find('count'));
$this->Books->recursive = 0;
$this->paginate = array('order' => array('Serial_No' => 'DESC'));
$this->set('All_Books', $this->paginate());
}
public function checkForUpdate($rowCount)
{
$updateNecessary = $this->Books->find('count') != (int)$rowCount;
return new CakeResponse(array('body' => json_encode($updateNecessary)));
}
查看:强>
<script>
jQuery(function($)
{
var rowCount = <?php echo $rowCount; ?>;
function checkForUpdate()
{
$.get('/books/checkForUpdate', {rowCount: rowCount}, function(updateNecessary)
{
if(updateNecessary === true)
{
alert('update necessary');
// now reload the page or use an additional AJAX request for updating the content
}
else
{
queueUpdateCheck();
}
},
'json');
}
function queueUpdateCheck()
{
setTimeout(checkForUpdate, 5000);
}
queueUpdateCheck();
});
</script>
当然,您也可以提交可能的数据以及更新检查,以避免其他请求。例如:
<强>模型强>
public function checkForUpdate($time)
{
$data = '';
$updateAvailable = $this->Books->getUpdateTime() > (int)$time;
if($updateAvailable)
{
$this->set('books', $this->Books->find('all'));
// render /Elements/books.ctp in ajax.ctp layout and grab the rendered content
$this->viewPath = 'Elements';
$view = $this->render('books', 'ajax');
$data = $view->body();
}
$body = compact('updateAvailable', 'data');
return new CakeResponse(array('body' => json_encode($body)));
}
查看强>
<script>
jQuery(function($)
{
var lastUpdate = <?php echo $lastUpdate; ?>;
function checkForUpdate()
{
$.get('/books/checkForUpdate', {time: lastUpdate}, function(response)
{
if(response.updateAvailable === true)
{
// the data is already available, so directly update the content
$('#content').html(response.data);
}
queueUpdateCheck();
},
'json');
}
function queueUpdateCheck()
{
setTimeout(checkForUpdate, 5000);
}
queueUpdateCheck();
});
</script>