I'm building a small TV Show library in laravel. I want to include an API as well for possible future expansion. When I started I had 2 controllers for what should have been a single controller: API controller and the web frontend controller. They both handled the same logic. That's obviously not good practice since that leads to duplicate code.
How would I make my application API centric? I was thinking of having an API controller which handles all the logic and returns a JSON object and a regular controller for the frontend which simply takes the JSON object returned by the API controller and passes it to a view (after, if any, processing). If that's the way to go, how would I retrieve said object? A GET request to my own server?
If you are developing API, than it should be on a separate server to take off load form main web server.
If it is on a same server, why would you send a request to it as you can develop a class that can act as API and call it inside your web controllers.
Later on when you decide to have separate server, just wrap API contoller around that class.
<?php
$myApi = new MyApi();
$myApi->setParmas( $paramsArray );
$myApi->doLogic();
echo $myApi->asJson();
// or make API class that can handle one liner
echo MyApi::factory($_GET)->doLogic()->toJson();
?>
Make your Laravel application an API endpoint and use a frontend framework or some frontend routing and templating libraries to handle the client-side.
Name space the api with /api and versions i.e. /api/v1
This allows you to easily develop with many different technologies and not have to rewrite your backend, as it is just an API endpoint.
It can then serve your webapp, an iOS app, an Android app, etc. because all it does is handle data, validation, requests, security, etc.
You can use repositories to get required data, then you may pass it to a View to make a webpage, or just print the JSON, for the API, this way you can prevent duplicate code.
Route::get('/latest', function () {
return View::make('latest', Movie::latest());
}
Route::get('/api/latest', function () {
return json_encode(Movie::latest());
}
Check this video for more info about repositories in Laravel: http://vimeo.com/53029232
In larval 5.3 you may want to consider using larval passport which provides a really nice way to consume your own api's from the front end without needing to worry too much about the authentication https://laravel.com/docs/5.3/passport#consuming-your-api-with-javascript
There is also a nice video on this on laracasts https://laracasts.com/series/whats-new-in-laravel-5-3/episodes/13
Related
I have an MVC PHP web application that needs to call a REST API. I'm unclear on whether I should be calling the API from my controller or from the model? Looking at various resources I'm getting mixed information. I assume it should be from the Model since all I'm doing is dealing with data and passing that up to the controller correct?
Some more details to clarify. I do have full control over the REST API which I'm in the process of building and is in PHP as well. The API however will also be leveraged by an iOS and Android companion app built by my team and a few other apps running on proprietary devices.
The original plan was that the web app was not going to leverage the API and just go straight to the DB to cut out any overhead, but several debates later and I'm leaning toward using the API.
I'd call from the model if the REST resource is a representation of the model, or if you're going to need this functionality across multiple controllers.
Call from the controller if it is not 100% specific to the model representation, or if it is only important to the controller/view you're working with.
You should call the web API from the Controller. The Model is how the data is passed from the Controller to the View. The Model should only have data and no business logic.
When you get the response from the web API, the data should be put into the Model and passed to the View.
The Model, the View and the Controller make up the MVC pattern. The Controller is responsible for putting the data in to the Model, which it passes to the View. The View takes the Model and displays the data, as it has been told to. There is no Business Logic in either the Model or the View.
Ideally, you would put your API code into a class library, that the controller uses. This allows you to separate the business logic out of the website and into a separate component.
I need to send a push message from Urban Airship. To do this I have to send an API request from CakePHP.
My question: where should i put the code for the API request in CakePHP? In the model or in the controller? Where is the correct place for this?
I follow Neil Crookes' idea of keeping the logic in the datasource. An API is really just a datasource, after all. Then, models are introduced as the various endpoints the API has. For example, I have a Stripe plugin that follows this model. A StripeCustomer model then has a $path variable that the datasource uses as the endpoint.
This model has several benefits:
API calls are integrated with the ORM - so they look like regular model finds and saves
You can utilize built in validation, callbacks, behaviors, etc.
Very DRY and therefore easy to debug and test
I am planning to use a architecture (MVC = PHP->Yii) where I will be using REST API based architecture for native site (main web app) and non-native (apps such as iPhone, BB, WAP etc).
No my question is it advisable to use View-Controller (HTML+User Requests) (For Main Site) with Controller-Model (Request/Response+DB) (for API) and same API platform will be used for non-native apps, or should I use full MVC for main site and build separate platform for APIs. This is because I don't want additional HTTP (cURL) overhead for main site.
Update:
#karmakaze
That's the though with me but still I have to write RestControllers because there is lots of code involved. So anyway we ends up having two different controllers e.g.
UserController extends CController {
actionRegister() {
...Some calculations
.
.
Instead of making Calls to model We will use call controller i.e.
$userRest = new UserRestController();
/*
* This will return json data or php obj depending on params passed or
* may raise an exception
*/
$userRest->actionCreate($param1, $param2);
// Process data obtained.
}
}
or is there any other way around?
If it fits your needs, you may build a front-end based on some JavaScript libraries like AngularJs, BackBone.JS or any other MVC JavaScript library.
This way you should build only one RESTful API in Yii, as the back-end of your app.
This solution, however, lets something uncovered: it will be hard to make the application crawlable.
The perspective of the question made me to understand that it is relatively important to render the HTML on the server side. I am thinking at this solution:
make normal MVC app, including controllers and views
Use any of the following ticks:
a GET parameter that will be false by default, but ture when it is an API call:
Check this example:
// in a controller:
public function actionView($id, $api=false) {
// some calculations, getting the $model variable
if ($api) {
echo $model->json_output(); // you can implement it in components/model.php or generate the json output some other way
} else {
render('view', array('model'=>$model));
}
}
a subdomain called, for instance, api (you'll have api.yourapp.tld),
or use another HTTP parameter from the request to determine if it is an API call or not.
Any of these version will bring a way of verifying if the client requests a JSON/XML response (API call) or HTML for the browser.
This way you avoid the headache of building separate controllers for the API and the main site.
Note It is not required to do this trick for actions when they simply render a form - it is useless.
Note 2 You can use the latter method to render the requests with _request_fragment and assume that every request is an API call unless $_GET['_request_fragment'] is specified. Like this you can make an AngularJs, Blackbone.js app crawlable with Yii.
UPDATE The _request_fragment is specified here, and it is used by most search engines to crawl AJAX web applications.
You can use the same for both native and non-native app, it will also reduce you work at development time as well update or change ur logic.... I do have so many experience with such situation..
Use full MVC for main web app and reuse the same Models and Controllers to build the REST API. There are extensions which will do this automagically if you follow Yii conventions while building the main web app. Just search REST in the Yii extensions. We'll be doing the same for our mobile apps. Currently investigating RESTFullYii.
Backbone tutorials I have read implement some type of a mini-framework (i.e. Slim) with a RESTful architecture performing CRUD on a server db, like this. The Backbone docs state you need a RESTful api, which I believe is due to the Backbone Route and Sync functionality that keeps models up to date, which is a huge aspect of my choosing to use Backbone.
For example, the line below maps a faux url (route) to the 'addWine' function (within a Slim api):
$app->post('/wines', 'addWine');
Assumption 1: If I have a (PHP) CMS backend (and not a mini-framework) I assume I could simply replace the 2nd parameter (addWine) with my own CMS class method call and return a json object.
Assumption 2 But I would not be able to directly call that same class method from a link in the html without causing backbone to lose state and thus it's ability to sync the model data (and remember the browsers history).
Assumption 3 In that case, I will need to use the Slim api and route backbone urls through (Slim) RESTful CRUD calls in order to access my CMS database to keep backbone happy.
If those assumptions are correct, then it would seem backbone is intercepting those HTTP calls - which leaves me wondering how the whole RESTful + Backbone relationship works. Can you explain some of it?
If my assumptions are incorrect, then I need more help than I thought. Can you help with that?
Thanks
I can't speak intimately to your three assumptions, but as for your final question -- Backbone does not "intercept" HTTP calls -- it constructs them, just as any other javascript library would to create an AJAX request.
Backbone is relatively agnostic to your server side language/framework. Here is what Backbone expects any time "sync" is called:
Backbone's sync function uses different HTTP request types based on which method was called. These different HTTP request types are:
POST
GET
PUT
DELETE
Your framework needs to support all of the above to support the "out of the box" functionality of Backbone. This means that you must specify all of the above routes within your application in order to work with Backbone.
One other thing to note is the "create" and "update" method does not carry post data with the request specifically -- instead it sends a content body with a json digest of the data and expects the server side to properly parse a JSON object and deal with it appropriately.
I say yes to all three assumptions and also agree with #Andy Baird.
Also, the only problem to your project is how to notify Backbone that you have updated the database and you would like it to update itself in the front-end. I can only see two solutions:
1) using Javascript's setInterval() - if you do not need the front end to be updated immediately on DB update, you can check for changes every 1 minute, Backbone knows to only update what has changed and add new stuff but of course this is not healthy to the server if you have 1k active people making repeated request every minute
2) using SocketIO or similar service - this way you can send from the server to Backbone either the entire list of modifications to your DB or a simple 'Please refresh, new stuff waiting'. Check this discussion.
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.