Yii - Adding RESTFull API to webapp - php

I have an existing app that was built on the Yii Framework for managing wine cellars. I used the standard Gii utility to create the initial CRUD controllers/models/views. I've significantly modified the code to meet my needs for navigation, look & feel and functionality. I'm now beginning the design for a companion mobile (android) app that will need to consume and create some of the data (get a list of wines in my cellar - GET, add a new wine to the cellar - POST) that can be used while out shopping/wine-tasting. I don't intend to expose all the models/controller options as web services, only a specific set of functions.
My question is really a design issue. Should I add the API methods to the existing CRUD controllers or should I create a new "API Controller" for each of the models (or a single apiController is another option I've seen)? My thinking is separate API controllers. This would allow me to update/deploy API specific changes more easily and to logically compartmentalize that interface. This API will need to be authenticated and I will probably implement OAuth in a future release.
BTW, I've looked at the RESTFullYii extension and I haven't been able to grok exactly how it works. I'd really love to see a working example app not just code snippets.

I suggest you to create a new controller. For example ApiController. You put all your actions such as actionAddWine. So you can call this action like:
http://example.com/index.php?r=api/addWine
The advantage of doing this, is that you have all your models, and you just need to interact with your modes via REST. In order to create a simple REST api you can check the following document which is really simple explained.
How-To: Create a REST API
If you do like the mentioned article, You can send the response to client simply using _sendResponse() method.
Another thing is to do authentications and similar things which can is readily attainable using your controller's init() method.
Another way is to create a module for your application. If you want to completely divide your API from your other codes you can create a module. You can create modules with GII. The advantage of module is that you can separate your sections. For example your actions will be:
http://example.com/index.php?r=api/wine/add
in above url you are calling an action in api module, and wine controller which its name is add.
Note that you can use your models in module by importing them.

Yes, go for separate controllers. You may even want to set up a separate application that shares some of your apps models and config but also allows for a more separate feel.
Also with planning how you will version your Api, as it is likely to need to change down the road while still needing to support your older Android app

Related

PHP - Structuring a Slim3 web application using MVC and understanding the role of the model

I’m trying to create an authentication system in php with the Slim3 framework along with the Twig template system, and for the database I’m using MySQL with PDO. I’m also trying to implement it using a model view controller design pattern. However I’m having difficulty understanding how to use an MVC structure for a web application. I’ve looked at a plethora of explanations on the web and there doesn’t seem to be a clear cut answer. A lot of people say to to use a php framework such as Laravel, Symfony or CodeIgniter as they apparently employ an MVC like structure. However I would much rather keep things simple and to write the code manually rather than using a framework.
Currently there are two interpretations of MVC that I see. The first one being depicted in this diagram:
The other interpretation I’ve seen is this: (which is taken from this YouTube video)
I have done my research. Questions and answers such as this and this have been helpful. But I’m still not sure how I might structure my own applications, specifically indentifying and understanding the model aspect of MVC. I’ll now explain the register process of my authentication app. So you have an idea how my code is works.
Firstly I have an SQLQueries class that simply puts a series of SQL statements into functions. I then have a SQLWrapper class that has functions that can for example store a new users details inside the database. This class also calls functions from the SQLQueries class. I also have a ValidateSanitize class that has functions that cleans user input as well as checking if user input is valid in the form. These three classes I think are part of the model aspect of MVC but I'm not sure. I see a lot of other tutorials using a ‘User Model class’ but I can’t find the need for one in my application.
My views are simply Twig templates that display html, such as the homepage, register, login etc. I then have controllers. I intend to have multiple controllers that do different things. For now I’ve only implemented the AuthController which is responsible for Registering and Signing a user in.
So the first thing the AuthController does is to display the register form in a function called getRegisterForm. Once the user has submitted the form the postRegisterForm function takes that user input and assigns it to tainted variables.
public function postRegisterForm($request, $response)
{
$arr_tainted_params = $request->getParsedBody();
$tainted_email = $arr_tainted_params['email']; it a variable
$tainted_username = $arr_tainted_params['username'];
$tainted_password = $arr_tainted_params['password'];
$tainted_password_confirm = $arr_tainted_params['password_confirm'];
Next all of the three previous classes as well as the database details are instantiated so their functions can be used in the AuthController:
$sanitizer_validator = $this->container->ValidateSanitize;
$sql_wrapper = $this->container->SQLWrapper;
$sql_queries = $this->container->SQLQueries;
$db_handle = $this->container->get('dbase');
The tainted user details are then cleaned with the sanitize_input function. The cleaned user details are then fed into the validate functions to make sure they don’t trigger any validation violations. The password is also hashed here:
$cleaned_email = $sanitizer_validator->sanitize_input($tainted_email, FILTER_SANITIZE_EMAIL);
$cleaned_username = $sanitizer_validator->sanitize_input($tainted_username, FILTER_SANITIZE_STRING);
$cleaned_password = $sanitizer_validator->sanitize_input($tainted_password, FILTER_SANITIZE_STRING);
$cleaned_password_confirm = $sanitizer_validator->sanitize_input($tainted_password_confirm, FILTER_SANITIZE_STRING);
$hashed_cleaned_password = password_hash($cleaned_password, PASSWORD_DEFAULT);
$sanitizer_validator->check_email_exists($cleaned_email);
$sanitizer_validator->validate_email($cleaned_email);
$sanitizer_validator->validate_username($cleaned_username);
$sanitizer_validator->validate_password($cleaned_password);
$sanitizer_validator→validate_password_confirm($cleaned_password_confirm);
Finally there is an if statement that checks to see if all validation error messages are empty. If they are we provide the SQLWrapper class with the database details as well as a SQLQueries class object. We then insert the users details into the database by calling the SQLWrapper classes store-details function. Finally we direct the user to the login page, so the user can sign into their newly registered account.
if ($sanitizer_validator->get_validate_messages('email_error') == ' ' && $sanitizer_validator->get_validate_messages('username_error') == ' '
&& $sanitizer_validator->get_validate_messages('password_error') == ' ' && $sanitizer_validator->check_passwords_match($cleaned_password, $cleaned_password_confirm ) == true
&& $sanitizer_validator->check_email_exists($cleaned_email) == false)
{
$sql_wrapper->set_db_handle($db_handle);
$sql_wrapper->set_sql_queries($sql_queries);
$sql_wrapper->store_details($cleaned_email, $cleaned_username, $hashed_cleaned_password);
return $response→withRedirect($this→container→router→pathFor('login'));
}
However if any of the validate error messages are not blank, then we call the SanitiseValidate display_validate_messages which simply sets the messages into a session to be displayed on the register twig template. We then redirect back to the register page so the user can see the validation error messages.
else
{
$sanitizer_validator->display_validate_messages();
return $response->withRedirect($this->container->router->pathFor('register'));
}
}
So based on this structure of a user registering an account. Does this adhere to a clean simple MVC structure or do some changes need to be made? Do any of my classes take the role of a model? Any suggestions and tips regarding my structure will be appreciated.
The full application can be seen on my GitHub if that would be helpful. Note that this version is slightly older than the sample code I used in this question.
Indeed, there are multiple approaches regarding how the MVC pattern should be applied in web applications. This multitude of variants is the result of the simple fact, that the original MVC pattern - developed for desktop applications (by Trygve Reenskaug, in 1979) - can not be applied as is to the web applications. Here is a little description. But, from this set of approaches, you can choose one which best complies with your requirements. Maybe you'll try more of them before you'll make your mind. Though, at some point, you'll know which one fits to your vision.
In the following diagrams I tried to present my chosen approach on the web MVC workflow - mainly inspired by Robert Martin's presentation Keynote: Architecture the Lost Years (licensed under a Creative Commons Attribution ShareAlike 3.0).
In general, you could think of a web MVC application as composed of the following parts:
Domain model (e.g. model, e.g. model layer);
Service layer (optional);
Delivery mechanism;
Other components (like own libraries, etc).
1) The domain model should consist of the following components:
Entities (e.g. domain objects) and value objects. They model the business rules in terms of properties and behavior and, being application-independent, can be used by multiple (types of) applications.
(Data) mappers and, optional, repositories. These components are responsible with the persistence logic.
External services. They are used to perform different tasks involving the use of external/own libraries (like sending emails, parsing documents, etc).
Further, the domain model could be split into two parts:
a) Domain model abstraction. This would be the only space of the model layer accessed by the components of the delivery mechanism, or by the services of the service layer - if one is implemented:
Entities and value objects;
(Data) mapper abstractions and, optional, repository abstractions;
Abstractions of external services.
Note: By abstractions I mean interfaces and abstract classes.
b) Domain model implementation. This space would be the one in which the implementations of the different domain model abstractions (see a) would reside. The dependency injection container (as part of the delivery mechanism) will be responsible with passing instances of these concrete classes as dependencies - as constructor arguments, for example - to the other components of the application (like controllers, views, services, etc).
2) Service layer (optional): Technically, the components of the delivery mechanism could directly interact with the elements of the domain model. Though such interactions involve (a lot of) operations, specific only to the model, not to the delivery mechanism. Therefore, a good choice is to defer the execution of these operations to service classes (e.g. services), as part of the so-called service layer. The delivery mechanism components will then use only these services to access the domain model components.
Note: The service layer can, actually, be seen as part of the model layer. In my diagrams bellow I preferred to display it as a layer residing outside the model. But, in the file system example, I put the corresponding folder in the domain space.
3) The delivery mechanism sums up the constructs used to assure the interaction between the user and the model layer's components. By user I don't mean a person, but an interface with which a person can interact - like a browser, a console (e.g. CLI), a desktop GUI, etc.
Web server: parses the user request through a single point of entry (index.php).
Dependency injection container: provides the proper dependencies to the different components of the application.
HTTP message (e.g. HTTP request and HTTP response) abstraction (see PSR-7: HTTP message interfaces).
Router: matches the request components (HTTP method and URI path) against the components of each route (HTTP method and pattern) in a predefined list of routes and returns the matched route, if found.
Front controller: matches the user request against a route and dispatches it to a certain controller and/or view action.
Controllers. They write (e.g. perform create, update and delete operations) to the model layer and (should) expect no results. This can happen by directly interacting with the components defined in the domain model, or, preferably, by only interacting with the service classes.
Views. They should be classes, not template files. They can receive a template engine as dependency. They only fetch data (e.g. perform read operations) from the model layer. Either by directly interacting with the components defined in the domain model, or, preferably, by only interacting with the service classes. Also, they decide which result (like a string), or template file content, will be displayed to the user. A view action should always return a HTTP response object (maybe as defined by the PSR-7 specification), whose body will be before-hand updated with the mentioned result or template file content.
Template files. Should be kept as simple as possible. The whole presentation logic should happen only in the view instances. So, the template files should contain only variables (be they pure PHP ones, or presented with the used template engine syntax) and, maybe, some simple conditional statements, or loops.
Response emitter: reads the body of the HTTP response instance returned by the view and prints it.
4) Other components. As wished. For example some libraries developed by your own. Like an implementation of the PSR-7 abstraction.
How I chose to dispatch the user request:
As you see in the diagrams above, the front controller dispatches the user request not only to a controller action (in order to update the domain model), but also to a view action (in order to read and display the updated state/data from the model layer). Kind of a splitted dispatch. This can be relatively easy achieved by assigning the controller action and the view action to each route (like bellow), and telling the front controller to call them successively:
<?php
use MyApp\UI\Web\Application\View;
use MyApp\UI\Web\Application\Controller;
// Note: $this specifies a RouteCollection to which the route is added.
$this->post('/upload', [
'controller' => [Controller\Upload::class, 'uploadFiles'],
'view' => [View\Upload::class, 'uploadFiles'],
]);
This approach gives flexibility in regard to the user request dispatch. For example, the name of the view action can be different from the name of the controller action. Or, in order to only fetch model layer data, you don't need to dispatch the user request to a controller, but only to a view. Therefore you don't need to assign a controller action in the route at all:
<?php
use MyApp\UI\Web\Application\View;
$this->get('/upload', [View\Upload::class, 'listFiles']);
File system structure example:
myapp/domain: folder containing the domain model classes and the services. This directory could be brought into the "myapp/web/src" folder, but it shouldn't, because the model layer and the service layer are not part of the delivery mechanism.
myapp/web: folder containing the delivery mechanism classes. Its name depicts the type of application - can be a web app, a cli app, etc.
myapp/web/src:
Resources:
*) Sandro Mancuso : An introduction to interaction-driven design
*) The ones listed in an older answer of mine.
*) The tutorials presented by Alejandro Gervasio:
Building a Domain Model – An Introduction to Persistence Agnosticism
Building a Domain Model – Integrating Data Mappers
Handling Collections of Aggregate Roots – the Repository Pattern
An Introduction to Services
*) The example on the Slim 3 page: Action-Domain-Responder with Slim.
There is a course where you get walked through making MVC with slim 3. Ill link it here : https://codecourse.com/courses/slim-3-authentication . Hope this helped, its a really easy to follow course and you learn alot.

