SlideShare a Scribd company logo
1 of 40
Download to read offline
Bootstrap REST APIs
with Laravel 5
Elena Kolevska
www.speedtocontact.com
Automated lead response system / call center in a
browser
Why REST?
SOAP!
POST http://www.stgregorioschurchdc.org/cgi/websvccal.cgi HTTP/1.1
Accept-Encoding: gzip,deflate
Content-Type: text/xml;charset=UTF-8
SOAPAction: "http://www.stgregorioschurchdc.org/Calendar#easter_date"
Content-Length: 479
Host: www.stgregorioschurchdc.org
Connection: Keep-Alive
User-Agent: Apache-HttpClient/4.1.1 (java 1.5)
<?xml version="1.0"?>
<soapenv:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:cal="http://www.stgregorioschurchdc.org/Calendar">
<soapenv:Header/>
<soapenv:Body>
<cal:easter_date soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/
encoding/">
<year xsi:type="xsd:short">2014</year>
</cal:easter_date>
</soapenv:Body>
</soapenv:Envelope>
Basic Authentication
ALWAYS use SSL!
$header = 'Authorization: Basic' . base64_encode($username . ':' . $password);
Authentication Middleware
<?php namespace AppHttpMiddleware;
use AppUser;
use Closure;
use IlluminateContractsAuthGuard;
use IlluminateSupportFacadesHash;
class AuthenticateOnce {
public function handle($request, Closure $next)
{
if ($this->auth->onceBasic())
return response(['status'=>false, 'message'=>'Unauthorized'], 401, ['WWW-Authenticate' =>'Basic']);
return $next($request);
}
protected $routeMiddleware = [
'auth' => 'AppHttpMiddlewareAuthenticate',
'auth.basic' => 'IlluminateAuthMiddlewareAuthenticateWithBasicAuth',
'auth.basic.once' => 'AppHttpMiddlewareAuthenticateOnce',
'guest' => 'AppHttpMiddlewareRedirectIfAuthenticated',
];
<?php
Route::group(array('prefix' => 'api/v1/examples','middleware' => 'auth.basic.once'), function () {
Route::get('1', 'ExamplesController@example1');
Route::get('2', 'ExamplesController@example2');
Route::get('3', 'ExamplesController@example3');
Route::get('4', 'ExamplesController@example4');
Route::get('5', 'ExamplesController@example5');
Route::get('6', 'ExamplesController@example6');
Route::get('7', 'ExamplesController@example7');
Route::get('8', 'ExamplesController@example8');
});
app/Http/routes.php
Response format
HTTP/1.1 200 OK
Content-Type: application/json 

Connection: close 

X-Powered-By: PHP/5.6.3

Cache-Control: no-cache

Date: Fri, 13 Apr 2015 16:37:57 GMT 

Transfer-Encoding: Identity

{"status":true,"data":{"k1":"value1","k2":"value2"},"message":"Zero imagination for funny
messages"}
Most common HTTP status codes
• 200 OK
• 201 Created
• 204 No Content
• 400 Bad Request
• 401 Unauthorized
• 403 Forbidden
• 404 Not Found
• 409 Conflict
• 500 Internal Server Error
Response message format
{
"status": true,
"data": {
"k1": "value1",
"k2": "value2"
},
"message": "Zero imagination for funny messages"
}
{
"status": false,
"errors": {
"e1": "Nope, it can't be done",
"e2": "That can't be done either"
},
"error_code": 12345,
"message": "Zero imagination for funny messages"
}
Controller hierarchy
app/Http/Controllers/ApiController.php
<?php
namespace AppHttpControllers;
use IlluminateHttpRequest;
use IlluminateRoutingResponseFactory;
use IlluminateAuthGuard;
use AppUser;
class ApiController extends Controller{
public $response;
public $request;
public $auth;
public function __construct(ResponseFactory $response, Request $request, Guard $auth)
{
$this->response = $response;
$this->request = $request;
$this->auth = $auth;
$this->currentUser = $this->auth->user();
}
}
app/Http/Controllers/ApiController.php
public function respond($data, $response_message, $status_code = 200) {
//If this is an internal request we only return the data
if ($this->request->input('no-json'))
return $data;
$message['status'] = true;
if (isset($data))
$message['data'] = $data;
if (isset($message))
$message['message'] = $response_message;
if (isset($error_code))
$message['error_code'] = $error_code;
return $this->response->json($message, $status_code);
}
app/Http/Controllers/ExamplesController.php
<?php namespace AppHttpControllers;
class ExamplesController extends ApiController {
/**
* Send back response with data
*
* @return Response
*/
public function example1()
{
$sample_data_array = ['k1'=>'value1', 'k2'=>'value2'];
return $this->respond($sample_data_array, 'Message');
}
}
app/Http/Controllers/ApiController.php
public function respondWithError($errors, $error_code, $status_code = 400) {
if (is_string($errors))
$errors = [$errors];
$message = [
'status' => false,
'errors' => $errors,
'error_code' => $error_code
];
return $this->response->json($message, $status_code);
}}
public function example3()
{
$error = "Can't be done";
return $this->respondWithError($error, 123, 500);
}
app/Http/Controllers/ExamplesController.php
app/Http/Controllers/ApiController.php
}
/**
* @param array $errors
* @param int $status_code
* @return Response
*/
public function respondWithValidationErrors($errors, $status_code = 400) {
$message = [
'status' => false,
'message' => "Please double check your form",
'validation_errors' => [$errors]
];
return $this->response->json($message, $status_code);
}
}
app/Http/Controllers/ApiController.php
public function respondCreated( $message = 'Resource created') {
return $this->respond($message, 201);
}
public function respondUnauthorized( $error_code, $message = 'You are not authorized for this') {
return $this->respondWithError($message, $error_code, 401);
}
public function respondNotFound( $error_code, $message = 'Resource not found') {
return $this->respondWithError($message, $error_code, 404);
}
public function respondInternalError( $error_code, $message = 'Internal error') {
return $this->respondWithError($message, $error_code, 500);
}
public function respondOk( $message = 'Done') {
return $this->respond(null, $message, 200);
}
Always use fake data
for testing
https://github.com/fzaninotto/Faker
<?php
use IlluminateDatabaseSeeder;
class UsersTableSeeder extends Seeder {
public function run()
{
Eloquent::unguard();
$faker = FakerFactory::create();
for($i=1; $i < 20; $i++ ){
$data = [
'name' => $faker->name,
'email' => $faker->email,
'password' => bcrypt('demodemo')
];
AppUser::create($data);
}
}
}
database/seeds/UsersTableSeeder.php
Setting up the repositories
app/Providers/RepoBindingServiceProvider.php
<?php
namespace AppProviders;
use IlluminateSupportServiceProvider;
class RepoBindingServiceProvider extends ServiceProvider {
public function register() {
$app = $this->app;
$app->bind('AppRepositoriesContractsUsersInterface', function()
{
$repository = new AppRepositoriesUsersRepository(new AppUser);
return $repository;
});
}
}
* Register the service provider in the list of autoloaded service providers in config/app.php
app/Repositories/BaseRepository.php
<?php
namespace AppRepositories;
use IlluminateDatabaseEloquentModel;
class BaseRepository {
public function __construct(Model $model) {
$this->model = $model;
}
public function create($data)
{
return $this->model->create($data);
}
public function find($id)
{
return $this->model->find($id);
}
public function delete($id)
{
return $this->model->destroy($id);
}
public function all()
{
return $this->model->all();
}
app/Repositories/BaseRepository.php
public function update($record, $data)
{
if (is_int($record)){
$this->model->find($record);
$id = $record;
} else {
$this->model = $record;
$id = $record->id;
}
return $this->model->where('id',$id)->update($data);
}
public function getById($id, $user_id = null, $with = null)
{
if (is_array($id)){
$result = $this->model->whereIn('id', $id);
}else{
$result = $this->model->where('id', $id);
}
if ($user_id)
$result->where('user_id', $user_id);
if ($with)
$result->with($with);
if (is_array($id)){
return $result->get();
return $result->first();
}
public function example5()
{
$data = App::make('AppRepositoriesContractsUsersInterface')->getById(3,null,['courses']);
return $this->respond($data,"All users");
}
{
"status": true,
"data": {
"id": 3,
"name": "Asia Towne DVM",
"email": "emmett42@welch.com",
"api_token":"543bjk6h3uh34n5j45nlk34j5k43n53j4b5jk34b5jk34",
"created_at": "2015-04-14 18:09:48",
"updated_at": "2015-04-14 18:09:48",
"courses": [
{
"id": 3,
"name": "Forro",
"pivot": {
"user_id": 3,
"course_id": 3
}
},
{
"id": 4,
"name": "Jiu Jitsu",
"pivot": {
"user_id": 3,
"course_id": 4
}
}
]
},
"message": "User with the id of 3"
}
app/Http/Controllers/ExamplesController.php
Data Transformers
You need them
<?php
namespace AppDataTransformers;
abstract class DataTransformer {
public function transformCollection($items, $method = 'transform')
{
return array_map([$this, $method], $items);
}
public abstract function transform($item);
}
app/DataTransformers/DataTransformer.php
<?php
namespace AppDataTransformers;
class UserTransformer extends DataTransformer{
public function transform($user)
{
return [
'id' => $user['id'],
'name' => $user['name'],
'email' => $user['email'],
];
}
}
app/DataTransformers/UserTransformer.php
{
"status": true,
"data": [
{
"id": 20,
"name": "Vance Jacobs",
"email": "callie.zieme@hotmail.com"
},
{
"id": 19,
"name": "Chesley Swift",
"email": "giovani72@schumm.com"
},
{
"id": 18,
"name": "Frederick Hilpert",
"email": "dameon.macejkovic@gmail.com"
}
],
"message": "Latest 3 users"
}
<?php
namespace AppDataTransformers;
class UserTransformer extends DataTransformer{
public function transform($user)
{
return [
'id' => $user['id'],
'name' => $user['name'],
'email' => $user['email'],
'courses' => (isset($user['courses']) && count($user['courses']))
? array_map([$this,'transformCourses'], $user['courses'])
: null,
];
}
public function transformCourses($course){
return [
'id' => $course['id'],
'name' => $course['name']
];
}
}
What about nested resources?
{
"status": true,
"data": [
{
"id": 20,
"name": "Vance Jacobs",
"email": "callie.zieme@hotmail.com",
"courses": null
},
{
"id": 19,
"name": "Chesley Swift",
"email": "giovani72@schumm.com",
"courses": [
{
"id": 2,
"name": "Samba"
},
{
"id": 3,
"name": "Forro"
}
]
},
{
"id": 18,
"name": "Frederick Hilpert",
"email": "dameon.macejkovic@gmail.com",
"courses": [
{
"id": 4,
"name": "Jiu Jitsu"
}
]
}
],
"message": "Latest 3 users"
}
Pretty error messages
public function render($request, Exception $e)
{
if ($e instanceof IlluminateDatabaseEloquentModelNotFoundException){
$message = [
'status' => false,
'error_code' => 2234,
'errors' => ["That resource doesn't exist"]
];
return response($message, 404);
}
if ($e instanceof SymfonyComponentHttpKernelExceptionNotFoundHttpException){
$message = [
'status' => false,
'error_code' => 1235,
'errors' => ["We don't have that kind of resources"]
];
return response($message, 404);
}
if ($e instanceof Exception){
$message = [
'status' => false,
'message' => $e->getMessage()
];
return response($message, $e->getCode());
}
return parent::render($request, $e);
}
}
app/Exceptions/Handler.php
STATUS 404 Not Found
{
"status": false,
"error_code": 1235,
"errors": [
"We don't have that kind of resources"
]
}
STATUS 404 Not Found
{
"status": false,
"error_code": 2234,
"errors": [
"That resource doesn't exist"
]
}
STATUS 418 I'm a teapot
{
"status": false,
"message": "I'm a teapot"
}
STATUS 500 Internal Server Error
{
"status": false,
"message": "Class 'User' not found"
}
Internal dispatcher
For your (probably) most important consumer
<?php
namespace AppHttp;
class InternalDispatcher {
public function release( $url, $method = 'GET', $input, $no_json) {
// Store the original input of the request
$originalInput = Request::input();
// Create request to the API, adding the no-json parameter, since it's an internal request
$request = Request::create($url, $method);
// Replace the input with the request instance input
Request::replace($input);
// Fetch the response
if ($no_json){
$content = Route::dispatch($request)->getContent();
$result = json_decode($content, 1);
}else{
$result = Route::dispatch($request)->getContent();
}
// Replace the input again with the original request input.
Request::replace($originalInput);
return $result;
}
public function withNoInput($url, $method = 'GET', $no_json = true){
$input = ['no-json'=>$no_json];
return $this->release($url, $method = 'GET', $input, $no_json);
}
}
app/Http/InternalDispatcher.php
STATUS 200 OK
{
"status": true,
"data": {
"latest_users": [
{
"id": 20,
"name": "Vance Jacobs",
"email": "callie.zieme@hotmail.com",
"courses": []
},
{
"id": 18,
"name": "Frederick Hilpert",
"email": "dameon.macejkovic@gmail.com",
"courses": []
}
],
"youngest_user": {
"id": 3,
"name": "Asia Towne DVM",
"email": "emmett42@welch.com",
"courses": [
{
"id": 3,
"name": "Forro"
},
{
"id": 4,
"name": "Jiu Jitsu"
}
]
}
},
"message": "Good data"
}
Thank you for listening!
Let the discussion begin :)

