2_2_Application architecture - OpenISDM/VMS GitHub Wiki

VMS is a web application which users access the View through browser. The browser renders the HTML and CSS for the client and sends a HTTP request to RESTful API endpoint on server. When receiving the HTTP request, the server processes it and sends an appropriate response to the client.

vms architecture Architecture diagram

View

View provides navigation, rendering and submitting requests to the server.

  • Navigation: It helps users to go to correct page by links or menu and ensures that users can navigate to views for which they are authorized.
  • Submitting requests: It helps send requests to server.
  • Rendering: It helps client render HTML, display response from server and localize UI. (eg. show messages for users)

HTTP routing

HTTP routing tells VMS the URIs it should respond to and give it the controller to call when that URI is requested. It supports to versionize RESTful API and register middlewares in routes for filtering request before entering controllers.

All routes are defined in app/Http/routes.php file. It uses Dingo API for grouping and creating endpoints.

For example, VMS uses the following routing features from Dingo API.

  • Versionizing the RESTful API: $api->version()
  • Grouping endpoints: $api->group()
  • Creating endpoints: $api->post(), $api->get() and so on.
<?php

// ingore 

$api = app('Dingo\Api\Routing\Router');

// Version 1.0
$api->version('v1.0', function ($api) {

    $api->group(['middleware' => ['check.header']], function ($api) {

        // Register
        $api->post('register', 'App\Http\Controllers\Api\V1_0\VolunteerAuthController@register');
        
    });

    $api->group(['middleware' => ['check.header', 'api.auth']], function ($api) {

        // Retrive volunteer's profile
        $api->get('users/me', 'App\Http\Controllers\Api\V1_0\VolunteerProfileController@showMe');

    });

});

HTTP middleware

HTTP middleware is responsible for filtering HTTP request. For example, before a request enters the Closure, the check.header middleware which is defined in app/Http/Kernel.php checks the HTTP headers. If the HTTP headers is not validated, the middleware will responses a error message to client.

$api->group(['middleware' => ['check.header']], function ($api) {

});

HTTP request

HTTP request helps retrieve input data. Furthermore, it supports authorization and input validation by creating a request class.

For example, in app/Http/Requests/Api/V1_0/CreateOrUpdateHyperlinksRequest.php class, the class contains authorize() and rules() for checking if the user has authorized to create/update the hyperlinks in the project or not and defining the validation rules respectively.

<?php

namespace App\Http\Requests\Api\V1_0;

use App\Http\Requests\AbstractJsonRequest;
use App\Project;
use Gate;

class CreateOrUpdateHyperlinksRequest extends AbstractJsonRequest
{
    /**
     * Determine if the user is authorized to make this request.
     *
     * @return bool
     */
    public function authorize()
    {
        $projectId = $this->route('projectId');

        $project = Project::findOrFail($projectId);

        return Gate::allows('update', $project);
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules()
    {
        return [
            'create.*.name'=> 'required',
            'create.*.link' => 'required|url',
            'update' => 'array',
            'update.*.id' => 'required|exists:hyperlinks,id',
            'update.*.name' => 'required',
            'update.*.link' => 'required|url'
        ];
    }
}

Controllers

Controller is invoked via HTTP routing for processing requests and handling logic. The Controllers are stored in app/Http/Controllers directory.

Controller is able to type-hint dependencies on methods or constructor to obtain the instance. For example, the store() method type-hints ExperienceRequest class to get the instance.

class VolunteerExperienceController extends BaseAuthController
{
    public function store(ExperienceRequest $request)
    {
        // ingore
        
        $experience = new Experience($request->all());
    }
}

Models

Models provide a convenience way to work with database without writing SQL command. Each model corresponds with a table. For example, the Volunteer model corresponds with volunteers table. It also contains the relationship with other models.

Query builders

Although, using Models to manipulate database is more convenience that writing SQL command, models lacks some features, like LEFT JOIN. Hence, Query builder provides interface to execute SQL command.

Exception handlers

As application encounters an exception, it should response an error message smoothly. The exception handler implements by Dingo API Exception Handler. It defines each exception response content and format in app/Providers/ApiErrorHandlerServiceProvider.php

Transformers

Transformers helps output structural and consistent format to client. They exists in app/Transformers/*.php. All transformers inheritance League\Fractal\TransformerAbstract and include transform() method for returning the structural format.

Policies

The policies are parts of authorization. It controls each user's action for resource.