Is it possible to separate Controller and View in RESTful Symfony app?

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

Laravel 4 RESTful API resource controllers

Im developing a Laravel 4 RESTful JSON application.
The application is based around resource controllers bound with repositories / interfaces using Laravel 4's amazing IoC abilities.
Currently i have the following resources:
Users
Events
Activities
Although i have come to a point in the application development where i need to represent a "dashboard" that will be displaying a mixture of these resources in an "activity feed".
As this does not relate to a discreet resource should i be creating a standard DashboardController class? and how would i fit this into my current Model / Controller / Interface / Repository ... setup?
( as a side note the reason im developing it as a RESTful JSON API is that the application will have three interfaces web, iOS app, Android app.)
This kind of question always come when we try to build a RESTful application. You have two options :
You try to abstract the situation to link a page to an existing resource (for example a user#show page displaying the activity of this user and not the user itself).
You create a dedicated controller, wich could be RESTful, not linked to a specific resource.
I try to use the first solution when I can but it's generally impossible to build an entire app with this pattern for two reasons : some pages can't be link to a resource, even with a lot of abstraction skills, and generally we have more pages or services than REST verbs * resources.
In your case, I would have created a DashboardController. It can be RESTfull if you just create an index method, for example, and it's not really in conflict with your global design.

Send Push from CakePHP

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

RESTful API design pattern while creating API with php

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.

Categories