CakePHP允许使用API​​按字段搜索?

jrq*_*ick 5 php cakephp cakephp-3.0

我正在尝试使用CakePHP创建一个允许搜索的API.例如:

http://localhost:8765/users/index/?username=admin
Run Code Online (Sandbox Code Playgroud)

哪个应该返回用户名等于'admin'的用户:

users: [
   {
      id: 3,
      username: "admin",
      image: "",
      firstName: "Jeremy",
      lastName: "Quick",
      userTypeId: 1,
      email: "jrquick@test.com",
      groupId: 2
   }
]
Run Code Online (Sandbox Code Playgroud)

到目前为止,我已经能够通过AppController中的自定义get()来完成此操作,该自定义get()检查模型上字段的$ _GET和$ _POST数组.但随着我添加更多功能(范围搜索,集合搜索和子表过滤),该功能变得越来越复杂,并且越来越复杂.是否有更好的,更CakePHP友好的方式来实现这一目标?无论是通过纯蛋糕还是插件?

jrq*_*ick 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;
}
Run Code Online (Sandbox Code Playgroud)