Yii2 overriding fields() to rename fields in case of validation errors - rest

Ref: http://www.yiiframework.com/doc-2.0/guide-rest-resources.html#overriding-fields
I am overriding fields() to rename fields in User model.
GET - response data fields are renamed as expected
POST - validation error field names are not renamed
1. User table columns
public function rules()
{
return [
[['User_Name', 'Password', 'Auth_Token', 'User_Type_Id', 'User_Status_Id'], 'required'],
]
}
2. overriding fields()
public function fields()
{
return [
'user_id' => 'User_Id',
'access_token' => 'Auth_Token',
'user_name' => 'User_Name',
'user_type' => 'userType.User_Type_Name',
'name' => 'userProfile.Fname',
];
}
3. Get User data (fields renamed as expected)
[
{
"user_id": "1",
"access_token": "123",
"user_name": "kiran",
"user_type": "Customer",
"name": "customer"
}
]
Validate model (error field names are not renamed)
[
{
"field": "User_Name",
"message": "User Name cannot be blank."
},
{
"field": "Password",
"message": "Password cannot be blank."
},
{
"field": "Auth_Token",
"message": "Auth Token cannot be blank."
},
{
"field": "User_Type_Id",
"message": "User Type ID cannot be blank."
},
{
"field": "User_Status_Id",
"message": "User Status ID cannot be blank."
}
]

Using getter/setter methods to load the post data inside user model.
Ref: Yii2 REST create with fields()
Overwriting addError() method to change error field name
public function addError($attribute, $error = '') {
$renamed_attr = $this->renamedFields($attribute);
parent::addError($renamed_attr, $error);
}

Related

Mongoose hide fields AFTER populating

Supposed I have this schema
class Room {
member_ids: [String]
owner_ids: [String]
}
And two virtual populates members and owners, which map to User schema (custom path, not _id)
I successfully get the data populated with this:
return this.roomModel
.findOne({ id: roomId })
.select('-_id -__v')
.populate('members owners', '-_id -__v')
.exec();
It now returns
{
"member_ids": [
"1",
"2"
],
"owner_ids": [
"1"
],
"owners": [
{
"id": "1",
"name": "User 1"
}
],
"members": [
{
"id": "1",
"name": "User 1"
},
{
"id": "2",
"name": "User 2"
}
]
}
The thing is, I don't want member_ids and owner_ids to end up in my response. I've tried using select('-member_ids -owner_ids') however the response did not have populated data anymore (I guess the select phase happens before the populate phase?). Is there anyway to achieve this, without resorting to manually removing the fields afterwards? Thank you.

How do I add custom queries in GraphQL using Strapi?

I'm using graphQL to query a MongoDB database in React, using Strapi as my CMS. I'm using Apollo to handle the GraphQL queries. I'm able to get my objects by passing an ID argument, but I want to be able to pass different arguments like a name.
This works:
{
course(id: "5eb4821d20c80654609a2e0c") {
name
description
modules {
title
}
}
}
This doesn't work, giving the error "Unknown argument \"name\" on field \"course\" of type \"Query\"
{
course(name: "course1") {
name
description
modules {
title
}
}
}
From what I've read, I need to define a custom query, but I'm not sure how to do this.
The model for Course looks like this currently:
"kind": "collectionType",
"collectionName": "courses",
"info": {
"name": "Course"
},
"options": {
"increments": true,
"timestamps": true
},
"attributes": {
"name": {
"type": "string",
"unique": true
},
"description": {
"type": "richtext"
},
"banner": {
"collection": "file",
"via": "related",
"allowedTypes": [
"images",
"files",
"videos"
],
"plugin": "upload",
"required": false
},
"published": {
"type": "date"
},
"modules": {
"collection": "module"
},
"title": {
"type": "string"
}
}
}
and the
Any help would be appreciated.
Referring to Strapi GraphQL Query API
You can use where with the query courses to filter your fields. You will get a list of courses instead of one course
This should work:
{
courses(where: { name: "course1" }) {
name
description
modules {
title
}
}
}

GraphQL query result for object that does not exist

I have a GraphQL query that calls a REST service to get the return object. The query contains an Id parameter that is then passed to the service. However, the REST service can respond with http status 404 Not Found if an object with that Id does not exist. That seems like the right response.
How do you model a Not Found response in GraphQL?
Is there a way to inform the GQL caller that something does not exist?
Update
Some options I am considering:
Return null
Change the GrqlhQL Query to return a list of objects and return empty list of nothing is found
Return some kind of error object with an error code
but it is unclear if there is a recommended practice in GQL API design.
You might treat it as an error and handle it accordingly.
I recommend you to check the GraphQL spec, the paragraph about error handling.
I hope it contains exactly what you are looking for.
Basically, you should return whatever you could, and inform a client about potential problems in the "errors" field.
The example from the documentation:
Request:
{
hero(episode: $episode) {
name
heroFriends: friends {
id
name
}
}
}
Response:
{
"errors": [
{
"message": "Name for character with ID 1002 could not be fetched.",
"locations": [ { "line": 6, "column": 7 } ],
"path": [ "hero", "heroFriends", 1, "name" ]
}
],
"data": {
"hero": {
"name": "R2-D2",
"heroFriends": [
{
"id": "1000",
"name": "Luke Skywalker"
},
{
"id": "1002",
"name": null
},
{
"id": "1003",
"name": "Leia Organa"
}
]
}
}
}