More Related Content

What's hot

Laravel Restful API and AngularJS
Laravel Restful API and AngularJSLaravel Restful API and AngularJS
Laravel Restful API and AngularJS
Blake Newman
 
Bullet: The Functional PHP Micro-Framework
Bullet: The Functional PHP Micro-FrameworkBullet: The Functional PHP Micro-Framework
Bullet: The Functional PHP Micro-Framework
Vance Lucas
 
Keeping it Small: Getting to know the Slim Micro Framework
Keeping it Small: Getting to know the Slim Micro FrameworkKeeping it Small: Getting to know the Slim Micro Framework
Keeping it Small: Getting to know the Slim Micro Framework
Jeremy Kendall
 

What's hot (20)

Web service with Laravel
Web service with LaravelWeb service with Laravel
Web service with Laravel
 
Laravel Restful API and AngularJS
Laravel Restful API and AngularJSLaravel Restful API and AngularJS
Laravel Restful API and AngularJS
 
Getting to know Laravel 5
Getting to know Laravel 5Getting to know Laravel 5
Getting to know Laravel 5
 
Laravel Beginners Tutorial 2
Laravel Beginners Tutorial 2Laravel Beginners Tutorial 2
Laravel Beginners Tutorial 2
 
Laravel 101
Laravel 101Laravel 101
Laravel 101
 
