Yii2:定义除';ID';

Yii2:定义除';ID';,yii2,yii2-advanced-app,Yii2,Yii2 Advanced App,我正试图利用yii2restapi(基于高级模板)创建我自己的服务。我当前正在成功使用以下URL返回一条“文章”记录: 我现在正试图复制此代码,以便它适用于其他记录类型。我的新记录有一个名为“key”的主键,我想通过它进行搜索。因此,我需要将参数名称“id”更改为“key” 有人能解释一下如何在此URL上指定“id”以外的参数吗?每当我省略id作为参数时,我都会得到一个“错误的请求:缺少必需的参数:id”。我不明白这个必需的参数来自何处,以及如何更改或添加它 相关类别如下所示: class A

我正试图利用yii2restapi(基于高级模板)创建我自己的服务。我当前正在成功使用以下URL返回一条“文章”记录:

我现在正试图复制此代码,以便它适用于其他记录类型。我的新记录有一个名为“key”的主键,我想通过它进行搜索。因此,我需要将参数名称“id”更改为“key”

有人能解释一下如何在此URL上指定“id”以外的参数吗?每当我省略id作为参数时,我都会得到一个“错误的请求:缺少必需的参数:id”。我不明白这个必需的参数来自何处,以及如何更改或添加它

相关类别如下所示:

class ArticleController extends ActiveController
{
    /**
     * @var string
     */
    public $modelClass = 'frontend\modules\api\v1\resources\Article';
    /**
     * @var array
     */
    public $serializer = [
        'class' => 'yii\rest\Serializer',
        'collectionEnvelope' => 'items'
    ];

    /**
     * @inheritdoc
     */
    public function actions()
    {
        return [
            'index' => [
                'class' => 'yii\rest\IndexAction',
                'modelClass' => $this->modelClass,
                'prepareDataProvider' => [$this, 'prepareDataProvider']
            ],
            'view' => [
                'class' => 'yii\rest\ViewAction',
                'modelClass' => $this->modelClass,
                'findModel' => [$this, 'findModel']
            ],
            'options' => [
                'class' => 'yii\rest\OptionsAction'
            ]
        ];
    }

    /**
     * @return ActiveDataProvider
     */
    public function prepareDataProvider()
    {
        return new ActiveDataProvider(array(
            'query' => Article::find()->published()
        ));
    }

    /**
     * @param $id
     * @return array|null|\yii\db\ActiveRecord
     * @throws HttpException
     */
    public function findModel($id)
    {
        $model = Article::find()
            ->published()
            ->andWhere(['id' => (int) $id])
            ->one();
        if (!$model) {
            throw new HttpException(404);
        }
        return $model;
    }
}

class Article extends \common\models\Article implements Linkable
{
    public function fields()
    {
        return ['id', 'slug', 'category_id', 'title', 'body', 'published_at'];
    }

    public function extraFields()
    {
        return ['category'];
    }

    /**
     * Returns a list of links.
     *
     * @return array the links
     */
    public function getLinks()
    {
        return [
            Link::REL_SELF => Url::to(['article/view', 'id' => $this->id], true)
        ];
    }
}
提前谢谢

编辑:“前端”文件夹结构中的urlManager规范如下:

<?php
return [
    'class'=>'yii\web\UrlManager',
    'enablePrettyUrl'=>true,
    'showScriptName'=>false,
    'rules'=> [
        // Pages
        ['pattern'=>'page/<slug>', 'route'=>'page/view'],

        // Articles
        ['pattern'=>'article/index', 'route'=>'article/index'],
        ['pattern'=>'article/attachment-download', 'route'=>'article/attachment-download'],
        ['pattern'=>'article/<slug>', 'route'=>'article/view'],

        // Api
        ['class' => 'yii\rest\UrlRule', 'controller' => 'api/v1/article', 'only' => ['index', 'view', 'options']],
        ['class' => 'yii\rest\UrlRule', 'controller' => 'api/v1/user', 'only' => ['index', 'view', 'options']]
    ]
];

只需像往常一样在
ArticleController
中创建新方法即可:

