我正在尝试使用允许搜索的CakePHP创建API。例如:
http://localhost:8765/users/index/?username=admin
哪些用户名应该返回用户名等于' admin':
users: [
{
id: 3,
username: "admin",
image: "",
firstName: "Jeremy",
lastName: "Quick",
userTypeId: 1,
email: "jrquick@test.com",
groupId: 2
}
]
到目前为止,我已经能够通过AppController中的自定义get()来完成此操作,它会检查模型中字段的$ _GET和$ _POST数组。但随着我添加更多功能(范围搜索,集合搜索和子表过滤),该功能变得越来越复杂,并且越来越复杂。是否有更好的,更CakePHP友好的方式来实现这一目标?无论是通过纯蛋糕还是插件?
答案 0 :(得分:1)
我想你想使用Cakephp搜索插件。它具有良好的文档,并使用类似于您当前使用的PRG方法。它将通过API正常运行。这是指向该插件的链接:github.com/FriendsOfCake/search
答案 1 :(得分:0)
如果您想创建API,首先应创建一个MiddleWare,它会过滤令牌,密钥等,以使您的API受到更多保护。 此外,您应该使用Plugins和RESTful Routes,这将非常有帮助。
创建插件:
bin/cake bake plugin Api
创建模型:
bin/cake bake model Users
例如,您希望在Api插件中使用UsersController:
<?php
namespace Api\Controller;
/* This controller will be extending like parent */
use Api\Controller\AppController;
use Api\Model\Table\UsersTable;
/**
* Class UsersController
* @package Api\Controller
* @property UsersTable $Users
*
*/
class UsersController extends AppController{
public function initialize(){
parent::initialize();
$this->loadModel('Api.Users');
}
public function getUser($field ='username', $username = false){
return $this->_jsonResponse(
[
'users' => $this->Users->findBy{ucfirst($field)}($username)
];
)
}
public function _jsonResponse($data, $code = 200){
$this->response->type('json');
$this->response->statusCode($code);
$this->response->body(
json_encode((array)$data)
);
return $this->response;
}
}
路线将在plugins/config/routes.php
中进行描述。您需要在/api
路径中为API创建路线图:
function (RouteBuilder $routes) {
$routes->resources('Users', [
'map' => [
'get-user' => [
'action' => 'getUser',
'method' => 'GET' /* Can be also as array ['GET', 'PUT', 'DELETE'] */
]
]
]);
$routes->fallbacks('DashedRoute');
}
如果您经常接听电话,则应使用Cache来拨打并保存一段时间。例如 - 10 minutes
。可以在config/app.php
中配置缓存。您应该创建单独的Cache前缀并以这种方式使用它:
<?php
use Cake\Cache\Cache;
$data = [];
Cache::write('some_key', $data, 'prefix')
dump(Cache::read('some_key', 'prefix'));
这只是一个例子。如果您将遇到一些问题 - 请在评论中说明:)
另外,使用Migrations和Seeds代替转储sql文件
如果您想过滤来自中间件的数据 - 您应该有Event作为参数,它将包含请求数据($_POST
)和请求查询($_GET
)变量您将成为能够轻松处理。
来自控制器您需要使用$this->request->data
获取POST
数据数组或$this->request->query
获取GET
数据数组。
答案 2 :(得分:0)
我还没有找到一个似乎可以正常工作的答案,所以这是我当前的get命令。它允许按字段搜索,连接表,大于/小于,在数组中等。
如果有人提出改进建议,我会更新我的答案。
public function get() {
$response = new Response();
$model = $this->loadModel();
$fields = $this->getFields();
$joins = $this->getJoins();
$order = $this->getOrder();
$params = $this->getParams();
$limit = $this->getLimit();
$offset = $this->getOffset();
$query = $model->find('all', ['fields' => $fields]);
if (!is_null($joins)) {
$query->contain($joins);
}
if (sizeof($params['equals']) > 0) {
foreach ($params['equals'] as $equalsKey=>$equalsValue) {
$query->andWhere([$equalsKey => $equalsValue]);
}
}
if (sizeof($params['or']) > 0) {
foreach ($params['or'] as $orKey=>$orValue) {
$query->orWhere([$orKey => $orValue]);
}
}
if (!is_null($order)) {
$query->order([$order]);
}
if (!is_null($limit)) {
$query->limit($limit);
if (!is_null($offset)) {
$query->offset($offset);
}
}
$response->addMessage($model->table(), $query->toArray());
$response->respond($this);
}
private function getFields() {
$fields = [];
if (array_key_exists('fields', $_GET)) {
$fields = explode(',', $_GET['fields']);
}
return $fields;
}
private function getLimit() {
$limit = null;
if (array_key_exists('limit', $_GET)) {
$limit = $_GET['limit'];
}
return $limit;
}
private function getJoins() {
$joins = null;
if (array_key_exists('joins', $_GET)) {
$joins = explode(',', $_GET['joins']);
}
return $joins;
}
private function getOffset() {
$offset = null;
if (array_key_exists('offset', $_GET)) {
$offset = $_GET['limit'];
}
return $offset;
}
private function getOrder() {
$results = [];
if (array_key_exists('order', $_GET)) {
$orders = explode(',', $_GET['order']);
foreach ($orders as $order) {
$sign = substr($order, 0, 1);
$direction = 'ASC';
if (in_array($sign, ['+', '-'])) {
if ($sign === '-') {
$direction = 'DESC';
}
$order = substr($order, 1);
}
$result = $order;
if (strpos($result, '.') === false) {
$result = $this->loadModel()->alias() . '.' . $order;
}
$result = $result . ' ' . $direction;
$results[] = $result;
}
}
return (sizeof($results) == 0) ? null : implode(',', $results);
}
private function getParams() {
$params = [
'equals' => [],
'or' => []
];
$parentModel = $this->loadModel();
$array = array_merge($_GET, $_POST);
foreach ($array as $field=>$value) {
$comparisonType = 'equals';
$operator = substr($field, strlen($field) - 1);
if (in_array($operator, ['!', '>', '<'])) {
$field = substr($field, 0, strlen($field) - 1);
$operator .= '=';
} else if (in_array($operator, ['|'])) {
$field = substr($field, 0, strlen($field) - 1);
$comparisonType = 'or';
$operator = '=';
} else if (in_array($operator, ['%'])) {
$field = substr($field, 0, strlen($field) - 1);
$operator = 'LIKE';
$value = '%'.$value.'%';
} else {
$operator = '=';
}
if ($value == 'null') {
$operator = (strpos($operator, '!') === false) ? 'IS' : 'IS NOT';
$value = null;
}
$field = str_replace('_', '.', $field);
if (strpos($field, '.') === false) {
$alias = $parentModel->alias();
} else {
$fieldExplosion = explode('.', $field);
$alias = $fieldExplosion[0];
$field = $fieldExplosion[1];
}
$model = null;
if ($parentModel->alias() !== $alias) {
$association = $parentModel->associations()->get($alias);
if (!is_null($association)) {
$model = $this->loadModel($association->className());
}
} else {
$model = $parentModel;
}
if (!is_null($model)) {
if ($model->hasField(rtrim($field, 's')) && !$model->hasField($field)) {
$field = rtrim($field, 's');
$value = '(' . $value . ')';
$operator = ' IN';
}
if ($model->hasField($field)) {
$params[$comparisonType][$alias.'.'.$field . ' ' . $operator] = $value;
}
}
}
return $params;
}