Creating REST Applications with the Slim Micro-Framework by Vikram Vaswani
Creating REST Applications with the Slim Micro-Framework by Vikram VaswaniCreating REST Applications with the Slim Micro-Framework by Vikram Vaswani
Creating REST Applications with the Slim Micro-Framework by Vikram Vaswani
 
Bullet: The Functional PHP Micro-Framework
Bullet: The Functional PHP Micro-FrameworkBullet: The Functional PHP Micro-Framework
Bullet: The Functional PHP Micro-Framework
 
Laravel - Website Development in Php Framework.
Laravel - Website Development in Php Framework.Laravel - Website Development in Php Framework.
Laravel - Website Development in Php Framework.
 
ACL in CodeIgniter
ACL in CodeIgniterACL in CodeIgniter
ACL in CodeIgniter
 
API Development with Laravel
API Development with LaravelAPI Development with Laravel
API Development with Laravel
 
Hello World on Slim Framework 3.x
Hello World on Slim Framework 3.xHello World on Slim Framework 3.x
Hello World on Slim Framework 3.x
 
Keeping it Small: Getting to know the Slim Micro Framework
Keeping it Small: Getting to know the Slim Micro FrameworkKeeping it Small: Getting to know the Slim Micro Framework
Keeping it Small: Getting to know the Slim Micro Framework
 
