I have a CakePHP app and would like to incorporate a simple REST API, at first just for GET requests without authentication.
I have the conventional structure, e.g.:
Post (post model),
postsController (posts controller), method names match the routes.
views/posts (posts views - e.g. index.ctp etc)
Say I wanted a few REST API routes how would I add them alongside my normal views and controller methods. I presume having a separate apiPostsController might be a good idea but I'm not sure how to implement.
Route wise, for a given example.com/posts/view/123, the API equivalent might be example.com/api/v1/posts/view/123.
How might I implement this?
Looking at the book, the given instructions make use of the conventional controller and views which are already in use for actually viewing the app.
Why do you think you need another controller? This is not DRY. You'll replicate a lot when you do this.
If your API methods behave that much different you can still use prefix routing and prefix the methods with api, for example: api_some_action().
I guess your API is using XML or Json, see this chapter of the book how to archive this along side the regular HTML views: JSON and XML Views.
Router::connect('/api/:version/:controller/:action/*',
array(),
array(
'version' => 'v1|v2',
)
);
This route should work.
Related
I am thinking about using Symfony to create a RESTful api. I want my app to only accept json and/or xml and just output either. I want my frontend to be completely separate in a separate directory.
Disclaimer: I know most frameworks only claim to be MVC, and that the definition/principles of MVC vary from developer to developer. Therefore, I've laid out my understanding of MVC.
How I picture MVC (taken from Martin Fowler):
Make a strong separation between presentation (view & controller) and domain (model)
Controller and view should (mostly) not communicate directly but through the model.
Have views (and controllers) observe the model to allow multiple widgets to update without needed to communicate directly - Observer Synchronization.
In Symfony, the Controller returns a Response, and there really isn't a View class. They sort of combined the two.
My questions are:
Is it possible to separate the controller into a controller and view?
Can you make the controller not return something?
Possible to not have any html/templates within the app/bundle?
As I stated earlier, I want to keep frontend completely separate, therefore, I wouldn't use twig. I would use JS, SASS, React, etc. for my frontend stuff to make ajax calls to my Symfony api.
What you are trying to do is a pretty standard architecture.
You do not need to use templates but your controllers have to return "something". If you are handling the view in the front-end, this would be just the data needed to create this view, usually in the form of json
Symfony can do this, no problem
I'm wondering if it's possible to set a route in Cakephp that will allow me to route to a set of controllers where a prefix is set. What I'm looking to do is duplicate most of my controllers but for a REST api.
I'd like to still have all the default controllers for the site itself but have a product controller for instance that only returns JSON. For this I would like to move all api controllers into a subfolder and route to them by detecting /api/controllername.
Is this possible or even the correct way to accomplish this?
What I'm looking to do is duplicate most of my controllers but for a
REST api.
Bad idea. IMHO. You're going to duplicate code very likely and scatter code everywhere. Keep it in one place. This sentence is an indicator that makes me think you have to much logic in your controllers. Move it to models, fat models.
There are several better ways to do this.
Use a prefix for routing to API methods inside your related controllers (api/v1/foo/bar -> ControllerName::api_actionName())
Implement a single API controller that dispatches model methods (api/v1/foo/bar -> FooModel::barMethod($queryParam1, $queryparam2,...)
Implement a service layer that sits between the model and the controllers and implement a dispatcher filter or the API controller from the 2nd suggestion to dispatch the service methods. You'll use services instead of models then. Controller <-> Service <-> Model. To implement this well some experience with the framework and design patterns is required. If its not well done it will probably cause more problems than benefit - IMHO.
If it's a more or less simple API and the API logic is similar to your actions you can simple re-use the same controller actions you already have and just usethe built in REST and JSON/XML view serialization and could still use routing to create a fancy route (api/v1/...) for them. You can then do conditional checks as well if the controller is called as API.
It's up to you which one you pick, I've seen and used them all in action, they all work the difference is mostly the implementation and level of abstraction you need. However, the key point is to write clean and DRY code and care about SoC.
I'm new to MVC's (this is my first time using one in a real scenario) and I am a little bit confused about how controllers (should) work.
After reading the Laravel documentation, I came to the conclusion that for general tasks like handling loading the sites (different sites are connected together), pages, admin, etc. I need RESTful controllers.
For the simple tasks it worked. It was easy and very fun to use. I had a Route like this:
Route::controller('admin', 'AdminController');
I had functions like
public function getProduct($id)
and it worked. (It was used to get a specific product: ../admin/product/1)
Now I want something more complex. Like
../sites/loadsite/mysite/mypage/mysubpage/123?myoption=yes
How do I do this? How do I begin, how to approach the problem? Do I have to use Route::get() for every single thing or is there a "nicer" way of doing this?
Laravel provides the "Resource Controllers" helper for generating RESTful routes for corresponding controller methods:
http://laravel.com/docs/controllers#resource-controllers
You can use this to easily create the standard REST routes for a given model, or, as shown in the example provided at laravel.com, you can restrict to only certain routes. The table they provide demonstrates how given paths map to given actions / controller methods.
Regarding the example url you give: ../sites/loadsite/mysite/mypage/mysubpage/123?myoption=yes, I'll break the question into two pieces, the url and query string:
Regarding the URL /sites/loadsite/mysite/mypage/mysubpage/123. This would not be considered by many to be a "RESTful" route. Instead of pages and subpages, you should be thinking in terms of models, and sometimes submodels. It is commonly considered best practice to avoid deeply nested routes, which typically means anything more than a single layer of depth: /model/{id}/submodel/[id]
Regarding the query string at the end of the url: ?myoption=yes: Laravel provides access to query string parameters by using the Input::get("Param") function. You do not have to designate query string params in your routes, they can simply be accessed in your controller method.
The "nicer" way is resource controllers - which of course may be combined with route prefixing and filters (e.g. authentication filters), etc.
Inside the methods of resource controllers, you can retrieve additional input (the option in the query string of your example) and process it with validation and whatever you want.
I have an application in Cakephp. In my front-end, it only responses for one request and I have used usual CakeRequest() class, and in my back-end, as far as using extjs, I have defined another Request and Response Class for multi-requests and multi-responses. but I have problem in distinguishing between them. I mean where and when one of them is executed. the default cakephp index.php file for front-end is
$Dispatcher->dispatch(new CakeRequest(), new CakeResponse(array('charset' => Configure::read('App.encoding'))));
and for back-end is
$Dispatcher->dispatch(new TestRequestCollection(...
but I don't know the if clause between them.
To what if clause are you referring to?
CakePHP is not designed to use different request classes in the index.php. Not sure what you are doing here. You might want to go the same route I went with Bancha and create a second frontend controller which does different a dispatching.
I am developing RESTful with php. Currently I have started coding with MVC design pattern. In which the view files are acting as an interface. An interface which isn't showing any graphical UI but it has all the request handling logic.
Now, my question is the way I am coding is correct or there is a better way to create RESTful api in php?
My inspiration is based on JavaEE application model. In which we have Entity classes as model, Java beans as controllers and Remote Interface is the the list of method which gets called from client (kind of a view).
Am I on right track?
A good example for building a RESTful API in a PHP based MVC framework can be found at http://www.chrisdanielson.com/2009/09/02/creating-a-php-rest-api-using-the-zend-framework/.
This example extends a class in Zend Framework called the Zend_Rest_Controller which simplifies this process. You can have a look at the source code to see how they do it and if it gives you an ideas on how to make your own implementation.
To answer your question though, you should have controllers acting as the interface. So if you send a POST request to myapp.com/comment (where comment is the controller), it knows you are trying to add a new comment. If you send a GET request to the same URL, it knows you want all of the comments, and if you send a GET request to myapp.com/comment/4 it knows you want to get the comment with ID 4. Your views should have nothing to do with the internal functionality of your API.
You can use any existing RESTful PHP MVC framework, like Yii or Kohana both are very light and natively support RESTful applications.
For your existing application, MVC model states that all the requests and logic handling should be done by the Controllers not the views. Things are usually done in one of two ways here:
(1) Controller has a special method to respond to each type of requests and acts differently As seen in RubyOnRails (mainly at the end of each controller action)
respond_to do |format|
format.html
format.xml { render :xml => #events}
format.json { render :json => #events}
end
(2) Controller detects the current requested format and changes that entire theme/layout to, say, a JSON theme (All layouts/views receive the same data). This is my current implementation and it goes like:
$format is any of [html,json,xml] (detected from url suffix)
$controller->layout = "$format";
$controller->render($viewFile, $object);
view file in HTML Layout
<div id='model>
<h1><?=$object->title?></h1>
<p><?=$object->description?></p>
</div>
View file in JSON layout
echo json_encode($object);
View file in XML layout
/** Loop and build XML tree */
I did a bunch of webinars on API Facade Design Patterns. Hope you will find the concepts useful irrespective of the underlying technology you use to implement it. Please can find it here
http://youtu.be/n8B-K3iJ7b4
http://youtu.be/MRxTP-rQ-S8
http://youtu.be/aJBhVm4BbCI
Apigility is a Zend Framework 2 based project designed soley for the purpose of creating REST and RPC services.
https://apigility.org/
Out of the box you're given an easy way to get started with MySQL and OAuth2 for authentication.