Yii2 REST: How to customize Error response?

For first I use this solution - http://www.yiiframework.com/doc-2.0/guide-rest-error-handling.html
But, I want to customize two types error.
When model validation wrong.
When something wrong (Exceptiin)
If model validation wrong i get response, like that:
{
"success": false,
"data": [
{
"field": "country_id",
"message": "Country Id cannot be blank."
},
{
"field": "currency_id",
"message": "Currency Id cannot be blank."
},
{
"field": "originator_id",
"message": "Originator Id cannot be blank."
}
]
}
But i want like that:
{
"success": false,
"data": [
"errors": [
{
"field": "country_id",
"message": "Country Id cannot be blank."
},
{
"field": "currency_id",
"message": "Currency Id cannot be blank."
},
{
"field": "originator_id",
"message": "Originator Id cannot be blank."
}
]
]
}
Second type error i get
{
"success": false,
"data": {
"name": "Exception",
"message": "Invalid request arguments",
"code": 0,
"type": "yii\\base\\InvalidParamException",
]
}
}
But i Want:
{
"success": false,
"data": {
"errors" : 1, <----------------
"name": "Exception",
"message": "Invalid request arguments",
"code": 0,
"type": "yii\\base\\InvalidParamException",
]
}
}
Because in anyway user get 200 Response and they don know about error or mistake.
If you are using default yii/rest/Controller model with error send 422.
Use yii/rest/Controller or yii/rest/ActiveController or extend it.
Or use own Serializer
http://www.yiiframework.com/doc-2.0/yii-rest-serializer.html
Maybe this could guide you, how to change error format:
class JsonErrors
{
public static function validation($model)
{
Yii::$app->response->statusCode = 422;
//Yii::$app->response->format = 'json';
$errorArray = [];
foreach($model->getErrors() as $key => $val) {
$errorArray[] = [
'field' => $key,
'message' => implode(', ', $val) // $val is array (can contain multiple error messages)
];
}
return $errorArray;
}
}
// in controller:
return JsonErrors::validation($model);
// config:
'on beforeSend' => function ($event) {
$response = $event->sender;
if($response->statusCode == 422)
{
$details = $response->data;
if(isset($response->data["message"]) && is_string($response->data["message"])) $details = $response->data["message"];
if(isset($response->data["message"]) && is_array($response->data["message"])) $details = json_decode($response->data['message']);
$response->data = [
'message' => 'Please correct your data with correct values.',
'details' => $details
];
}
}

How to create google datastore composite indices via REST API?

I am trying to change the order of my results but I keep getting an error saying You need an index to execute this query.
In my console, I doesn't say that any indices exist, but I set most of the indexed options to true.
I know in Java, I can create indices that relate to multiple properties either ascending or descending, how do I do this with the REST API?
Following the REST API docs for Google Datastore, my entities are created like this:
{
"mode": "TRANSACTIONAL",
"transaction": "Eb2wksWfYDjkGkkABRmGMQ_vKGijwNwm-tbxAbUPRt8N2RaUCynjSbGT7jFQw3pgaDCT7U0drs3RTPLSIN8TQikdqkdl7pLm2rkMqORmKlO_I_dp",
"mutation": {
"insertAutoId": [
{
"key": {
"path": [
{
"kind": "Attendance"
}
]
},
"properties": {
"section": {
"indexed": true,
"stringValue": "Venturers"
},
"date": {
"dateTimeValue": "2015-01-16T00:00:00+00:00",
"indexed": true
},
"attendee": {
"indexed": true,
"keyValue": {
"path": [
{
"id": "5659313586569216",
"kind": "Attendee"
}
]
}
},
"presence": {
"indexed": false,
"integerValue": 0
}
}
}
]
}
}
And I am trying to query like this:
{
"gqlQuery": {
"allowLiteral": true,
"queryString": "SELECT * FROM Attendance WHERE section = #section ORDER BY date ASC",
"nameArgs": [
{
"name": "section",
"value": {
"stringValue": "Venturers"
}
}
]
}
}
And I get this error:
{
"error": {
"errors": [
{
"domain": "global",
"reason": "FAILED_PRECONDITION",
"message": "no matching index found.",
"locationType": "header",
"location": "If-Match"
}
],
"code": 412,
"message": "no matching index found."
}
}
For future reference:
You can't make a composite index directly through the REST API. You must go through php app engine.
How to build datastore indexes (PHP GAE)