SlideShare ist ein Scribd-Unternehmen logo
1 von 40
Downloaden Sie, um offline zu lesen
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 :)

Weitere ähnliche Inhalte

Was ist angesagt?

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
 

Was ist angesagt? (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
 

Andere mochten auch

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
 

Andere mochten auch (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
 

Ähnlich wie 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
 

Ähnlich wie 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
 

Kürzlich hochgeladen

TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service provider
mohitmore19
 
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
 
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online ☂️
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online  ☂️CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online  ☂️
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online ☂️
anilsa9823
 
+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
 
CALL ON ➥8923113531 🔝Call Girls Badshah Nagar Lucknow best Female service
CALL ON ➥8923113531 🔝Call Girls Badshah Nagar Lucknow best Female serviceCALL ON ➥8923113531 🔝Call Girls Badshah Nagar Lucknow best Female service
CALL ON ➥8923113531 🔝Call Girls Badshah Nagar Lucknow best Female service
anilsa9823
 

Kürzlich hochgeladen (20)

SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AI
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AISyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AI
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AI
 
TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service provider
 
5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf
 
How To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.jsHow To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.js
 
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
 
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfLearn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
 
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
 
Microsoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdfMicrosoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdf
 
Unlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language ModelsUnlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language Models
 
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 ...
 
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
 
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsUnveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
 
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
 
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
 
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online ☂️
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online  ☂️CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online  ☂️
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online ☂️
 
+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...
 
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
 
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
 
CALL ON ➥8923113531 🔝Call Girls Badshah Nagar Lucknow best Female service
CALL ON ➥8923113531 🔝Call Girls Badshah Nagar Lucknow best Female serviceCALL ON ➥8923113531 🔝Call Girls Badshah Nagar Lucknow best Female service
CALL ON ➥8923113531 🔝Call Girls Badshah Nagar Lucknow best Female service
 
Software Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsSoftware Quality Assurance Interview Questions
Software Quality Assurance Interview Questions
 

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 :)