Workshop Laravel 5.2
Workshop Laravel 5.2Workshop Laravel 5.2
Workshop Laravel 5.2
 
Rails web api 开发
Rails web api 开发Rails web api 开发
Rails web api 开发
 
Connecting Content Silos: One CMS, Many Sites With The WordPress REST API
 Connecting Content Silos: One CMS, Many Sites With The WordPress REST API Connecting Content Silos: One CMS, Many Sites With The WordPress REST API
Connecting Content Silos: One CMS, Many Sites With The WordPress REST API
 
More to RoC weibo
More to RoC weiboMore to RoC weibo
More to RoC weibo
 
Keeping it small - Getting to know the Slim PHP micro framework
Keeping it small - Getting to know the Slim PHP micro frameworkKeeping it small - Getting to know the Slim PHP micro framework
Keeping it small - Getting to know the Slim PHP micro framework
 
Slim RedBeanPHP and Knockout
Slim RedBeanPHP and KnockoutSlim RedBeanPHP and Knockout
Slim RedBeanPHP and Knockout
 
Web services with laravel
Web services with laravelWeb services with laravel
Web services with laravel
 
Using the new WordPress REST API
Using the new WordPress REST APIUsing the new WordPress REST API
Using the new WordPress REST API
 

Viewers also liked

Nanoparticles drug delivery in cancer therapy
Nanoparticles drug delivery in cancer therapyNanoparticles drug delivery in cancer therapy
Nanoparticles drug delivery in cancer therapy
roydebolina278
 
0046352b60861f1df3000000.pdf
0046352b60861f1df3000000.pdf0046352b60861f1df3000000.pdf
0046352b60861f1df3000000.pdf
stoneshedadvisory
 
Brian Barrera Resume 5
Brian Barrera Resume 5Brian Barrera Resume 5
Brian Barrera Resume 5
Brian Barrera
 

Viewers also liked (20)

jQuery Keynote - Fall 2010
jQuery Keynote - Fall 2010jQuery Keynote - Fall 2010
jQuery Keynote - Fall 2010
 
How to restart windows 8
How to restart windows 8How to restart windows 8
How to restart windows 8
 
Nanoparticles drug delivery in cancer therapy
Nanoparticles drug delivery in cancer therapyNanoparticles drug delivery in cancer therapy
Nanoparticles drug delivery in cancer therapy
 
0046352b60861f1df3000000.pdf
0046352b60861f1df3000000.pdf0046352b60861f1df3000000.pdf
0046352b60861f1df3000000.pdf
 
Evaluation question 2
Evaluation question 2Evaluation question 2
Evaluation question 2
 
Presentación1
Presentación1Presentación1
Presentación1
 
Brian Barrera Resume 5
Brian Barrera Resume 5Brian Barrera Resume 5
Brian Barrera Resume 5
 
NAV CV,,,,,,,
NAV CV,,,,,,,NAV CV,,,,,,,
NAV CV,,,,,,,
 
Android operating system
Android operating systemAndroid operating system
Android operating system
 
Unit 3 standards presentation
Unit 3 standards presentationUnit 3 standards presentation
Unit 3 standards presentation
 
Digital Etiquette
Digital EtiquetteDigital Etiquette
Digital Etiquette
 
Каталог faberlic №6/2015
Каталог faberlic №6/2015Каталог faberlic №6/2015
Каталог faberlic №6/2015
 
2016 13 cat_ru
2016 13 cat_ru2016 13 cat_ru
2016 13 cat_ru
 
