api - Yii2 REST 查询

标签 api rest yii2

嗨。
我有一个扩展 yii\rest\ActiveController 的 ProductController。
问题是我如何通过 HTTP GET 请求进行查询。

喜欢:http://api.test.loc/v1/products/search?name=iphone

并且返回对象将包含名称为 iphone 的所有产品。

最佳答案

更新:2016 年 4 月 29 日

这是一种比我在上一次更新中介绍的方法更简单的方法。它总是涉及搜索 生成的类gii .我喜欢用它在一个地方定义和维护所有与搜索相关的逻辑,比如使用自定义场景、处理验证或在过滤过程中涉及相关模型(如 example)。所以我要回到我的第一个答案:

public function actions() 
{ 
    $actions = parent::actions();
    $actions['index']['prepareDataProvider'] = [$this, 'prepareDataProvider'];
    return $actions;
}

public function prepareDataProvider() 
{
    $searchModel = new \app\models\ProductSearch();    
    return $searchModel->search(\Yii::$app->request->queryParams);
}

然后确保您的搜索类使用 load($params,'')而不是 load($params)或者将其添加到 型号 类(class):
class Product extends \yii\db\ActiveRecord
{
    public function formName()
    {
        return '';
    }

这应该足以让您的请求看起来像:

/products?name=iphone&status=available&sort=name,-price

更新:2015 年 9 月 23 日

这是相同的方法,但通过实现完整和更清洁的解决方案:
namespace app\api\modules\v1\controllers;

use yii\rest\ActiveController;
use yii\helpers\ArrayHelper;
use yii\web\BadRequestHttpException;

class ProductController extends ActiveController
{
    public $modelClass = 'app\models\Product';
    // Some reserved attributes like maybe 'q' for searching all fields at once 
    // or 'sort' which is already supported by Yii RESTful API
    public $reservedParams = ['sort','q'];

    public function actions() {
        $actions = parent::actions();
        // 'prepareDataProvider' is the only function that need to be overridden here
        $actions['index']['prepareDataProvider'] = [$this, 'indexDataProvider'];
        return $actions;
    }

    public function indexDataProvider() {
        $params = \Yii::$app->request->queryParams;

        $model = new $this->modelClass;
        // I'm using yii\base\Model::getAttributes() here
        // In a real app I'd rather properly assign 
        // $model->scenario then use $model->safeAttributes() instead
        $modelAttr = $model->attributes;

        // this will hold filtering attrs pairs ( 'name' => 'value' )
        $search = [];

        if (!empty($params)) {
            foreach ($params as $key => $value) {
                // In case if you don't want to allow wired requests
                // holding 'objects', 'arrays' or 'resources'
                if(!is_scalar($key) or !is_scalar($value)) {
                    throw new BadRequestHttpException('Bad Request');
                }
                // if the attr name is not a reserved Keyword like 'q' or 'sort' and 
                // is matching one of models attributes then we need it to filter results
                if (!in_array(strtolower($key), $this->reservedParams) 
                    && ArrayHelper::keyExists($key, $modelAttr, false)) {
                    $search[$key] = $value;
                }
            }
        }

        // you may implement and return your 'ActiveDataProvider' instance here.
        // in my case I prefer using the built in Search Class generated by Gii which is already 
        // performing validation and using 'like' whenever the attr is expecting a 'string' value.
        $searchByAttr['ProductSearch'] = $search;
        $searchModel = new \app\models\ProductSearch();    
        return $searchModel->search($searchByAttr);     
    }
}

现在您的 GET 请求将如下所示:

/products?name=iphone

或者甚至喜欢:

/products?name=iphone&status=available&sort=name,-price
  • 注:

    如果不是 /products?name=iphone你正在寻找一个特定的
    处理搜索或过滤请求的操作,例如:

    /products/search?name=iphone

    然后,在上面的代码中,您需要 删除 Action 功能及其所有内容:
    public function actions() { ... }

    重命名 :indexDataProvider()actionSearch()
    & 最后 添加 'extraPatterns' => ['GET search' => 'search']到您的 yii\web\UrlManager::rules 描述
    在@KedvesHunor 的回答中。


  • 原答案:2015 年 5 月 31 日

    有一个简短的方法可以做到这一点,如果在使用 Gii 为您的模型生成 CRUD 时,您定义了一个搜索模型类,那么您可以使用它来过滤结果,您所要做的就是覆盖 prepareDataProvider indexAction 的功能强制它返回 ActiveDataProvider search 返回的实例您的模型搜索类的功能,而不是创建一个自定义的新类。

    如果您的模型是 ,则恢复产品.php & 你生成了一个 ProductSearch.php 作为它的搜索类,然后在你的 Controller 中你只需要添加这个:

    public function actions() {
    
        $actions = parent::actions();
        $actions['index']['prepareDataProvider'] = [$this, 'prepareDataProvider'];
    
        return $actions;
    }
    
    public function prepareDataProvider() {
    
        $searchModel = new \app\models\ProductSearch();    
        return $searchModel->search(\Yii::$app->request->queryParams);
    }
    

    然后过滤结果,您的网址可能如下所示:

    api.test.loc/v1/products?ProductSearch[name]=iphone
    

    甚至像这样:

    api.test.loc/v1/products?ProductSearch[available]=1&ProductSearch[name]=iphone
    

    关于api - Yii2 REST 查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25522462/

    相关文章:

    java - 带有服务帐户的 Google Calendar 1.17 API - 未解析的 GoogleClient 类

    ruby-on-rails - 如何在我的 Rails 应用程序中与 Amazon Product Advertising API 交互?

    api - REST API 中错误 HTTP 方法的返回代码?

    php - Yii2模型关系

    php - 通过 CURL (php) 在 twilio 通知 API 中发送批量消息

    python - 为什么这个默认路由会重定向?

    python - 尝试使用 Python 通过 API 访问数据时出错

    json - REST 请求作为 url 编码或 JSON

    php - Yii2 - 更新用户身份信息

    php - 带有自定义 URL 的 ActionColumn 按钮