Zend Framework 2: How can I add in RESTful API a custom http method? - rest

I'm trying to create a custom http method in RESTful API. I was reading the documentation and it is said that you can do it buy adding a simple action in controller and then for example conifg your route with child routes with action => action_name but in the code I have spotted addHttpMethodHandler() method in Zend\Mvc\Controller\AbstractRestfulController.php so in controller construct method I have added:
$add = function () {
return new JsonModel(array(
'id' => 2222,
));
};
$this->addHttpMethodHandler('someAction', $add);
var_dump($this->customHttpMethodsMap);
With the var_dump I can see that this new function is added but I just wonder how can I call it or maybe I'm missing the point.
Regards,

I actually wrote a blog post on this because I had so much trouble too.
The problem is that in addition to calling addHttpMethodHandler within the abstract restful controller, you also need to make sure that the Zend Request class knows that your http method exists.
Here is a link to a better explanation: http://richardbrock1.wordpress.com/2013/03/23/custom-http-methods-in-zf2/

Related

Writing API best practice in Cakephp

i am creating a web application in cakephp 2.9. it has two use,
To provide API access to android and Ios devices
To serve Web pages(Normal web applicaiton)
currently i am developing the api part , i create a webserviceController.php file and write all the Api , Now i feel like the controller is too fatty,
i dont know which is the best practice to manage API's. now my webservice controllerhave more than 2000 lines of code..
now iam planning to seperate the each api's in different controller
can anyone suggest me a good practice for writing apis in cakephp
currently my code look like
class WebServicesController extends Controller
{
public $uses = null;
public $components = array('RequestHandler', 'Verification', 'AppContstant','PushNotification');
public function users()
{
//code to get users
//
$this->set(array(
'result' => $result,
'_serialize' => 'result'
));
}
and in my route.php
Router::mapResources('WebServices');
Router::parseExtensions();
Router::resourceMap(array(
array('action' => 'users', 'method' => 'GET', 'id' => false),
i have more around 43 api's in webserviceController,
How to manage API's cakephp
What is the best practice?
_serialize vs json_encode() which is fast?
How to versioning my API url ?
The simplest way of making an API in cakephp is print the a JSON directly from the controller and stop the rendering by die().
Official document suggests you to have an API view for the output, which is a standard MVC way and is a good practice. You can check out more here: https://book.cakephp.org/2.0/en/views/json-and-xml-views.html
Maybe you can reference how Croogo implemented it, this is a Cakephp based CMS.
They make API as a component to manage version and methods: https://github.com/croogo/croogo/blob/master/Croogo/Controller/Component/BaseApiComponent.php
This is an example of its URL routing in format /$version/$model/$method.$format/?$parameters
http://www.example.com/croogo-2.2.2/api/v1.0/nodes/lookup.json?type=page&title=how
Sibin Francis, You can use rest api class and include in you api controller
add following line at top
App::import('Vendor', 'REST', array('file' => 'Rest.inc.php'));
Public function yourFunctionName() {
if ($this->request->is("post")) { // Use your method name put/post/get/etc
$rest = new REST();
// Your logic here
return $rest->response(json_encode($data), response_code);
}
}
Its very easy and simple. Only you need to call vendor Rest Api class.

using filters with autofac in webapi2

I have a actionfilter something as below.. The filter basically adds a few attributes to the header of the response..
public class myHeaderAttribute : ActionFilterAttribute
{
public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
{
if (actionExecutedContext.Response != null)
//my code goes here
base.OnActionExecuted(actionExecutedContext);
}
}
I would normally call this in WebApiConfig.Register as config.Filters.Add(new myHeaderAttribute());
I wish to use Autofac in my project..
There is a page in autofac site (http://docs.autofac.org/en/latest/integration/webapi.html)which speaks of implementing IAutofacActionFilter.
But, I'm not very clear as to what I'm supposed to do.
I can create another class which implements IAutofacActionFilter and add the onActionExecuted method.
But do I also keep my present class or remove it along with the line in WebApiConfig.Register.
Also the page speaks of registering the Autofac filter provider as well as the class which implements IAutofacActionFilter. But no complete example exists.
Also, it speaks of using 'service location' in case we need per-request or instance-per-dependency services in our filters.
The whole thing seems a little too confusing to me. I would sincerely appreciate if someone who understands these concepts and has used Autofac in a web api2 project could guide me.
Thanks
Remove it. It explains exactly in the docs you reference yourself that it uses its own action filter resolver. See section "Provide filters via dependency injection".
Update
First register the filter provider:
var builder = new ContainerBuilder();
builder.RegisterWebApiFilterProvider(config);
Then register your actionfilter like so:
builder.Register(c => new myHeaderAttribute())
.AsWebApiActionFilterFor<YourController>(c => c.YourMethod(default(int)))
.InstancePerApiRequest();
So complete code:
var builder = new ContainerBuilder();
builder.RegisterWebApiFilterProvider(config);
builder.Register(c => new myHeaderAttribute())
.AsWebApiActionFilterFor<YourController>(c => c.YourMethod(default(int)))
.InstancePerApiRequest();
It's all right there in the docs. If you have any specific question then you can ask seperately. But this is becoming to be too broad.

Nested REST routes and subnamespaces in CakePHP3

In CakePHP 3 the rest routing doesn't call classes in subnamespace. For example the route "posts/2/comments/10" call App\Controller\CommentsController. I want it to call App\Controller\Posts\CommentsController because comments are not always for posts...
Here is my solution :
$routes->resources('Posts');
Router::scope('/posts/:post_id/',['post_id'=>'[0-9]+','prefix'=>'posts'], function($routes){
$routes->resources('Comments');
});
It works fine but i don't know if it is a good practice.
Thank you
If you want to group controllers by namespace use Router::prefix() or $routes->prefix() instead of $routes->scope()

CakePHP Custom REST Routes

I'm using CakePHP and Backbone.js as a frontend so I want to get CakePHP's REST routing working, but I don't really want to use the default REST routes.
For example, I want to be able to POST to http://example.com/cards/search.json and get a list of results in JSON, however I am getting a 200 status code back, and a blank response which makes me think the routing is not working properly.
I have tested my code using the default REST routes by chagning the search() method of my controller to add(), but I would prefer to be able to properly setup and use custom REST routes.
Router::connect(
"/cards/search",
array(
"[method]" => "POST",
"controller" => "cards",
"action" => "search"
)
);
Router::mapResources('cards');
Router::parseExtensions('json');
The code from my routes.php is above and I'm not entirely sure why it isn't working...either because the documentation on this is a little light, or I just don't understand routing very well.
You can get the json output in this url:
http://localhost:{port}/{api* name in config # app/core}/{controller name}/{things after api_ in function name}/{input parameters}.json
read more in here
You may have to alter the routing to change the name
api
to anything in
Configure::write('Routing.prefixes', array('master', 'api'));
in core.php in app/config
Feel free for a comment and also share your core.php in config for more explanation.

How can I check my post data in Zend?

I am a beginner and I am creating some forms to be posted into MySQL using Zend, and I am in the process of debugging but I don't really know how to debug anything using Zend. I want to submit the form and see if my custom forms are concatenating the data properly before it goes into MySQL, so I want to catch the post data to see a few things. How can I do this?
The Default route for zend framework application looks like the following
http://www.name.tld/$controller/$action/$param1/$value1/.../$paramX/$valueX
So all $_GET-Parameters simply get contenated onto the url in the above manner /param/value
Let's say you are within IndexController and indexAction() in here you call a form. Now there's possible two things happening:
You do not define a Form-Action, then you will send the form back to IndexController:indexAction()
You define a Form action via $form->setAction('/index/process') in that case you would end up at IndexController:processAction()
The way to access the Params is already defined above. Whereas $this->_getParam() equals $this->getRequest()->getParam() and $this->_getAllParams() equals $this->getRequest->getParams()
The right way yo check data of Zend Stuff is using Zend_Debug as #vascowhite has pointed out. If you want to see the final Query-String (in case you're manually building queries), then you can simply put in the insert variable into Zend_Debug::dump()
you can use $this->_getAllParams();.
For example: var_dump($this->_getAllParams()); die; will output all the parameters ZF received and halt the execution of the script. To be used in your receiving Action.
Also, $this->_getParam("param name"); will get a specific parameter from the request.
The easiest way to check variables in Zend Framework is to use Zend_Debug::dump($variable); so you can do this:-
Zend_Debug::dump($_POST);
Zend framework is built on the top of the PHP . so you can use var_dump($_POST) to check the post variables.
ZF has provided its own functions to get all the post variables.. Zend_Debug::dump($this->getRequest()->getPost())
or specifically for one variable.. you can use Zend_Debug::dump($this->getRequest()->getPost($key))
You can check post data by using zend
$request->isPost()
and for retrieving post data
$request->getPost()
For example
if ($request->isPost()) {
$postData = $request->getPost();
Zend_Debug::dump($postData );
}