2016 14 cat_ru
2016 14 cat_ru2016 14 cat_ru
2016 14 cat_ru
 
Universal design - Towards a More Thorough Ethical and Theoretical Understan...
Universal design - Towards a More Thorough  Ethical and Theoretical Understan...Universal design - Towards a More Thorough  Ethical and Theoretical Understan...
Universal design - Towards a More Thorough Ethical and Theoretical Understan...
 
Cat 16-2016-01
Cat 16-2016-01Cat 16-2016-01
Cat 16-2016-01
 
Digital literacy
Digital literacyDigital literacy
Digital literacy
 
Avalon_Case_Study
Avalon_Case_StudyAvalon_Case_Study
Avalon_Case_Study
 
Welzijn, diversiteit & actorschap; Een introductie op de 'capability' benadering
Welzijn, diversiteit & actorschap; Een introductie op de 'capability' benaderingWelzijn, diversiteit & actorschap; Een introductie op de 'capability' benadering
Welzijn, diversiteit & actorschap; Een introductie op de 'capability' benadering
 
Pests infesting Fam. Solanaceae
Pests infesting Fam. SolanaceaePests infesting Fam. Solanaceae
Pests infesting Fam. Solanaceae
 

Similar to Bootstrat REST APIs with Laravel 5

Remedie: Building a desktop app with HTTP::Engine, SQLite and jQuery
Remedie: Building a desktop app with HTTP::Engine, SQLite and jQueryRemedie: Building a desktop app with HTTP::Engine, SQLite and jQuery
Remedie: Building a desktop app with HTTP::Engine, SQLite and jQuery
Tatsuhiko Miyagawa
 
Zendcon 2007 Api Design
Zendcon 2007 Api DesignZendcon 2007 Api Design
Zendcon 2007 Api Design
unodelostrece
 
PHP and Rich Internet Applications
PHP and Rich Internet ApplicationsPHP and Rich Internet Applications
PHP and Rich Internet Applications
elliando dias
 

Similar to Bootstrat REST APIs with Laravel 5 (20)

Unit testing after Zend Framework 1.8
Unit testing after Zend Framework 1.8Unit testing after Zend Framework 1.8
Unit testing after Zend Framework 1.8
 
Creating native apps with WordPress
Creating native apps with WordPressCreating native apps with WordPress
Creating native apps with WordPress
 
WordPress REST API hacking
WordPress REST API hackingWordPress REST API hacking
WordPress REST API hacking
 
Bag Of Tricks From Iusethis
Bag Of Tricks From IusethisBag Of Tricks From Iusethis
Bag Of Tricks From Iusethis
 
Building Lithium Apps
Building Lithium AppsBuilding Lithium Apps
Building Lithium Apps
 
Zend framework service
Zend framework serviceZend framework service
Zend framework service
 
Zend framework service
Zend framework serviceZend framework service
Zend framework service
 
Silex meets SOAP & REST
Silex meets SOAP & RESTSilex meets SOAP & REST
Silex meets SOAP & REST
 
I Phone On Rails
I Phone On RailsI Phone On Rails
I Phone On Rails
 
Fatc
FatcFatc
Fatc
 
Remedie: Building a desktop app with HTTP::Engine, SQLite and jQuery
Remedie: Building a desktop app with HTTP::Engine, SQLite and jQueryRemedie: Building a desktop app with HTTP::Engine, SQLite and jQuery
Remedie: Building a desktop app with HTTP::Engine, SQLite and jQuery
 
Zendcon 2007 Api Design
Zendcon 2007 Api DesignZendcon 2007 Api Design
Zendcon 2007 Api Design
 
関西PHP勉強会 php5.4つまみぐい
関西PHP勉強会 php5.4つまみぐい関西PHP勉強会 php5.4つまみぐい
関西PHP勉強会 php5.4つまみぐい
 
PHP and Rich Internet Applications
PHP and Rich Internet ApplicationsPHP and Rich Internet Applications
PHP and Rich Internet Applications
 
Why is crud a bad idea - focus on real scenarios
Why is crud a bad idea - focus on real scenariosWhy is crud a bad idea - focus on real scenarios
Why is crud a bad idea - focus on real scenarios
 
Doctrine For Beginners
Doctrine For BeginnersDoctrine For Beginners
Doctrine For Beginners
 
Silex Cheat Sheet
Silex Cheat SheetSilex Cheat Sheet
Silex Cheat Sheet
 
Silex Cheat Sheet
Silex Cheat SheetSilex Cheat Sheet
Silex Cheat Sheet
 
Unit testing zend framework apps
Unit testing zend framework appsUnit testing zend framework apps
Unit testing zend framework apps
 
Ch ch-changes cake php2
Ch ch-changes cake php2Ch ch-changes cake php2
Ch ch-changes cake php2
 

Recently uploaded

AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM TechniquesAI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
VictorSzoltysek
 
TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service provider
mohitmore19
 
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
Health
 
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICECHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
9953056974 Low Rate Call Girls In Saket, Delhi NCR
 