public function actionView2($your_desired_parameter) {
    $article = Article::find()->where(['your_desired_parameter'=>$your_desired_parameter]);
    if (!$article->exists()) 
        throw new NotFoundHttpException();
    return $article->one();
}

我不知道这是否是官方的做法,但我已经创造了一个额外的行动来应对这种情况。“id”参数似乎来自于反映动作中的“run”方法调用,因此我可以使用另一个名为“key”的参数的唯一方法是定义如下所示的函数:

class ExtraAction extends Action  // in yii/rest
{
    public function run($key)  // NOTE: The name 'key' is reflected and then becomes an expected parameter
    {
        $model = $this->findModel($key);

        if (!$model) {
            throw new HttpException(404);
        }
        return $model;
    }
}
完成后,我需要更改actions()定义,如下所示:

    'view' => [
        'class' => 'yii\rest\ExtraAction',
        'modelClass' => $this->modelClass,
        'findModel' => [$this, 'findModel']
    ],
然后,控制器中的findModel($id)将接收GET URL中定义的“key”参数(例如api/v1/article?key=blah123)

然后,我可以基于我拥有的不同唯一密钥执行查找:

public function findModel($id)
{
    $model = Record::find()
    ->andWhere(['key_field' => $id])
    ->one();    
} 

我不知道这是否是正确的做法,但在这种情况下似乎确实有效

这可以通过在配置文档中向urlmanager添加规则来实现

例如:

'rules' => [
    [   'class' => 'yii\rest\UrlRule',
        'pluralize' => false,
        'controller' => [
            'yourController',
        ],
        'patterns' => [
            'PUT,PATCH {id}' => 'update',
            'DELETE {id}' => 'delete',
            'GET,HEAD {id}' => 'view',
            'GET,HEAD {key}' => 'view',
            'POST' => 'create',
            'GET,HEAD' => 'index',
            '{id}' => 'options',
            'OPTIONS' => 'options',
            'PUT,PATCH {key}' => 'update',
        ],
         'tokens' => [
            '{id}' => '<id:\\d[\\d,]*>',
            '{type}' => '<type:\\w[\\w,]*>',
            '{key}' => '<key:\\w[\\w,]*>',
        ],
    ],
]
并将密钥参数添加到操作中

class ViewAction  extends \yii\rest\ViewAction {

    public function run($id = null, $key = null)
    {
        // your code
    }
}
现在你应该可以这样做了


GET your/{keyparam}->wil resolve to yourController->ViewAction

检查ViewAction docs:,默认情况下需要接收
$id
参数。我要做的是创建一个新操作,比如说
view2
,然后添加您需要的功能。看起来您使用的规则与通常实现的规则不同。您还可以显示您的
urlManager
设置吗?谢谢您的回复,@gmc。如果我按照您的建议创建一个新方法,您是否知道(或者可以让我参考文档)在哪里配置了“id”值?@Salem,我不确定在哪里可以找到urlManager设置(我有点新手)。您可以在配置文件中找到它。它是定义url
规则的地方。你会在我之前评论中链接的文档中看到它。谢谢@gmc,尽管我需要在控制器中添加“view2”操作吗?如果是,我的“类”属性应该是什么?如果我将其设置为“ViewAction”,它将再次坚持我需要提供id。我不是100%确定,但我认为您不需要将其添加到此处。很遗憾,添加“actionView2”无效(“未找到页面”)。我似乎需要添加一个操作,但如果我将“查看”操作复制并粘贴为“查看2”,我再次需要提供一个“id”(即使使用您提到的代码)。Hi@Tim,您能告诉我在我的示例中只接受GET URL中的“key”而不接受“id”的具体设置吗?我已经尝试了所有这些设置的许多排列,但不知道如何省略'id'参数。不幸的是,这些文档对我来说并不是不言自明的。我尝试添加一个模式,说“GET,HEAD{key}”=>“view”,但这不起作用。@SimpleGuy对我的反应太晚表示歉意,但我已经更新了我的答案如何配置控制器和相应的视图,希望能有所帮助
class ViewAction  extends \yii\rest\ViewAction {

    public function run($id = null, $key = null)
    {
        // your code
    }
}