-
-
Notifications
You must be signed in to change notification settings - Fork 2
9. Helpers , Forms & REST API
This framework provides a certain number of capabilities that are meant to accelerate, to some extent, some of the basic logic that is redundant in every project. Some of those are global helper methods that can be used across the framework, others are specific to HTML Forms. Last but not least, we will show how this framework is already prebuilt to handle api calls without any extra coding.
- Framework helper methods
function view($viewName, $viewData = array()); // returns a view that uses the Pug template viewName with the data sent to it `viewData`
function redirect($url); // redirects to another local route
function api($viewData = array()); // returns a view suitable for api result
function request(); // retrieves the Request object and you perform any Request operation on it
function connect(); // connects to the database with the credentials defined in the settings
function currentRoute(); // returns the current Route
function httpRequest($url, $method, $data, $headers); // performs an http request, mainly used to send http requests to external apis
function sendMail($recipients, $emailContent, $from); // sends an email from the host defined in the env file
- Global Variables & Session helper methods
function saveInSession(Object $input, String $sessionVariableName); // saves any data type into a define session variable
function clearFromSession(String $sessionVariableName); // clears a session variable
function session($key, $value = null); // Gets or sets a session variable. When a value is specified it saves it. Otherwise, it retrieves it.
function scripts($key, $value = null); // Gets or sets a script stored in the session. When a value is specified it saves it. Otherwise, it retrieves it.
function copyright($value = null); // Gets or sets the copyright for your application to be used on any page. When a value is specified it saves it. Otherwise, it retrieves it.
function keywords($value = null); // Gets or sets the keywords associated with your application to be used on any page. When a value is specified it saves it. Otherwise, it retrieves it.
function metadata($pairs = null); // Gets or sets the metadata of a page. When a key/value pair is specified it will make the change and return the full metadata array
function terminateSession($url); // Destroys a session and redirects to a specified url when the session is destroyed
function getGlobalInformation($superGlobal = 'session'); // Gets PHP Super Globals $_GET, $_POST, $_FILES . By default, it gets $_SESSION
- String & Array helper methods
function generateToken($size = 12); // generates a random string of hexadecimals of a specified size
function findKey($array, $keySearch); // finds a key in a multi-dimensional array
function recursive_filter(Array &$array, Array $allowed); // filters an array based on a set of allowed keys
function loadConstantFromArray($array); // create PHP constants out of an array of key/value pairs
function isJson($string); // Checks if a string is JSON format
function sanitize($string); // performs a basic html sanitization of a string
function parsePath($path); // returns an array of the different parts of a path
function startWith($haystack, $needle); // checks if a haystack starts with a needle and returns it without the needle
function endWith($haystack, $needle); // checks if a haystack ends with a needle and returns it without the needle
function singularize($word); // returns the singular of a word by simply getting rid of the last character
function rearrange($arr); // returns a new array arranged by index
function arraySort($array, $attribute, $sort = SORT_DESC); // sorts a multi-dimensional associative array by a specified key
- Time Methods
function getRelativeTime($datetime, $depth=1); //returns relative time such as 1 day ago, 11 hours ago etc.
function now(); // returns current time in a mysql datetime format
- Encrypting Methods
function encryptDecrypt($action, $data, $key = APP_KEY); // action is 'encrypt' or 'decrypt' data based on a specified key. The default key is the APP_KEY defined in the .env
function generateKey($size = 32); // returns a random base64encoded string of a specified size
- Authentication Methods
function authorize($user); // use this method upon your login mechanism to authorize user
function authorized(); // checks if the user within a session is valid and authorized to perform actions
function unauthorize(); // use this method upon your logout mechanism to unauthorize all users
function user(); // returns the logged in user
function guard($permissionAttribute, $acceptedPermission, $loginUrl = '/'); // checks if user is permitted to use controller, otherwise redirect to the specified url
function logout($redirectUrl = '/'); // logs out an authenticated user and redirects to the specified url
- Image Manipulations
This framework uses a powerful third-party library for simple server-side image manipulations called SimpleImage by Claviska. This library can be immediately used in this framework by calling the imageCanva()
method:
$image = imageCanva(); // returns a SimpleImage object
A SimpleImage object gets returned by this method and all the powerful features of the library can now be used.
Check the full SimpleImage library here
This framework provides 2 major capabilities that allow your HTML forms to 1) Send PUT
and DELETE
requests
and 2) Secure requests again Cross-Site Request Forgery (CSRF)
HTML forms do not support PUT
and DELETE
. The framework does this for you from the moment you include a hidden _method
field in the form with a value of PUT
or DELETE
. This is called method spoofing.
This can be achieved using regular HTML:
<form action="/books" method="POST">
<input type="hidden" name="_method" value="PUT">
</form>
Or, using Pug directives that will do it automatically for you:
form(action="/books", method="POST")
=methodField('PUT')
Cross-Site Request Forgery is a type of attack that forces the user to execute an unwanted action on a web application where they are already authenticated. This usually comes from the fact that the server does not validate if the form from which the request was made is coming from the same session that the user is currently using.
In order to remedy to this, this framework provides the capability of signing the HTML Form
and it makes sure that on the server-side the signature is validated.
This can be achieved using regular HTML:
<form action="/books" method="POST">
<input type="hidden" name="_token" value="<session ID goes here">
</form>
Or, using a Pug directive that will do it automatically for you:
form(action="/books", method="POST")
=csrf()
A REST API or more appropriately, a RESTful API uses the fundamentals of a REST (Representational State Transfer) communication protocol to break down a transaction
received through HTTP and translate them into small modules that your application can make sense of and act on.
RESTful APIs take advantage of HTTP methodologies. They use GET
to retrieve data. They use POST
to create a resource. They use DELETE
to delete a resource. They use PUT
to update a resource.
In the Routing
section, we explained how this framework deeply relies on such a protocol to route a Request
to a corresponding Controller
action. It is therefore already built-in and ready to receive API calls using the same routes that your application uses.
The most effective way to test the API is to use a service like Postman. Postman is a great tool that allows to create GET
, POST
, PUT
and DELETE
requests without any extra coding.
We will use the example of the book application throughout.
1. API Authorization: API access must be authorized. The purpose of an API is to open up your services for third-parties to use them. There needs to be a way in your RESt-API to provide authorization for access. Caligrafy does this for you in a seamless way. By providing you with the tools to generate API tokens that sign all HTTP requests to your server even if you want your services to be openly accessible to any party.
-
Single API key for public use Caligrafy provides you with an easy way to generate an APP_KEY and an API_KEY from the terminal using Caligrafer. From the terminal, run
./caligrafer.php generatekeys
orphp caligrafer.php generatekeys
. Caligrafer will give you a pair of key/value pairs to put in your.env
file. -
Generate Multiple API keys for distribution If you have an APP_KEY and API_KEY already defined in your
.env
file or if you created them through Caligrafer, you might need to generate more API_KEY(s) to hand over to third-parties. You can do this with Caligrafer. From the terminal, run./caligrafer.php generateapikey
orphp caligrafer.php generateapikey
. This will generate a new API_KEY for you to give away.
2. Enabling API Access:
In the /application/config/routing/web.php
, you will need to activate API access and define the routes. By default the API access is enabled through Auth::activateAPI()
. By commenting out the statement, you disable all API accesses.
try {
// Activate the API access
Auth::activateAPI();
Route::get('/books', 'BookController@readAll'); // returns all books in the database books table
Route::post('/books', 'BookController@create'); // expects a form with all book attributes to create a book record
Route::put('/books/{id}', 'BookController@update'); // expects a form with all the book attributes to update for book with specified id
Route::delete('/books/1', 'BookController@remove'); // deletes book with specified id
Route::run();
} catch(Exception $e) {
// error handling goes here
}
3.Create a Model: Create a books
table in your database and a Book
model.
If you need to know more about creating a
Model
, you can read further about it in the respective section of this documentation
4.Create a Controller:
In order to output a result, whether an HTML page or a JSON output, you need to return a View
from the Controller
. When you first start your project, you most likely don't have any HTML pages or Pug pages created. You however might want to test your api service. In order to help you achieve that, you can return a view that has a null
template name.
use Caligrafy\Controller;
class BookController extends Controller {
public function readAll()
{
$this->associate('Book', 'books'); // define the context
return view(null, $this->all()); // notice the null
}
public function create()
{
$this->associate('Book', 'books'); // define the context
$parameters = $this->request->parameters(); // get all the parameters posted
$book = new Book();
$book->title = isset($parameters['title'])? $parameters['title'] : $book->title;
$book->author = isset($parameters['author'])? $parameters['author'] : $book->author;
return view(null, $this->save($book));
}
public function update()
{
$this->associate('Book', 'books'); // define the context
$book = $this->find(); // finds the book from id specified in the URI
$parameters = $this->request->parameters(); // get all the parameters posted
$book->title = isset($parameters['title'])? $parameters['title'] : $book->title; // take the title only if it is set in the post
$book->author = isset($parameters['author'])? $parameters['author']: $book->author;
return view(null, $this->save($book));
}
public function remove()
{
$this->associate('Book', 'books'); // define the context
$book = $this->find(); // finds the book from id specified in the URI
return view(null, $this->delete());
}
}
In the future, when you have Pug template created, you just replace the null
with the name of the template. And guess what? this does not impact the output of your api.
If you need to know more about creating a
Controller
, you can read further about it in the respective section of this documentation
Several ways can be used to test the API. We recommend using Postman as an API client to avoid extra coding.
-
Headers: For all requests through
Postman
, you need to do the following: In theHeaders
tab, add an 'Accept' key and give it a value 'application/json'. This instructs the server that the client needs a JSON output. -
Authorization: For all requests, you need to add an
Authorization
header: In Postman, you can go to theAuthorization
tab and selectBearer Token
from theType
selector. You will need to enter theAPI_KEY
in theToken
field provided. -
GET and DELETE: For
GET
andDELETE
, you can test them without any additional settings. All you need to do is enter the respective URI for each. -
POST: For
POST
you need to provide inputs through theBody
of the request. There are different ways to do this in Postman-
Option 1 - In the
Body
tab, selectform-data
: this option allows you to mimic an HTML form that could support both text and files. You need to make sure that all the required inputs for the model are entered appropriately. If your application supports file uploading, then you would probably want to test the API using this option.After you add your
form-data
inputs, verify that in theHeaders
section, you have another keyContent-Type
that got added with value eithermultipart/form-data
orapplication/json
. If not, you should add it manually. -
Option 2 - In the
Body
tab, selectx-www-form-urlencoded
: this option allows you to send the entire content as a giant query string. This option could be used if you don't have large inputs (such as files) that need to be transferred to the server. Similarly, you need to make sure that all the required inputs for the model are entered appropriately. If your application supports file uploading, this option will not work.After you add your
x-www-form-urlencoded
inputs, verify that in theHeaders
section, you have another keyContent-Type
that got added with valueapplication/x-www-form-urlencoded
. If not, you should add it manually.
-
Option 3 - In the
Body
tab, selectraw
: this option allows you to send a raw file using the format of your choice. The format could be changed toText
orJSON
orXML
etc. by clicking on theText
dropdown. Then you could type directly in the body the content you want to send in the desired format.After you add your
raw
inputs in a format, verify that in theHeaders
section, you have another keyContent-Type
that got added with valueapplication/json
(if the format you chose was JSON).
-
-
PUT: For
PUT
, since our framework spoofs aPOST
method, options 1 and 2 above won't work. Only option 3 could work. If your application supports file uploading, then you should test the API as aPOST
and add a_method
key in theBody
that has the valuePUT
.