Recently uploaded (20)

The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...
The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...
The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...
 
Vip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS Live
Vip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS LiveVip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS Live
Vip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS Live
 
Microsoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdfMicrosoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdf
 
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
Direct Style Effect Systems -The Print[A] Example- A Comprehension AidDirect Style Effect Systems -The Print[A] Example- A Comprehension Aid
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
 
Exploring the Best Video Editing App.pdf
Exploring the Best Video Editing App.pdfExploring the Best Video Editing App.pdf
Exploring the Best Video Editing App.pdf
 
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
 
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
 
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM TechniquesAI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
 
Azure_Native_Qumulo_High_Performance_Compute_Benchmarks.pdf
Azure_Native_Qumulo_High_Performance_Compute_Benchmarks.pdfAzure_Native_Qumulo_High_Performance_Compute_Benchmarks.pdf
Azure_Native_Qumulo_High_Performance_Compute_Benchmarks.pdf
 
Introducing Microsoft’s new Enterprise Work Management (EWM) Solution
Introducing Microsoft’s new Enterprise Work Management (EWM) SolutionIntroducing Microsoft’s new Enterprise Work Management (EWM) Solution
Introducing Microsoft’s new Enterprise Work Management (EWM) Solution
 
TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service provider
 
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
 
8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech students8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech students
 
VTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learnVTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learn
 
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
 
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
 
Optimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVOptimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTV
 
10 Trends Likely to Shape Enterprise Technology in 2024
10 Trends Likely to Shape Enterprise Technology in 202410 Trends Likely to Shape Enterprise Technology in 2024
10 Trends Likely to Shape Enterprise Technology in 2024
 
Diamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with PrecisionDiamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with Precision
 
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICECHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
 

