每次在db表中插入记录时更新CakePhp View

我正在制作一个能够通过浏览器远程查看记录和报告的应用程序。 我已经使用cakePHP来使应用程序和它的工作正常,但我有一个小问题,因为应用程序不执行任何插入它只是读取数据,我想当用户打开一个视图并且已插入记录该表,它应该更新所有打开的客户端,而不是用户刷新页面以获取新记录。 是否有一个cakePHP websocket插件实际上有效吗? 我们的webhost不允许安装程序或添加apache模块,因此nodejs或类似的解决方案不适用于此处。

我正在寻找一个纯粹的php和javascript实现,你只需将你的应用程序文件上传到网络服务器,一切都在运行。 你不必运行,安装额外的东西或对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),它在分页的表中显示数据。

 
Session->flash() ?>


Html->link(__($book['Book']['Serial_No']),'/books/view/'.$book['Book']['Serial_No']) ?>
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}' )); ?>

我可以在我的视图或控制器或模型上添加什么,以使视图自动更新? 这可以用ajax实现吗?

您可以使用AJAX轮询器或(HTML5)websockets(例如使用Pusher )进行推送通知。

你已经提到过它,AJAX。 这是完成类似操作的最简单方法,只需通过AJAX在后台进行检查,并在必要时重新加载页面,或者再次使用AJAX请求更新受影响的部分。

根据数据量,您当然可以直接加载数据,而不是先检查更新。

更新我误解了这个问题,如果插入/ udpates是由一个你没有直接控制的外部源,如评论中所描述的那样,我可以想到的唯一选择是检查是否有必要更新视图,检查UPDATE_TIME 信息模式 (仅适用于MyISAM),使用触发器更新可以检查的自定义信息模式,或计算行数,但后者仅覆盖插入。

所有方法都将获取特定视图的控制器操作中的比较值(更新时间或行计数),并将该值传递给视图,然后在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))); } 

视图:

  

使用触发器

另一种选择是使用触发器 。 您需要一个额外的表来连接表和时间值,例如使用表名和两个触发器,一个用于插入,一个用于更新。 然后,这些触发器可以更新自定义信息表。

信息表

 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']; } 

ControllerView与前一个示例中的相同。


计数行

现在最后一个选项是比较行数,这当然只适用于插入。 在这个例子中, 模型将保持不变。

控制器:

 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))); } 

视图:

  

检索数据以及更新检查

当然,您也可以提交可能的数据以及更新检查,以避免其他请求。 例如:

模型

 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))); } 

视图