I created an api named valid which is not working. Postman says
"name": "Not Found",
"message": "Page not found.",
"code": 0,
"status": 404,
"type": "yii\\web\\NotFoundHttpException",
"previous": {
"name": "Invalid Route",
"message": "Unable to resolve the request \"user/valid/1\".",
"code": 0,
"type": "yii\\base\\InvalidRouteException"
}
}
My controller name is user controller.
Here is my function
public function actionValid($id)
{
return 'example';
}
i called my route as /user/valid/1.
Any reason why this is happening?
This is how i solved this.
If you want to create your own apis in yii, You must follow these steps.
First add your route in UrlManager Like this
'urlManager' => [
'enablePrettyUrl' => true,
'enableStrictParsing' => true,
'showScriptName' => false,
'rules' => [
[
'class' => 'yii\rest\UrlRule',
'controller' => 'user',
'extraPatterns' => [
'POST valid/<id>' => 'valid',
'GET listing' => 'listing
]
],
],
]
Now, call your route like this users/valid/{your-id} and users/listing. Make sure to use a plural of your controller's name.
For example, a request of POST /users/data would mean accessing the actiondata function in your usercontroller.
Related
Below is the link to the Scout Elasticsearch Drive which I am using in my Laravel project.
https://github.com/babenkoivan/scout-elasticsearch-driver
I have database table users with the following columns:
id Integer
name String
created_at DateTime
Following the documentation on GitHub, my mapping in the User model looks like followings:
use Searchable; // using Searchable trait.
protected $mapping = [
'properties' => [
'name' => [
'type' => 'text',
'fields' => [
'raw' => [
'type' => 'keyword',
],
],
],
'created_at' => [
'type' => 'date',
'format' => 'dd-MM-yyyy HH:mm',
'fields' => [
'raw' => [
'type' => 'keyword',
],
],
],
// Custom field...
'created_date' => [
'type' => 'date',
'format' => 'dd-MM-yyyy',
'fields' => [
'raw' => [
'type' => 'keyword',
],
],
],
// Custom field...
'created_time' => [
'type' => 'date',
'format' => 'HH:mm',
'fields' => [
'raw' => [
'type' => 'keyword',
],
],
],
]
]
Below is the implementation of the toSearchableArray() function.
public function toSearchableArray()
{
$array = $this->toArray();
// Pre-format the custom fields before inserting them into Elasticsearch.
$array['created_date'] = $this->created_at->format('d-m-Y');
$array['created_time'] = $this->created_at->format('h:i');
return $array;
}
When using curl -X GET command I get the following results and of course with the custom fields.
"hits" : [
{
"_source" : {
"id" : 3,
"name": "John Doe",
"created_at": "31-12-2018 23:59",
"created_date": "31-12-2018", // My custom field.
"created_time": "23:59" // My custom field.
}
]
In my index() action in my controller, I query the data using the following code.
public function index()
{
return User::search("*")->get();
}
I get the records with only the original attributes, matching those columns in the database table as following.
[
{
"id" : 3,
"name": "John Doe",
"created_at": "31-12-2018 23:59",
}
]
Note that this is a JSON response provided by default by Laravel, responding to API calls. My custom attributes created_date and created_time do exist in Elasticsearch as well. How can I get them too as result? The reason I created these custom fields is to format the date and time on the server side beforehands so that my client-side does not need to worry about formating the date and time in the for-loop.
When I use User::search("*")->explain(); I do get my custom fields as well in the hits.hits._source{} object.
This should give you results directly from Elastic Search without matching up with your related models. I think thats the reason why your custom fields get lost.
public function index()
{
return User::search("*")->raw();
}
Documentation
I'm adding a REST API onto an existing cakephp codebase.
It is working as I expect. I hit /api/v1/contacts/12312 and get json data back for contact 12312. If put an id of a contact that doesn't exist then I get the html 404 page error rather than json.
This happens internally on the contacts->get($id) line.
In the api app controller I have
public function initialize()
{
parent::initialize();
$this->loadComponent('RequestHandler');
$this->loadComponent('Crud.Crud', [
'actions' => [
'Crud.Index',
'Crud.View',
'Crud.Add',
'Crud.Edit',
'Crud.Delete'
],
'listeners' => [
'CrudJsonApi.JsonApi',
'CrudJsonApi.Pagination', // Pagination != ApiPagination
'Crud.ApiQueryLog',
],
'Error' => [
'errorLevel' => E_ALL,
'exceptionRenderer' => 'CrudJsonApi\Error\JsonApiExceptionRenderer',
'skipLog' => [],
'log' => true,
'trace' => true,
],
]);
$this->Crud->config(['listeners.jsonApi.exceptionRenderer' => 'CrudJsonApi\Error\JsonApiExceptionRenderer']);
$this->setJsonResponse();
}
public function beforeRender(Event $event)
{
$this->RequestHandler->renderAs($this, 'json');
$this->response->type('application/json');
$this->set('_serialize', true);
}
I thought using the JsonApiExceptionRenderer 404 errors would be handled with json output.
Also the Pagination works but the Pagination data isnt returned with the response...
{
"viewVar": "crmContacts",
"crmContacts": [
{
"id": 1,
"lastname": "testname1"
},
{
"id": 2,
"lastname": "smith"
}
],
"success": true
}
Any ideas?
Thanks
I'm use Guzzle for Laravel to send POST for Webservice, but I can't access array to send picture. That is the structed to I need follow:
{
"title": "xxxxxxxxxxxxxxxxx",
"category_id": "XXXX",
"official_store_id": null,
"pictures": [
{
"id": "XXXXX",
"url": "http://mlb-s1-p.mlstatic.com/292325-MLB25432321923_032017-O.jpg",
"secure_url": "https://mlb-s1-p.mlstatic.com/292325-MLB25432321923_032017-O.jpg",
"size": "500x500",
"max_size": "500x500",
"quality": ""
}
],
}
I try to send it like this:
$r = $client->request('POST', 'https://api.mercadolibre.com/items?access_token='.$token->erp_access_token, [
'json' => [
'title' => $name,
'category_id' => $cat2,
'price' => $price,
'currency_id' => 'BRL',
'available_quantity' => $quantity,
'buying_mode' => 'buy_it_now',
'listing_type_id' => 'gold_special',
'condition' => 'new',
'description' => $description,
'pictures' => [
'url' => $image
]
]
]);
Returns the error:
{"message":"body.invalid_field_types","error":"[invalid property type: [pictures] expected List but was JSONObject value (truncated...)
I read the Guzzle docs, but I not found any example for that case.
Any suggestion?
Change your pictures value from this
'pictures' => [
'url' => $image
]
to this
'pictures' => [
['url' => $image]
]
Currently, for my GET endpoints in RESTFUL Zend Framework 3, if I can't find the item the user requests through the paramaters I send 400 with JSON API errors like so:
$this->response->setStatusCode(Response::STATUS_CODE_400);
return JsonModel([
'errors' => [
[ 'title' => 'Not found' ]
]
]);
The correct status of course is 404. However as soon as I set $this->response->setStatusCode(Response::STATUS_CODE_404); the default 404 route is displayed. How do I disable it?
I tried commenting out the following in module.config.php
. . .
'view_manager' => [
// 'display_not_found_reason' => true,
'display_exceptions' => true,
'doctype' => 'HTML5',
// 'not_found_template' => 'error/404',
'exception_template' => 'error/index',
'strategies' => [
'ViewJsonStrategy',
],
. . .
],
That works, except I have two problems:
I'd like the 404 route for some endpoints
It adds information to the return JSON I don't want sent
{
"errors": [
{
"title": "Not Found",
}
],
"message": "Page not found.",
"display_exceptions": true,
"controller": "Company\Module\Controller\RestfulController",
"controller_class": null
}
What are my options?
Your issue is caused by Zend\Mvc\View\Http\RouteNotFoundStrategy, which is registered by your default view manager. You can see that at Zend\Mvc\View\Http\ViewManager:
$routeNotFoundStrategy = $services->get('HttpRouteNotFoundStrategy');
Even if you use 'display_exceptions' => false, message is still appended.
To overcome this, one solution is to inject the model content to the response and return the latter directly on your view:
$this->response->setStatusCode(Response::STATUS_CODE_404);
$model = new JsonModel([
'errors' => [
[ 'title' => 'Not found' ]
]
]);
return $this->getResponse()->setContent($model->serialize());
I'm implementing RESTFUL API with Yii2. The thing is I don't use models at all. My API just gets the request and performs some calculations (or passes request as a proxy to somewhere else) and outputs the response.
I have following controllers in app\modules\api\v1\controllers:
namespace app\modules\api\v1\controllers;
class CarController extends \yii\rest\Controller
{
// GET /v1/car/:id
public function actionIndex()
{
$carId = \Yii::$app->request->get('id');
// Forwarding request to other API
return ['some_reponse'];
}
// DELETE /v1/car/:id
public function actionDelete()
{
$carId = \Yii::$app->request->get('id');
// Forwarding request to other API
return ['some_reponse'];
}
public function behaviors()
{
return [
'verbs' => [
'class' => \yii\filters\VerbFilter::className(),
'actions' => [
'create' => ['post'],
'delete' => ['delete']
],
],
];
}
}
// ===============================
namespace app\modules\api\v1\controllers;
class CarsController extends \yii\rest\Controller
{
// POST /v1/cars
public function actionCreate()
{
$carData = \Yii::$app->request->post;
// Forwarding data to other API
return ['some_reponse'];
}
public function behaviors()
{
return [
'verbs' => [
'class' => \yii\filters\VerbFilter::className(),
'actions' => [
'create' => ['post']
],
],
];
}
}
// ===============================
namespace app\modules\api\v1\controllers;
class NotificationsController extends \yii\rest\Controller
{
// POST /v1/notifications
public function actionCreate()
{
$noticicationsData = \Yii::$app->request->post;
// Perform some additinal actions here
return ['some_reponse'];
}
public function behaviors()
{
return [
'verbs' => [
'class' => \yii\filters\VerbFilter::className(),
'actions' => [
'create' => ['post']
],
],
];
}
}
Url manager configuration:
'urlManager' => [
'enablePrettyUrl' => true,
'enableStrictParsing' => true,
'showScriptName' => false,
'rules' => [
[
'class' => 'yii\rest\UrlRule',
'controller' => [ 'v1/cars' ],
'extraPatterns' => [ 'POST cars' => 'create' ]
],
[
'class' => 'yii\rest\UrlRule',
'controller' => [ 'v1/car' ],
'extraPatterns' => [ 'GET car' => 'index', 'DELETE car' => 'delete' ]
],
[
'class' => 'yii\rest\UrlRule',
'controller' => [ 'v1/notifications' ],
'extraPatterns' => [ 'POST notifications' => 'create' ]
]
]
]
Cars endpoint works fine. But other endoints return 404 error. Error response example:
{
"name": "Not Found",
"message": "Page not found.",
"code": 0,
"status": 404,
"type": "yii\web\NotFoundHttpException",
"previous": {
"name": "Invalid Route",
"message": "Unable to resolve the request: v1/car/options",
"code": 0,
"type": "yii\base\InvalidRouteException"
}
}
Any ideas whats wrong here? I guess something is wrong with my rules.
The problem was with urlManager rules configuration. For e.g. if I create CarController it treats like CarsController. So I have to set pluralize to false. Also modified extraPatterns section as well:
'urlManager' => [
'enablePrettyUrl' => true,
'enableStrictParsing' => true,
'showScriptName' => false,
'rules' => [
[
'class' => 'yii\rest\UrlRule',
'controller' => [ 'v1/cars' ],
'extraPatterns' => [ 'POST' => 'create' ],
],
[
'class' => 'yii\rest\UrlRule',
'controller' => [ 'v1/car' ],
'extraPatterns' => [ 'GET' => 'index', 'DELETE' => 'delete' ],
'pluralize' => false
],
[
'class' => 'yii\rest\UrlRule',
'controller' => [ 'v1/notifications' ],
'extraPatterns' => [ 'POST' => 'create' ]
]
]
]
Problem with yii\rest\Controller::actions(), this method already have actions index , options,view etc. You need disabled action to use your action:
public function actions()
{
$actions = parent::actions();
unset($actions['view'], $actions['index']);
return $actions;
}