Bootstrat REST APIs with Laravel 5

  • 1. Bootstrap REST APIs with Laravel 5 Elena Kolevska
  • 2. www.speedtocontact.com Automated lead response system / call center in a browser
  • 4. SOAP! POST http://www.stgregorioschurchdc.org/cgi/websvccal.cgi HTTP/1.1 Accept-Encoding: gzip,deflate Content-Type: text/xml;charset=UTF-8 SOAPAction: "http://www.stgregorioschurchdc.org/Calendar#easter_date" Content-Length: 479 Host: www.stgregorioschurchdc.org Connection: Keep-Alive User-Agent: Apache-HttpClient/4.1.1 (java 1.5) <?xml version="1.0"?> <soapenv:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:cal="http://www.stgregorioschurchdc.org/Calendar"> <soapenv:Header/> <soapenv:Body> <cal:easter_date soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/ encoding/"> <year xsi:type="xsd:short">2014</year> </cal:easter_date> </soapenv:Body> </soapenv:Envelope>
  • 6. $header = 'Authorization: Basic' . base64_encode($username . ':' . $password);
  • 7.
  • 8. Authentication Middleware <?php namespace AppHttpMiddleware; use AppUser; use Closure; use IlluminateContractsAuthGuard; use IlluminateSupportFacadesHash; class AuthenticateOnce { public function handle($request, Closure $next) { if ($this->auth->onceBasic()) return response(['status'=>false, 'message'=>'Unauthorized'], 401, ['WWW-Authenticate' =>'Basic']); return $next($request); } protected $routeMiddleware = [ 'auth' => 'AppHttpMiddlewareAuthenticate', 'auth.basic' => 'IlluminateAuthMiddlewareAuthenticateWithBasicAuth', 'auth.basic.once' => 'AppHttpMiddlewareAuthenticateOnce', 'guest' => 'AppHttpMiddlewareRedirectIfAuthenticated', ];
  • 9. <?php Route::group(array('prefix' => 'api/v1/examples','middleware' => 'auth.basic.once'), function () { Route::get('1', 'ExamplesController@example1'); Route::get('2', 'ExamplesController@example2'); Route::get('3', 'ExamplesController@example3'); Route::get('4', 'ExamplesController@example4'); Route::get('5', 'ExamplesController@example5'); Route::get('6', 'ExamplesController@example6'); Route::get('7', 'ExamplesController@example7'); Route::get('8', 'ExamplesController@example8'); }); app/Http/routes.php
  • 10. Response format HTTP/1.1 200 OK Content-Type: application/json Connection: close X-Powered-By: PHP/5.6.3 Cache-Control: no-cache Date: Fri, 13 Apr 2015 16:37:57 GMT Transfer-Encoding: Identity {"status":true,"data":{"k1":"value1","k2":"value2"},"message":"Zero imagination for funny messages"}
  • 11. Most common HTTP status codes • 200 OK • 201 Created • 204 No Content • 400 Bad Request • 401 Unauthorized • 403 Forbidden • 404 Not Found • 409 Conflict • 500 Internal Server Error
  • 12. Response message format { "status": true, "data": { "k1": "value1", "k2": "value2" }, "message": "Zero imagination for funny messages" } { "status": false, "errors": { "e1": "Nope, it can't be done", "e2": "That can't be done either" }, "error_code": 12345, "message": "Zero imagination for funny messages" }
  • 14. app/Http/Controllers/ApiController.php <?php namespace AppHttpControllers; use IlluminateHttpRequest; use IlluminateRoutingResponseFactory; use IlluminateAuthGuard; use AppUser; class ApiController extends Controller{ public $response; public $request; public $auth; public function __construct(ResponseFactory $response, Request $request, Guard $auth) { $this->response = $response; $this->request = $request; $this->auth = $auth; $this->currentUser = $this->auth->user(); } }
  • 15. app/Http/Controllers/ApiController.php public function respond($data, $response_message, $status_code = 200) { //If this is an internal request we only return the data if ($this->request->input('no-json')) return $data; $message['status'] = true; if (isset($data)) $message['data'] = $data; if (isset($message)) $message['message'] = $response_message; if (isset($error_code)) $message['error_code'] = $error_code; return $this->response->json($message, $status_code); }
  • 16. app/Http/Controllers/ExamplesController.php <?php namespace AppHttpControllers; class ExamplesController extends ApiController { /** * Send back response with data * * @return Response */ public function example1() { $sample_data_array = ['k1'=>'value1', 'k2'=>'value2']; return $this->respond($sample_data_array, 'Message'); } }
  • 17.
  • 18. app/Http/Controllers/ApiController.php public function respondWithError($errors, $error_code, $status_code = 400) { if (is_string($errors)) $errors = [$errors]; $message = [ 'status' => false, 'errors' => $errors, 'error_code' => $error_code ]; return $this->response->json($message, $status_code); }} public function example3() { $error = "Can't be done"; return $this->respondWithError($error, 123, 500); } app/Http/Controllers/ExamplesController.php
  • 19.
  • 20. app/Http/Controllers/ApiController.php } /** * @param array $errors * @param int $status_code * @return Response */ public function respondWithValidationErrors($errors, $status_code = 400) { $message = [ 'status' => false, 'message' => "Please double check your form", 'validation_errors' => [$errors] ]; return $this->response->json($message, $status_code); } }
  • 21. app/Http/Controllers/ApiController.php public function respondCreated( $message = 'Resource created') { return $this->respond($message, 201); } public function respondUnauthorized( $error_code, $message = 'You are not authorized for this') { return $this->respondWithError($message, $error_code, 401); } public function respondNotFound( $error_code, $message = 'Resource not found') { return $this->respondWithError($message, $error_code, 404); } public function respondInternalError( $error_code, $message = 'Internal error') { return $this->respondWithError($message, $error_code, 500); } public function respondOk( $message = 'Done') { return $this->respond(null, $message, 200); }
  • 22. Always use fake data for testing https://github.com/fzaninotto/Faker
  • 23. <?php use IlluminateDatabaseSeeder; class UsersTableSeeder extends Seeder { public function run() { Eloquent::unguard(); $faker = FakerFactory::create(); for($i=1; $i < 20; $i++ ){ $data = [ 'name' => $faker->name, 'email' => $faker->email, 'password' => bcrypt('demodemo') ]; AppUser::create($data); } } } database/seeds/UsersTableSeeder.php
  • 24. Setting up the repositories
  • 25. app/Providers/RepoBindingServiceProvider.php <?php namespace AppProviders; use IlluminateSupportServiceProvider; class RepoBindingServiceProvider extends ServiceProvider { public function register() { $app = $this->app; $app->bind('AppRepositoriesContractsUsersInterface', function() { $repository = new AppRepositoriesUsersRepository(new AppUser); return $repository; }); } } * Register the service provider in the list of autoloaded service providers in config/app.php
  • 26. app/Repositories/BaseRepository.php <?php namespace AppRepositories; use IlluminateDatabaseEloquentModel; class BaseRepository { public function __construct(Model $model) { $this->model = $model; } public function create($data) { return $this->model->create($data); } public function find($id) { return $this->model->find($id); } public function delete($id) { return $this->model->destroy($id); } public function all() { return $this->model->all(); }
  • 27. app/Repositories/BaseRepository.php public function update($record, $data) { if (is_int($record)){ $this->model->find($record); $id = $record; } else { $this->model = $record; $id = $record->id; } return $this->model->where('id',$id)->update($data); } public function getById($id, $user_id = null, $with = null) { if (is_array($id)){ $result = $this->model->whereIn('id', $id); }else{ $result = $this->model->where('id', $id); } if ($user_id) $result->where('user_id', $user_id); if ($with) $result->with($with); if (is_array($id)){ return $result->get(); return $result->first(); }
  • 28. public function example5() { $data = App::make('AppRepositoriesContractsUsersInterface')->getById(3,null,['courses']); return $this->respond($data,"All users"); } { "status": true, "data": { "id": 3, "name": "Asia Towne DVM", "email": "emmett42@welch.com", "api_token":"543bjk6h3uh34n5j45nlk34j5k43n53j4b5jk34b5jk34", "created_at": "2015-04-14 18:09:48", "updated_at": "2015-04-14 18:09:48", "courses": [ { "id": 3, "name": "Forro", "pivot": { "user_id": 3, "course_id": 3 } }, { "id": 4, "name": "Jiu Jitsu", "pivot": { "user_id": 3, "course_id": 4 } } ] }, "message": "User with the id of 3" } app/Http/Controllers/ExamplesController.php
  • 30. <?php namespace AppDataTransformers; abstract class DataTransformer { public function transformCollection($items, $method = 'transform') { return array_map([$this, $method], $items); } public abstract function transform($item); } app/DataTransformers/DataTransformer.php <?php namespace AppDataTransformers; class UserTransformer extends DataTransformer{ public function transform($user) { return [ 'id' => $user['id'], 'name' => $user['name'], 'email' => $user['email'], ]; } } app/DataTransformers/UserTransformer.php
  • 31. { "status": true, "data": [ { "id": 20, "name": "Vance Jacobs", "email": "callie.zieme@hotmail.com" }, { "id": 19, "name": "Chesley Swift", "email": "giovani72@schumm.com" }, { "id": 18, "name": "Frederick Hilpert", "email": "dameon.macejkovic@gmail.com" } ], "message": "Latest 3 users" }
  • 32. <?php namespace AppDataTransformers; class UserTransformer extends DataTransformer{ public function transform($user) { return [ 'id' => $user['id'], 'name' => $user['name'], 'email' => $user['email'], 'courses' => (isset($user['courses']) && count($user['courses'])) ? array_map([$this,'transformCourses'], $user['courses']) : null, ]; } public function transformCourses($course){ return [ 'id' => $course['id'], 'name' => $course['name'] ]; } } What about nested resources?
  • 33. { "status": true, "data": [ { "id": 20, "name": "Vance Jacobs", "email": "callie.zieme@hotmail.com", "courses": null }, { "id": 19, "name": "Chesley Swift", "email": "giovani72@schumm.com", "courses": [ { "id": 2, "name": "Samba" }, { "id": 3, "name": "Forro" } ] }, { "id": 18, "name": "Frederick Hilpert", "email": "dameon.macejkovic@gmail.com", "courses": [ { "id": 4, "name": "Jiu Jitsu" } ] } ], "message": "Latest 3 users" }
  • 35. public function render($request, Exception $e) { if ($e instanceof IlluminateDatabaseEloquentModelNotFoundException){ $message = [ 'status' => false, 'error_code' => 2234, 'errors' => ["That resource doesn't exist"] ]; return response($message, 404); } if ($e instanceof SymfonyComponentHttpKernelExceptionNotFoundHttpException){ $message = [ 'status' => false, 'error_code' => 1235, 'errors' => ["We don't have that kind of resources"] ]; return response($message, 404); } if ($e instanceof Exception){ $message = [ 'status' => false, 'message' => $e->getMessage() ]; return response($message, $e->getCode()); } return parent::render($request, $e); } } app/Exceptions/Handler.php
  • 36. STATUS 404 Not Found { "status": false, "error_code": 1235, "errors": [ "We don't have that kind of resources" ] } STATUS 404 Not Found { "status": false, "error_code": 2234, "errors": [ "That resource doesn't exist" ] } STATUS 418 I'm a teapot { "status": false, "message": "I'm a teapot" } STATUS 500 Internal Server Error { "status": false, "message": "Class 'User' not found" }
  • 37. Internal dispatcher For your (probably) most important consumer
  • 38. <?php namespace AppHttp; class InternalDispatcher { public function release( $url, $method = 'GET', $input, $no_json) { // Store the original input of the request $originalInput = Request::input(); // Create request to the API, adding the no-json parameter, since it's an internal request $request = Request::create($url, $method); // Replace the input with the request instance input Request::replace($input); // Fetch the response if ($no_json){ $content = Route::dispatch($request)->getContent(); $result = json_decode($content, 1); }else{ $result = Route::dispatch($request)->getContent(); } // Replace the input again with the original request input. Request::replace($originalInput); return $result; } public function withNoInput($url, $method = 'GET', $no_json = true){ $input = ['no-json'=>$no_json]; return $this->release($url, $method = 'GET', $input, $no_json); } } app/Http/InternalDispatcher.php
  • 39. STATUS 200 OK { "status": true, "data": { "latest_users": [ { "id": 20, "name": "Vance Jacobs", "email": "callie.zieme@hotmail.com", "courses": [] }, { "id": 18, "name": "Frederick Hilpert", "email": "dameon.macejkovic@gmail.com", "courses": [] } ], "youngest_user": { "id": 3, "name": "Asia Towne DVM", "email": "emmett42@welch.com", "courses": [ { "id": 3, "name": "Forro" }, { "id": 4, "name": "Jiu Jitsu" } ] } }, "message": "Good data" }
  • 40. Thank you for listening! Let the discussion begin :)