php [cakephp:API组件和控制器]用于ajax请求和Server-Sent事件的Cake模块。 #cakephp
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了php [cakephp:API组件和控制器]用于ajax请求和Server-Sent事件的Cake模块。 #cakephp相关的知识,希望对你有一定的参考价值。
<?php
// ApisController
namespace App\Controller\Api;
use App\Controller\AppUsersController;
use Cake\Event\Event;
class ApisController extends AppUsersController
{
/**
* Initialize method
* Add loading components.
*/
public function initialize() {
parent::initialize();
$this->loadComponent('Api');
}
/**
* Response status
* @param void
* @return Cake\Http\Response (json)
*/
public function status() {
return $this->Api->printJsonResponse([
'debug_mode' => DEBUG_MODE,
'request' => $this->request->url,
'authority' => $this->Auth->user(),
]);
}
}
// HogeController (extends ApisController)
namespace App\Controller\Api;
use App\Controller\Api\ApisController;
use Cake\ORM\TableRegistry;
use Cake\Datasource\ConnectionManager;
class QueuesController extends ApisController
{
/**
* Pull method
*/
public function pull() {
if ($this->request->is('get')) {
$queues = $this->Queues->find()
->where([/* conditions */])
->toArray();
return $this->Api->printJsonResponse($queues);
}
}
/**
* Fetch (server-push) method
*/
public function fetch() {
$this->Api->printFetchHeader();
$connection = ConnectionManager::get('default');
while (true) {
$queues = $this->Queues->find()
->where(['is_fetched' => false]);
if ($queues->count()) { /* State change event occurred. */
try { /* Flagging to queues as fetched, then send event. */
foreach ($queues as $queue) { /* Flagging loop. */
$tmpQueue = $this->Queues->patchEntity($queue, ['is_fetched' => true]);
if (!$this->Queues->save($tmpQueue)) throw new \Exception('Failed to save fetched records.');
}
$connection->commit();
$this->Api->printFetchEvent($queues, 'push', WAIT);
} catch (\Exception $e) { /* Print error and rollback. */
$connection->rollback();
$this->Api->printFetchEvent($e->getMessage(), 'error', WAIT);
}
} else {
$this->Api->printFetchEvent('Polling is alive.', 'ping', WAIT);
}
}
}
}
namespace App\Controller\Component;
use Cake\Controller\Component;
use Cake\Controller\ComponentRegistry;
use Cake\Network\Exception\BadRequestException;
/**
* Application Api Component
* Base component for application apis.
*/
class ApiComponent extends Component
{
/**
* Properties
* Set in initialize method.
*/
public $controller;
public $request;
public $debug = 'Print in response on debug mode.';
/**
* Initialize method
* @param array $config
* @return void
*/
public function initialize(array $config) {
$this->controller = $this->_registry->getController();
$this->request = $this->controller->request;
}
/**
* Startup method
* - Set controller properties (view / response).
* - Detection bad request without authority.
* @param void
* @return Cake\Http\Response (json) (on failure)
*/
public function startup() {
$this->controller->autoRender = false;
$this->controller->response = $this->controller->response->withCharset(ENCODING);
if ($this->request->action == 'fetch') { /* event-stream request */
if (!$this->controller->Auth->user()) return $this->printError(403);
} else { /* ajax push & pull request */
$this->controller->response = $this->controller->response->withType('application/json');
if ( /* remove this in debug by DHC REST Client */
!$this->controller->Auth->user() ||
!$this->controller->request->is('ajax') ||
strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) != 'xmlhttprequest'
) return $this->printError(403);
}
}
/**
* Print JSON Response
* Set & Print response as JSON
* @param array | null $results
* @param int $code
* @param string $message
* @return Cake\Http\Response (json)
*/
public function printJsonResponse(
array $results = null,
int $code = null,
string $message = null
) { /* Print response hash as JSON */
if ($status = !empty($results)) {
$code ?? $code = 200;
$message ?? $message = 'Api is working.';
} else {
$code ?? $code = 404;
$message ?? $message = 'Results not found.';
}
$response = [
'status' => $status,
'code' => $code,
'message' => $message,
'results' => $results,
];
if (DEBUG_MODE) $response += ['debug' => $this->debug];
$this->controller->response = $this->controller->response->withStringBody(json_encode(compact('response')));
return $this->controller->response;
}
/**
* Print error
* Print response as JSON for illegal access.
* @param int $code
* @param string $message
*/
public function printError(int $code=500, string $message='') {
if (empty($message)) $message = 'Failed to api access.';
return $this->printJsonResponse(null, $code, $message);
}
/**
* Methods for Server-Sent Events in $this->controller->fetch()
* @see https://gist.github.com/a08b20aea47f509d8947e6bb63dcb9e3
*/
public function printFetchHeader() {
header("Content-Type: text/event-stream\n");
header("Cache-Control: no-cache\n");
}
public function printFetchEvent($data, string $event='message', int $sleep=1) {
$print = "event: ".$event."\n";
if (is_array($data) || is_object($data)) {
$print .= "data: ".json_encode($data)."\n\n";
} else {
$print .= "data: ".$data."\n\n";
}
echo $print;
ob_flush();
flush();
session_write_close(); //important!
sleep($sleep);
}
public function printFetchFlush(int $sleep=1) {
ob_flush();
flush();
session_write_close(); //important!
sleep($sleep);
}
}
以上是关于php [cakephp:API组件和控制器]用于ajax请求和Server-Sent事件的Cake模块。 #cakephp的主要内容,如果未能解决你的问题,请参考以下文章