I am the developer of this framework, let’s isolate some explanations
Inphinit requires a class with 7 functions
Actually not required, all are optional, basically the class Rest
checks which class methods are valid in:
private static $valids = array(
'index' => array( 'GET', '/' ),
'create' => array( 'GET', '/create' ),
'store' => array( 'POST', '/' ),
'show' => array( 'GET', '/{:[^/]+:}' ),
'edit' => array( 'GET', '/{:[^/]+:}/edit' ),
'update' => array( array('PUT', 'PATCH'), '/{:[^/]+:}' ),
'destroy' => array( 'DELETE', '/{:[^/]+:}' ),
);
And then comparing it to what you set:
$route = empty(self::$valids[$method]) ? false : self::$valids[$method];
The class Rest
is just a facilitator, it creates the routes as you configure the class of your controller
It is possible to disable them?
Yes, they are optional
So much is a facilitator that without it you could create your API manually (if so desired), for example session-driven to simulate data recording and reading:
<?php
use Inphinit\Routing\Route;
use Inphinit\Http\Request;
use Inphinit\Http\Response;
session_start();
// Cria os dados iniciais se não existirem `Inphinit\Experimental\Rest`
if (empty($_SESSION['exemplo'])) {
$_SESSION['exemplo'] = array(
array( 'id' => 1, 'name' => 'Guilherme Costamilam' ),
array( 'id' => 2, 'name' => 'Wallace Maxters' ),
array( 'id' => 3, 'name' => 'Carlos Bacco' )
);
}
function getItemById($id)
{
foreach ($_SESSION['exemplo'] as $key => $value) {
if ($value['id'] == $id) return $key;
}
return false;
}
// Lista todas "entidades"
Route::set('GET', '/api/', function () {
Response::type('application/json');
return json_encode($_SESSION['exemplo']);
});
// Adiciona uma nova "entidade"
Route::set('POST', '/api/', function () {
$raw = stream_get_contents( Request::raw() );
$json = null;
if ($raw) {
$json = json_decode($raw);
}
//Pega a ultima ID
$lastId = max(array_column($_SESSION['exemplo'], 'id'));
//Nova ID
$newId = ++$lastId;
if (empty($json->name)) {
$status = 400;
$response = array( 'response' => 'Dados inválidos' );
} else {
$_SESSION['exemplo'][] = array(
'id' => $newId,
'name' => $json->name
);
$status = 201;
$response = array( 'response' => true );
}
Response::status($status);
Response::type('application/json');
return json_encode($response);
});
// Lê uma entidade especifica
Route::set('GET', '/api/{:\d+:}', function ($id) {
Response::type('application/json');
$key = getItemById($id);
if (empty($_SESSION['exemplo'][$key])) {
Response::status(404);
$response = array( 'response' => 'Não encontrado' );
} else {
$response = $_SESSION['exemplo'][$key];
}
return json_encode($response);
});
// Deleta uma entidade especifica
Route::set('DELETE', '/api/{:\d+:}', function ($id) {
Response::type('application/json');
$key = getItemById($id);
if (empty($_SESSION['exemplo'][$key])) {
Response::status(404);
$response = array( 'response' => 'Não encontrado' );
} else {
unset($_SESSION['exemplo'][$key]);
$response = array( 'response' => true );
}
return json_encode($response);
});
This would be an example of a very basic API, of course all done "manually", now creating a controller and using the class Inphinit\Experimental\Rest
would look something like this:
./system/main.php
<?php
use Inphinit\Experimental\Routing\Rest;
Rest::create('Photo');
./system/application/Controller/Pessoas.php
<?php
namespace Controller;
use Inphinit\Response;
class Pessoas
{
//Ao instanciar a classe (ocorre internamente dentro de )
public function __construct()
{
session_start();
// Cria os dados iniciais se não existirem
if (empty($_SESSION['exemplo'])) {
$_SESSION['exemplo'] = array(
array( 'id' => 1, 'name' => 'Guilherme Costamilam' ),
array( 'id' => 2, 'name' => 'Wallace Maxters' ),
array( 'id' => 3, 'name' => 'Carlos Bacco' )
);
}
}
// acesse via GET http://site.com/
public function index()
{
return json_encode($_SESSION['exemplo']);
}
// acesse via POST http://site.com/
public function store()
{
$raw = Request::raw();
$json = null;
if ($raw) {
$json = json_decode($raw);
}
if (empty($json->name)) {
$status = 400;
$response = array( 'response' => 'Dados inválidos' );
} else {
$status = 201;
$response = array( 'response' => true );
}
Response::status($status);
Response::type('application/json');
return json_encode($response);
}
// acesse via GET http://site.com/show/<ID>
public function show($id)
{
$key = getItemById($id);
if (empty($_SESSION['exemplo'][$key])) {
Response::status(404);
$response = array( 'response' => 'Não encontrado' );
} else {
$response = $_SESSION['exemplo'][$id];
}
return json_encode($response);
}
// acesse via DELETE http://site.com/<ID>
public function destroy($id)
{
$key = getItemById($id);
if (empty($_SESSION['exemplo'][$key])) {
Response::status(404);
$response = array( 'response' => 'Não encontrado' );
} else {
unset($_SESSION['exemplo'][$key]);
$response = array( 'response' => true );
}
return json_encode($response);
}
private function getItemById($id)
{
foreach ($_SESSION['exemplo'] as $key => $value) {
if ($value['id'] == $id) return $key;
}
return false;
}
}
This whole explanation was to understand what can "facilitate", now let’s explain the specific methods create
and edit
, I personally believe that these methods are only needed in environments like web pages or that will render something like HTML forms.
For example in these methods would have forms that would make requests fetch()
or XmlHttpRequest
that would access the methods store
and update
.
Now another scenario, imagine you are creating a Javafx application, and want to use FXML (read https://docs.oracle.com/javafx/2/api/javafx/fxml/doc-files/introduction_to_fxml.html), then the create
:
public function create($id)
{
Response::type('application/xml');
return '<?xml version="1.0" encoding="UTF-8"?>
<?import java.net.*?>
<?import javafx.geometry.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.text.*?>
<GridPane fx:controller="fxmlexample.FXMLExampleController"
xmlns:fx="http://javafx.com/fxml" alignment="center" hgap="10" vgap="10"
styleClass="root">
<padding><Insets top="25" right="25" bottom="25" left="25"/></padding>
<Label text="Digite o nome do novo usuário:"
GridPane.columnIndex="0" GridPane.rowIndex="1"/>
<TextField
GridPane.columnIndex="1" GridPane.rowIndex="1"/>
<HBox spacing="10" alignment="bottom_right"
GridPane.columnIndex="1" GridPane.rowIndex="4">
<Button text="Sign In"
onAction="#handleSubmitButtonAction"/>
</HBox>
</GridPane>';
}
And in the edit
would return something like:
public function edit($id)
{
Response::type('application/xml');
$name = null;
foreach ($_SESSION['foobarbaz'] as $key => $value) {
if ($value['id'] == $id) {
$name = $value['name'];
break;
}
}
if (!$name) {
Response::status(404);
$response = '<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Label?>
<Label text="Não encontrado!"/>';
} else {
$response = '<?xml version="1.0" encoding="UTF-8"?>
<?import java.net.*?>
<?import javafx.geometry.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.text.*?>
<GridPane fx:controller="fxmlexample.FXMLExampleController"
xmlns:fx="http://javafx.com/fxml" alignment="center" hgap="10" vgap="10"
styleClass="root">
<padding><Insets top="25" right="25" bottom="25" left="25"/></padding>
<Label text="Edite o nome do usuário:"
GridPane.columnIndex="0" GridPane.rowIndex="1"/>
<TextField text="' . $name . '"
GridPane.columnIndex="1" GridPane.rowIndex="1"/>
<HBox spacing="10" alignment="bottom_right"
GridPane.columnIndex="1" GridPane.rowIndex="4">
<Button text="Sign In"
onAction="#handleSubmitButtonAction"/>
</HBox>
</GridPane>';
}
return $response;
}
If you have any fault with the Fxmls let me know, it’s not my area
These are hypothetical examples only, many things I based on existing frameworks to make it easier for people to adapt and learn quickly the use of the framework, trying to make it a little easier
I must make something clear about the namespace Inphinit\Experimental
, everything in it is geared towards suggestions (not that others do not accept), I accept any suggestion and I will analyze it calmly, but to summarize if you have suggestions on how to work with REST in the framework can contact me wherever you want, facebook, Telegram and Linkedin.
To summarize, if you only want a JSON or XML API you just create the methods like this:
class Usuarios
{
// acesse via GET http://site/photo/
public function index()
{
...
}
// acesse via GET http://site/photo/create
public function create()
{
...
}
// acesse via POST http://site/photo/
public function store()
{
...
}
// acesse via GET http://site/photo/show/<digite o nome ou ID>
public function show($id)
{
...
}
// acesse via PUT http://site/photo/<digite o nome ou ID>
public function update($id)
{
...
}
// acesse via DELETE http://site/photo/<digite o nome ou ID>
public function destroy($id)
{
...
}
}
This way the routes GET /create
and GET /<id ou algo assim>/edit
nay will be available
Extra: Group routes
You can isolate the API by a "sub-route" with Inphinit\Experimental\Group
something like:
<?php
use Inphinit\Experimental\Routing\Rest;
use Inphinit\Experimental\Routing\Group;
Group::create()->path('/api/')->then(function () {
Rest::create('Usuarios');
});
Can isolate by domains:
//Acessivel via foobar.com ou www.foobar.com
Group::create()->domain('{:www|:}.foobar.com')->then(function () {
Route::set('GET', '/', 'Foo:index');
Route::set('GET', '/abc', 'Foo:bar');
Route::set('GET', '/xyz/', 'Foo:baz');
});
//Acessivel via api.foobar.com
Group::create()->domain('api.foobar.com')->then(function () {
Rest::create('Usuarios');
});
What would be another way to isolate what are forms and the like and isolate what are Apis
It’s quite likely that
create
andedit
follow a logic similar to that of Laravel: create the view layer, for displaying forms.– Wallace Maxters
@Wallacemaxters seems strange to me, I have always connected the REST the modern architecture, where the backend only traffic the data, IE, the registration and alteration form screens are not part of the responsibility of the back
– Costamilam
I agree with you. But the controller is responsible for rendering the view. In a scenario where the front end is in the framework, it makes sense to do so. Now if you just use the framework to serve REST, really, the methods would make no sense. It remains the creator to give an option to leave these optional methods.
– Wallace Maxters
@Wallacemaxters they only add/exist if the Controller has the methods
create()
andedit()
, if in the class there is no then it would be similar to useRoute::resource('photos', 'Usuarios')->except([ 'create', 'edit' ]);
of Laravel, the difference is that you don’t need to execute an except, just don’t create the methods in the class and FW takes care of this.– Guilherme Nascimento