SlideShare uma empresa Scribd logo
1 de 53
REST API 
Development and 
Testing 101 
By Samantha Geitz
A bit about me 
• 3 years of experience in web development 
• Now work for Packback 
• Background mostly in WordPress, a little bit of 
Rails, now use Laravel full-time 
• About 1 year experience building APIs
What we’re going to talk 
about tonight 
• “Typical” Laravel application / MVC 
• What is an API, and why should you care? 
• Shitty way to structure an API 
• Better way to structure an API 
• Demonstration of interacting with API
Our Application 
• Packback 
• Digital textbook rentals for 
college students 
• Resources: Users, Books 
• Users need to be able to “rent” 
books 
• https://github.com/samanthamic 
hele7/packback-rest-api-101 
• Two branches: master and 
api_with_fractal
Anatomy of the“Typical” 
Laravel Application 
• Model (Eloquent) + database 
• Controller + routes 
• View (Blade)
Problems! 
• What happens if we want to build an iOS/Android 
application with our data? 
• What happens if we want to use AngularJS or 
EmberJS? 
• What happens when we want to rebuild the front-end 
in a few years? 
• What happens if we want to let other companies work 
with our data? (Twitter API, Facebook API, etc.)
Solution: 
Let’s build an API! 
(Application Programming Interface)
What the hell does that even mean? 
• APIs only care about data - not what things look like 
• Data in, data out 
• JSON is what most of the cool kids are using 
• Keeps data types intact 
• You can also use XML if you like typing a lot 
• Turns everything into a string
<book> 
<id>1</id> 
<title>The Lord of the Rings</title> 
<author>J. R. R. Tolkien</author> 
</book> 
XML Example 
{ 
"book": { 
"id" : 1, 
"title": "The Lord of the Rings", 
"author": "J. R. R. Tolkien" 
} 
} 
JSON Example
Laravel makes it really easy 
• The client can access routes (which are basically just URLs) 
• Controllers handle logic (or call other classes to handle it for 
them) 
• Get data from or store data in database (via models) 
• ????? 
• PROFIT!!! 
• Return data as JSON
Stuff that we need to do 
• /createUser 
• /fetchUser 
• /setUserPassword 
• /updatePaymentInfo 
• /addBook 
• /getBook 
• /deleteBook 
• /addBooktoUser 
• /removeBook
Okay, this is getting 
kind of confusing
REST to the Rescue! 
• Representational State Transfer 
• Hopefully not what you’re doing if I’m boring you
It does CRUD 
• C - Create (POST) 
• R - Read (GET) 
• U - Update (PATCH/PUT) 
• D - Destroy (DELETE)
Stuff that we need to do 
(the RESTful way) 
• POST /users - Create a new user 
• GET /users - Get all users 
• GET /users/{id} - Get one user by ID 
• PATCH /users/{id} - Update a user by ID 
• DELETE /users/{id} - Delete a user by ID 
• POST /users/{id}/books/{id} - Add a book (or books) to a user 
• GET /users/{id}/books/ - Get a list of books for a specific user 
• etc.
Cool story, bro, but how 
do I actually build an API?
Step 1: Create Databases 
• Run database migrations (the same way as in a regular 
Laravel application) 
• Books, users, pivot 
php artisan migrate
app/database/migrations/2014_11_18_024437_create_users_table.<?php 
use IlluminateDatabaseSchemaBlueprint; 
use IlluminateDatabaseMigrationsMigration; 
class CreateUsersTable extends Migration { 
/** 
* Run the migrations. 
* 
* @return void 
*/ 
public function up() 
{ 
Schema::create('users', function(Blueprint $table) { 
$table->increments('id'); 
$table->string('email'); 
$table->string('name'); 
$table->string('password'); 
$table->timestamps(); 
}); 
} 
/** 
* Reverse the migrations. 
* 
* @return void 
*/ 
public function down() 
{ 
Schema::drop('users'); 
} 
}
app/database/migrations/2014_11_18_024939_create_books_table.<?php 
use IlluminateDatabaseSchemaBlueprint; 
use IlluminateDatabaseMigrationsMigration; 
class CreateBooksTable extends Migration { 
/** 
* Run the migrations. 
* 
* @return void 
*/ 
public function up() 
{ 
Schema::create('books', function(Blueprint $table) { 
$table->increments('id'); 
$table->string('isbn13'); 
$table->string('title'); 
$table->string('author'); 
$table->float('price'); 
$table->timestamps(); 
}); 
} 
/** 
* Reverse the migrations. 
* 
* @return void 
*/ 
public function down() 
{ 
Schema::drop('books'); 
} 
}
database/migrations/2014_11_18_025038_create_books_users_<?php 
use IlluminateDatabaseSchemaBlueprint; 
use IlluminateDatabaseMigrationsMigration; 
class CreateBooksUsersTable extends Migration { 
/** 
* Run the migrations. 
* 
* @return void 
*/ 
public function up() 
{ 
Schema::create('books_users', function(Blueprint $table) { 
$table->increments('id'); 
$table->integer('user_id')->unsigned(); 
$table->foreign('user_id')->references('id')->on('users'); 
$table->integer('book_id')->unsigned(); 
$table->foreign('book_id')->references('id')->on('books'); 
$table->timestamps(); 
}); 
} 
/** 
* Reverse the migrations. 
* 
* @return void 
*/ 
public function down() 
{ 
Schema::table('books_users', function(Blueprint $table) { 
$table->dropForeign('books_users_user_id_foreign'); 
$table->dropForeign('books_users_book_id_foreign'); 
}); 
Schema::drop('books_users'); 
}
Step 2: Seed data 
• Your life will be much easier if you fill your database with fake 
data 
• Faker is easy to use and has realistic fake data: 
https://github.com/fzaninotto/Faker 
• I generally do one seed file per table 
• Hook in database/seeds/DatabaseSeeder.php 
• Make sure you truncate every time the seeder is run or you will 
end up with a ton of data 
php artisan db:seed
Seed Users 
app/database/seeds/UserTableSeeder.php 
<?php 
use CarbonCarbon; 
use FakerFactory as Faker; 
class UserTableSeeder extends Seeder 
{ 
public function run() 
{ 
$faker = Faker::create(); 
DB::table('users')->truncate(); 
for ($i = 0; $i < 50; $i++) { 
DB::table('users')->insert([ 
'email' => $faker->email, 
'name' => $faker->name, 
'password' => Hash::make($faker->word), 
'created_at' => Carbon::now(), 
'updated_at' => Carbon::now() 
]); 
} 
} 
}
Seed Books 
app/database/seeds/BookTableSeeder.php 
<?php 
use CarbonCarbon; 
use FakerFactory as Faker; 
class BookTableSeeder extends Seeder 
{ 
public function run() 
{ 
$faker = Faker::create(); 
DB::table('books')->truncate(); 
for ($i = 0; $i < 50; $i++) { 
DB::table('books')->insert([ 
'isbn13' => $faker->ean13(), 
'title' => $faker->sentence, 
'author' => $faker->name, 
'price' => $faker->randomNumber(2) . '.' . $faker->randomNumber(2), 
'created_at' => Carbon::now(), 
'updated_at' => Carbon::now(), 
]); 
} 
} 
}
Seed User Books 
app/database/seeds/UserBookTableSeeder.php 
<?php 
use CarbonCarbon; 
class UserBookTableSeeder extends Seeder 
{ 
public function run() 
{ 
DB::table('books_users')->truncate(); 
for ($i = 1; $i < 51; $i++) { 
DB::table('books_users')->insert([ 
[ 
'user_id' => $i, 
'book_id' => $i, 
'created_at' => Carbon::now(), 
'updated_at' => Carbon::now() 
], 
[ 
'user_id' => $i, 
'book_id' => 51 - $i, 
'created_at' => Carbon::now(), 
'updated_at' => Carbon::now() 
] 
]); 
} 
} 
}
Step 3: Models 
• Very little difference compared to a more traditional 
Laravel app 
• Define a ManyToMany relationship between users and 
books
app/models/User.php 
class User extends Eloquent implements UserInterface, RemindableInterface { 
use UserTrait, RemindableTrait; 
protected $table = 'users'; 
protected $fillable = ['email', 'name', 'password']; 
protected $hidden = array('password', 'remember_token'); 
public function books() 
{ 
return $this->belongsToMany('Book', 'books_users'); 
} 
public function setPasswordAttribute($password) 
{ 
$this->attributes['password'] = Hash::make($password); 
} 
}
app/models/Book.php 
class Book extends Eloquent { 
protected $table = 'books'; 
protected $fillable = ['isbn13', 'title', 'author', 'price']; 
public function users() 
{ 
return $this->belongsToMany('User', 'books_users'); 
} 
}
Step 4: Routes 
• Should you use Laravel magic? (Route::resource() or 
Route::controller()) 
• Pros: Less code 
• Cons: Less code 
• It is generally clearer (to me) to explicitly define your 
routes (so you have a blueprint) 
• However, some people would disagree, so we’ll look 
at both
RESTful routes 
Option 1 (Less code) 
Route::group(['prefix' => 'api'], function() { 
Route::resource('users', 'UserController'); 
Route::resource('books', 'BookController'); 
}); 
This will automatically look for create, edit, 
index, show, store, update, and destroy 
methods in your controller.
RESTful Routes 
Option 2 (Explicit code) 
Route::group(['prefix' => 'api'], function() { 
Route::group(['prefix' => 'books'], function(){ 
Route::get('', array('uses' => 'BookController@index')); 
Route::get('{book_id}', array('uses' => 'BookController@show')); 
Route::post('', array('uses' => 'BookController@store')); 
Route::patch('{book_id}', array('uses' => 'BookController@update')); 
Route::delete('{book_id}', array('uses' => 'BookController@destroy')); 
}); 
Route::group(['prefix' => 'users'], function(){ 
Route::get('', array('uses' => 'UserController@index')); 
Route::get('{user_id}', array('uses' => 'UserController@show')); 
Route::get('{user_id}/books', array('uses' => 'UserController@showBooks')); 
Route::post('', array('uses' => 'UserController@store')); 
Route::post('{user_id}/books/{book_id}', array('uses' => 'UserController@storeBooks')); 
Route::patch('{user_id}', array('uses' => 'UserController@update')); 
Route::delete('{user_id}', array('uses' => 'UserController@destroy')); 
Route::delete('{user_id}/books/{book_id}', array('uses' => 'UserController@destroyBooks')); 
}); 
});
Let’s talk about status codes 
• Your API needs to send back a HTTP status code 
so that the client knows if the succeeded or failed 
(and if it failed, why) 
• 2xx - GREAT SUCCESS 
• 3xx - Redirect somewhere else 
• 4xx - Client errors 
• 5xx - Service errors
Some common status codes 
• 200 - generic OK 
• 201 - Created OK 
• 301 - Moved permanently and redirect to new location 
• 400 - Generic bad request (often used for validation on models) 
• 401 - Unauthorized (please sign in) 
• 403 - Unauthorized (you are signed in but shouldn’t be accessing this) 
• 404 - Does not exist 
• 500 - API dun goofed 
• 503 - API is not available for some reason 
• Plus lots more!
Step 5: Controllers 
• You will need (at least) 5 methods: index (get all), show (get 
one), store, update, destroy 
• What about create() and edit() (if you use 
Route::resource())? 
• You don’t need them if you’re building a pure data-driven 
API! 
• Use Postman (http://www.getpostman.com/) to interact 
with your API instead of Blade templates
Controllers / Index 
/** 
* Get all books 
* 
* @return Response 
*/ 
public function index() 
{ 
$books = Book::all(); 
return Response::json([ 
'data' => $books 
]); 
} 
/** 
* Get all users 
* 
* @return Response 
*/ 
public function index() 
{ 
$users = User::all(); 
return Response::json([ 
'data' => $users 
]); 
}
Controllers / Show 
/** 
* Get a single user 
* 
* @param $user_id 
* @return Response 
*/ 
public function show($user_id) 
{ 
$user = User::findOrFail($user_id); 
return Response::json([ 
'data' => $user 
]); 
} 
/** 
* Get a single book 
* 
* @param $book_id 
* @return Response 
*/ 
public function show($book_id) 
{ 
$book = Book::findOrFail($book_id); 
return Response::json([ 
'data' => $book 
]); 
}
Controllers / Store 
/** 
* Store a book 
* 
* @return Response 
*/ 
public function store() 
{ 
$input = Input::only('isbn13', 'title', 'author', 
'price'); 
$book = Book::create($input); 
return Response::json([ 
'data' => $book 
]); 
} 
/** 
* Store a user 
* 
* @return Response 
*/ 
public function store() 
{ 
$input = Input::only('email', 'name', 
'password'); 
$user = User::create($input); 
return Response::json([ 
'data' => $user 
]); 
}
Controllers / Update 
/** 
* Update a book 
* 
* @param $book_id 
* @return Response 
*/ 
public function update($book_id) 
{ 
$input = Input::only('isbn13', 'title', 
'author', 'price'); 
$book = Book::find($book_id); 
$book->update($input); 
return Response::json([ 
'data' => $book 
]); 
} 
/** 
* Update a user 
* 
* @param $user_id 
* @return Response 
*/ 
public function update($user_id) 
{ 
$input = Input::only('email', 'name', 
'password'); 
$user = User::findOrFail($user_id); 
$user->update($input); 
return Response::json([ 
'data' => $user 
]); 
}
Controllers / Destroy 
/** 
* Delete a book 
* 
* @param $book_id 
* @return Response 
*/ 
public function destroy($book_id) 
{ 
$book = User::findOrFail($book_id); 
$book->users()->sync([]); 
$book->delete(); 
return Response::json([ 
'success' => true 
]); 
} 
/** 
* Delete a user 
* 
* @param $user_id 
* @return Response 
*/ 
public function destroy($user_id) 
{ 
$user = User::findOrFail($user_id); 
$user->books()->sync([]); 
$user->delete(); 
return Response::json([ 
'success' => true 
]); 
}
Postman 
Demonstration
Let’s Review! 
• Request is sent through client (we used Postman, but could 
be AngularJS app, iPhone app, etc.) 
• Route interprets where it needs to go, sends it to 
appropriate controller + method 
• Controller takes the input and figures out what to do with it 
• Model (Eloquent) interacts with the database 
• Controller returns the data as JSON 
• Look, ma, no views!
A few problems… 
• We’re relying on the Laravel “hidden” attribute to avoid 
showing sensitive information but otherwise have no 
control over what is actually output. This is dangerous. 
• What happens if our database schema changes? 
• For example, we need to add a daily vs semester 
rental price and rename the “price” database column 
• How can we easily show a user + associated books with 
one API call?
Use transformers!
Transformers 
(Not like the robots) 
• “Transform” data per resource so that you have a lot more 
control over what you’re returning and its data type 
• Easy to build your own, or you can use Fractal for more 
advanced features: http://fractal.thephpleague.com/ 
• Serialize, or structure, your transformed data in a more 
specific way 
• Uses items (one object) and collections (group of objects) 
• Easily embed related resources within each other
Book Transformer 
app/Packback/Transformers/BookTransformer.php 
/** 
* Turn book object into generic array 
* 
* @param Book $book 
* @return array 
*/ 
public function transform(Book $book) 
{ 
return [ 
'id' => (int) $book->id, 
'isbn13' => $book->isbn13, 
'title' => $book->title, 
'author' => $book->author, 
// If we needed to rename the 'price' field to 'msrp' 
'msrp' => '$' . money_format('%i', $book->price) 
]; 
}
User Transformer 
app/Packback/Transformers/UserTransformer.php 
/** 
* Turn user object into generic array 
* 
* @param User $user 
* @return array 
*/ 
public function transform(User $user) 
{ 
return [ 
'id' => (int) $user->id, 
'name' => $user->name, 
'email' => $user->email 
]; 
}
/** 
* List of resources possible to include 
* 
* @var array 
*/ 
protected $availableIncludes = [ 
'books' 
]; 
/** 
* Include books in user 
* 
* @param User $user 
* @return LeagueFractalItemResource 
*/ 
public function includeBooks(User $user) 
{ 
$books = $user->books; 
return $this->collection($books, new BookTransformer); 
}
API Controller 
Extend the ApiController in 
UserController and BookController 
/** 
* Wrapper for Laravel's Response::json() method 
* 
* @param array $array 
* @param array $headers 
* @return mixed 
*/ 
protected function respondWithArray(array $array, array $headers = []) 
{ 
return Response::json($array, $this->statusCode, $headers); 
} 
class UserController extends ApiController 
class BookController extends ApiController 
app/controllers/ApiController.php
/** 
* Respond with Fractal Item 
* 
* @param $item 
* @param $callback 
* @return mixed 
*/ 
protected function respondWithItem($item, $callback) 
{ 
$resource = new Item($item, $callback); 
$rootScope = $this->fractal->createData($resource); 
return $this->respondWithArray($rootScope->toArray()); 
} 
/** 
* Respond with Fractal Collection 
* 
* @param $collection 
* @param $callback 
* @return mixed 
*/ 
protected function respondWithCollection($collection, $callback) 
{ 
$resource = new Collection($collection, $callback); 
$rootScope = $this->fractal->createData($resource); 
return $this->respondWithArray($rootScope->toArray()); 
}
Controller with Fractal 
public function index() 
{ 
$books = Book::all(); 
return $this->respondWithCollection($books, new BookTransformer); 
} 
public function show($book_id) 
{ 
$book = Book::findOrFail($book_id); 
return $this->respondWithItem($book, new BookTransformer); 
}
Improved Postman API Calls 
with Fractal
A Disclaimer 
• This app is an over-simplified example 
• Feel free to ignore everything I’ve told you tonight 
• Different conventions/opinions 
• Strict REST doesn’t make sense for every scenario 
• BUT the more you scale, the harder it will be to keep 
your code organized
REST APIs with Laravel 102 
AKA 
Things we didn’t have time to cover tonight 
• Testing :( 
• Pagination - return lots of records, a little bit at a time 
• Validation 
• Better error handling 
• Authentication 
• OOP best practices + design patterns
Questions? 
Twitter: @samanthageitz 
Email: samanthamichele7@gmail.com

Mais conteúdo relacionado

Mais procurados

Understanding Reactive Programming
Understanding Reactive ProgrammingUnderstanding Reactive Programming
Understanding Reactive ProgrammingAndres Almiray
 
OWASP AppSecCali 2015 - Marshalling Pickles
OWASP AppSecCali 2015 - Marshalling PicklesOWASP AppSecCali 2015 - Marshalling Pickles
OWASP AppSecCali 2015 - Marshalling PicklesChristopher Frohoff
 
Deep Dive into Docker Swarm Mode
Deep Dive into Docker Swarm ModeDeep Dive into Docker Swarm Mode
Deep Dive into Docker Swarm ModeAjeet Singh Raina
 
Developing RESTful Web APIs with Python, Flask and MongoDB
Developing RESTful Web APIs with Python, Flask and MongoDBDeveloping RESTful Web APIs with Python, Flask and MongoDB
Developing RESTful Web APIs with Python, Flask and MongoDBNicola Iarocci
 
Understanding REST
Understanding RESTUnderstanding REST
Understanding RESTNitin Pande
 
Red Hat OpenStack 17 저자직강+스터디그룹_1주차
Red Hat OpenStack 17 저자직강+스터디그룹_1주차Red Hat OpenStack 17 저자직강+스터디그룹_1주차
Red Hat OpenStack 17 저자직강+스터디그룹_1주차Nalee Jang
 
Automation with ansible
Automation with ansibleAutomation with ansible
Automation with ansibleKhizer Naeem
 
[112]rest에서 graph ql과 relay로 갈아타기 이정우
[112]rest에서 graph ql과 relay로 갈아타기 이정우[112]rest에서 graph ql과 relay로 갈아타기 이정우
[112]rest에서 graph ql과 relay로 갈아타기 이정우NAVER D2
 
Docker and the Linux Kernel
Docker and the Linux KernelDocker and the Linux Kernel
Docker and the Linux KernelDocker, Inc.
 
DCSF19 Dockerfile Best Practices
DCSF19 Dockerfile Best PracticesDCSF19 Dockerfile Best Practices
DCSF19 Dockerfile Best PracticesDocker, Inc.
 
[오픈소스컨설팅] 쿠버네티스와 쿠버네티스 on 오픈스택 비교 및 구축 방법
[오픈소스컨설팅] 쿠버네티스와 쿠버네티스 on 오픈스택 비교  및 구축 방법[오픈소스컨설팅] 쿠버네티스와 쿠버네티스 on 오픈스택 비교  및 구축 방법
[오픈소스컨설팅] 쿠버네티스와 쿠버네티스 on 오픈스택 비교 및 구축 방법Open Source Consulting
 
OpenStack 개요 및 활용 사례 @ Community Open Camp with Microsoft
OpenStack 개요 및 활용 사례 @ Community Open Camp with MicrosoftOpenStack 개요 및 활용 사례 @ Community Open Camp with Microsoft
OpenStack 개요 및 활용 사례 @ Community Open Camp with MicrosoftIan Choi
 

Mais procurados (20)

Understanding Reactive Programming
Understanding Reactive ProgrammingUnderstanding Reactive Programming
Understanding Reactive Programming
 
OWASP AppSecCali 2015 - Marshalling Pickles
OWASP AppSecCali 2015 - Marshalling PicklesOWASP AppSecCali 2015 - Marshalling Pickles
OWASP AppSecCali 2015 - Marshalling Pickles
 
From Zero to Docker
From Zero to DockerFrom Zero to Docker
From Zero to Docker
 
Deep Dive into Docker Swarm Mode
Deep Dive into Docker Swarm ModeDeep Dive into Docker Swarm Mode
Deep Dive into Docker Swarm Mode
 
Linux architecture
Linux architectureLinux architecture
Linux architecture
 
Developing RESTful Web APIs with Python, Flask and MongoDB
Developing RESTful Web APIs with Python, Flask and MongoDBDeveloping RESTful Web APIs with Python, Flask and MongoDB
Developing RESTful Web APIs with Python, Flask and MongoDB
 
Reactive programming intro
Reactive programming introReactive programming intro
Reactive programming intro
 
Understanding REST
Understanding RESTUnderstanding REST
Understanding REST
 
淺談探索 Linux 系統設計之道
淺談探索 Linux 系統設計之道 淺談探索 Linux 系統設計之道
淺談探索 Linux 系統設計之道
 
Red Hat OpenStack 17 저자직강+스터디그룹_1주차
Red Hat OpenStack 17 저자직강+스터디그룹_1주차Red Hat OpenStack 17 저자직강+스터디그룹_1주차
Red Hat OpenStack 17 저자직강+스터디그룹_1주차
 
Liquibase
LiquibaseLiquibase
Liquibase
 
Automation with ansible
Automation with ansibleAutomation with ansible
Automation with ansible
 
[112]rest에서 graph ql과 relay로 갈아타기 이정우
[112]rest에서 graph ql과 relay로 갈아타기 이정우[112]rest에서 graph ql과 relay로 갈아타기 이정우
[112]rest에서 graph ql과 relay로 갈아타기 이정우
 
Spring Core
Spring CoreSpring Core
Spring Core
 
Docker and the Linux Kernel
Docker and the Linux KernelDocker and the Linux Kernel
Docker and the Linux Kernel
 
DCSF19 Dockerfile Best Practices
DCSF19 Dockerfile Best PracticesDCSF19 Dockerfile Best Practices
DCSF19 Dockerfile Best Practices
 
Spring Boot
Spring BootSpring Boot
Spring Boot
 
[오픈소스컨설팅] 쿠버네티스와 쿠버네티스 on 오픈스택 비교 및 구축 방법
[오픈소스컨설팅] 쿠버네티스와 쿠버네티스 on 오픈스택 비교  및 구축 방법[오픈소스컨설팅] 쿠버네티스와 쿠버네티스 on 오픈스택 비교  및 구축 방법
[오픈소스컨설팅] 쿠버네티스와 쿠버네티스 on 오픈스택 비교 및 구축 방법
 
OpenStack 개요 및 활용 사례 @ Community Open Camp with Microsoft
OpenStack 개요 및 활용 사례 @ Community Open Camp with MicrosoftOpenStack 개요 및 활용 사례 @ Community Open Camp with Microsoft
OpenStack 개요 및 활용 사례 @ Community Open Camp with Microsoft
 
Why HATEOAS
Why HATEOASWhy HATEOAS
Why HATEOAS
 

Destaque

Laravel 5 Annotations: RESTful API routing
Laravel 5 Annotations: RESTful API routingLaravel 5 Annotations: RESTful API routing
Laravel 5 Annotations: RESTful API routingChristopher Pecoraro
 
Web services with laravel
Web services with laravelWeb services with laravel
Web services with laravelConfiz
 
RESTful API development in Laravel 4 - Christopher Pecoraro
RESTful API development in Laravel 4 - Christopher PecoraroRESTful API development in Laravel 4 - Christopher Pecoraro
RESTful API development in Laravel 4 - Christopher PecoraroChristopher Pecoraro
 
Bootstrat REST APIs with Laravel 5
Bootstrat REST APIs with Laravel 5Bootstrat REST APIs with Laravel 5
Bootstrat REST APIs with Laravel 5Elena Kolevska
 
Your rest api using laravel
Your rest api using laravelYour rest api using laravel
Your rest api using laravelSulaeman .
 
QA Lab: тестирование ПО. Станислав Шмидт: "Self-testing REST APIs with API Fi...
QA Lab: тестирование ПО. Станислав Шмидт: "Self-testing REST APIs with API Fi...QA Lab: тестирование ПО. Станислав Шмидт: "Self-testing REST APIs with API Fi...
QA Lab: тестирование ПО. Станислав Шмидт: "Self-testing REST APIs with API Fi...GeeksLab Odessa
 
Laravel 5.2 Gates, AuthServiceProvider and Policies
Laravel 5.2 Gates, AuthServiceProvider and PoliciesLaravel 5.2 Gates, AuthServiceProvider and Policies
Laravel 5.2 Gates, AuthServiceProvider and PoliciesAlison Gianotto
 
Super powered API testing
Super powered API testing Super powered API testing
Super powered API testing postmanclient
 
jQuery Keynote - Fall 2010
jQuery Keynote - Fall 2010jQuery Keynote - Fall 2010
jQuery Keynote - Fall 2010jeresig
 
Service-Oriented Architecture
Service-Oriented ArchitectureService-Oriented Architecture
Service-Oriented ArchitectureSamantha Geitz
 
Developing and Testing a MongoDB and Node.js REST API
Developing and Testing a MongoDB and Node.js REST APIDeveloping and Testing a MongoDB and Node.js REST API
Developing and Testing a MongoDB and Node.js REST APIAll Things Open
 
Laravel Restful API and AngularJS
Laravel Restful API and AngularJSLaravel Restful API and AngularJS
Laravel Restful API and AngularJSBlake Newman
 
SOAP-UI The Web service Testing
SOAP-UI The Web service TestingSOAP-UI The Web service Testing
SOAP-UI The Web service TestingGanesh Mandala
 
4 Major Advantages of API Testing
4 Major Advantages of API Testing4 Major Advantages of API Testing
4 Major Advantages of API TestingQASource
 
OpenStack Tempest and REST API testing
OpenStack Tempest and REST API testingOpenStack Tempest and REST API testing
OpenStack Tempest and REST API testingopenstackindia
 
Auto encoding-variational-bayes
Auto encoding-variational-bayesAuto encoding-variational-bayes
Auto encoding-variational-bayesmehdi Cherti
 
software testing on whatsapp
software testing on whatsappsoftware testing on whatsapp
software testing on whatsappnil65
 

Destaque (20)

Laravel 5 Annotations: RESTful API routing
Laravel 5 Annotations: RESTful API routingLaravel 5 Annotations: RESTful API routing
Laravel 5 Annotations: RESTful API routing
 
Web services with laravel
Web services with laravelWeb services with laravel
Web services with laravel
 
RESTful API development in Laravel 4 - Christopher Pecoraro
RESTful API development in Laravel 4 - Christopher PecoraroRESTful API development in Laravel 4 - Christopher Pecoraro
RESTful API development in Laravel 4 - Christopher Pecoraro
 
Bootstrat REST APIs with Laravel 5
Bootstrat REST APIs with Laravel 5Bootstrat REST APIs with Laravel 5
Bootstrat REST APIs with Laravel 5
 
REST API Laravel
REST API LaravelREST API Laravel
REST API Laravel
 
Your rest api using laravel
Your rest api using laravelYour rest api using laravel
Your rest api using laravel
 
QA Lab: тестирование ПО. Станислав Шмидт: "Self-testing REST APIs with API Fi...
QA Lab: тестирование ПО. Станислав Шмидт: "Self-testing REST APIs with API Fi...QA Lab: тестирование ПО. Станислав Шмидт: "Self-testing REST APIs with API Fi...
QA Lab: тестирование ПО. Станислав Шмидт: "Self-testing REST APIs with API Fi...
 
Laravel 5.2 Gates, AuthServiceProvider and Policies
Laravel 5.2 Gates, AuthServiceProvider and PoliciesLaravel 5.2 Gates, AuthServiceProvider and Policies
Laravel 5.2 Gates, AuthServiceProvider and Policies
 
Javascript laravel's friend
Javascript laravel's friendJavascript laravel's friend
Javascript laravel's friend
 
Super powered API testing
Super powered API testing Super powered API testing
Super powered API testing
 
jQuery Keynote - Fall 2010
jQuery Keynote - Fall 2010jQuery Keynote - Fall 2010
jQuery Keynote - Fall 2010
 
Service-Oriented Architecture
Service-Oriented ArchitectureService-Oriented Architecture
Service-Oriented Architecture
 
Developing and Testing a MongoDB and Node.js REST API
Developing and Testing a MongoDB and Node.js REST APIDeveloping and Testing a MongoDB and Node.js REST API
Developing and Testing a MongoDB and Node.js REST API
 
Laravel Restful API and AngularJS
Laravel Restful API and AngularJSLaravel Restful API and AngularJS
Laravel Restful API and AngularJS
 
SOAP-UI The Web service Testing
SOAP-UI The Web service TestingSOAP-UI The Web service Testing
SOAP-UI The Web service Testing
 
Api testing
Api testingApi testing
Api testing
 
4 Major Advantages of API Testing
4 Major Advantages of API Testing4 Major Advantages of API Testing
4 Major Advantages of API Testing
 
OpenStack Tempest and REST API testing
OpenStack Tempest and REST API testingOpenStack Tempest and REST API testing
OpenStack Tempest and REST API testing
 
Auto encoding-variational-bayes
Auto encoding-variational-bayesAuto encoding-variational-bayes
Auto encoding-variational-bayes
 
software testing on whatsapp
software testing on whatsappsoftware testing on whatsapp
software testing on whatsapp
 

Semelhante a REST APIs in Laravel 101

Getting to know Laravel 5
Getting to know Laravel 5Getting to know Laravel 5
Getting to know Laravel 5Bukhori Aqid
 
Laravel for Web Artisans
Laravel for Web ArtisansLaravel for Web Artisans
Laravel for Web ArtisansRaf Kewl
 
Getting Started with Rails
Getting Started with RailsGetting Started with Rails
Getting Started with RailsBasayel Said
 
Riding the Edge with Ember.js
Riding the Edge with Ember.jsRiding the Edge with Ember.js
Riding the Edge with Ember.jsaortbals
 
wwc start-launched
wwc start-launchedwwc start-launched
wwc start-launchedMat Schaffer
 
Learning to code for startup mvp session 3
Learning to code for startup mvp session 3Learning to code for startup mvp session 3
Learning to code for startup mvp session 3Henry S
 
Staying Sane with Drupal NEPHP
Staying Sane with Drupal NEPHPStaying Sane with Drupal NEPHP
Staying Sane with Drupal NEPHPOscar Merida
 
SproutCore and the Future of Web Apps
SproutCore and the Future of Web AppsSproutCore and the Future of Web Apps
SproutCore and the Future of Web AppsMike Subelsky
 
cake phptutorial
cake phptutorialcake phptutorial
cake phptutorialice27
 
Rails and the Apache SOLR Search Engine
Rails and the Apache SOLR Search EngineRails and the Apache SOLR Search Engine
Rails and the Apache SOLR Search EngineDavid Keener
 
PTW Rails Bootcamp
PTW Rails BootcampPTW Rails Bootcamp
PTW Rails BootcampMat Schaffer
 
WebNet Conference 2012 - Designing complex applications using html5 and knock...
WebNet Conference 2012 - Designing complex applications using html5 and knock...WebNet Conference 2012 - Designing complex applications using html5 and knock...
WebNet Conference 2012 - Designing complex applications using html5 and knock...Fabio Franzini
 
Rapid API Development ArangoDB Foxx
Rapid API Development ArangoDB FoxxRapid API Development ArangoDB Foxx
Rapid API Development ArangoDB FoxxMichael Hackstein
 
Jooctrine - Doctrine ORM in Joomla!
Jooctrine - Doctrine ORM in Joomla!Jooctrine - Doctrine ORM in Joomla!
Jooctrine - Doctrine ORM in Joomla!Herman Peeren
 
Introduction to Laravel Framework (5.2)
Introduction to Laravel Framework (5.2)Introduction to Laravel Framework (5.2)
Introduction to Laravel Framework (5.2)Viral Solani
 
Connecting the Worlds of Java and Ruby with JRuby
Connecting the Worlds of Java and Ruby with JRubyConnecting the Worlds of Java and Ruby with JRuby
Connecting the Worlds of Java and Ruby with JRubyNick Sieger
 

Semelhante a REST APIs in Laravel 101 (20)

Supa fast Ruby + Rails
Supa fast Ruby + RailsSupa fast Ruby + Rails
Supa fast Ruby + Rails
 
Getting to know Laravel 5
Getting to know Laravel 5Getting to know Laravel 5
Getting to know Laravel 5
 
MVS: An angular MVC
MVS: An angular MVCMVS: An angular MVC
MVS: An angular MVC
 
Laravel for Web Artisans
Laravel for Web ArtisansLaravel for Web Artisans
Laravel for Web Artisans
 
Getting Started with Rails
Getting Started with RailsGetting Started with Rails
Getting Started with Rails
 
Rails 4.0
Rails 4.0Rails 4.0
Rails 4.0
 
Riding the Edge with Ember.js
Riding the Edge with Ember.jsRiding the Edge with Ember.js
Riding the Edge with Ember.js
 
Wider than rails
Wider than railsWider than rails
Wider than rails
 
wwc start-launched
wwc start-launchedwwc start-launched
wwc start-launched
 
Learning to code for startup mvp session 3
Learning to code for startup mvp session 3Learning to code for startup mvp session 3
Learning to code for startup mvp session 3
 
Staying Sane with Drupal NEPHP
Staying Sane with Drupal NEPHPStaying Sane with Drupal NEPHP
Staying Sane with Drupal NEPHP
 
SproutCore and the Future of Web Apps
SproutCore and the Future of Web AppsSproutCore and the Future of Web Apps
SproutCore and the Future of Web Apps
 
cake phptutorial
cake phptutorialcake phptutorial
cake phptutorial
 
Rails and the Apache SOLR Search Engine
Rails and the Apache SOLR Search EngineRails and the Apache SOLR Search Engine
Rails and the Apache SOLR Search Engine
 
PTW Rails Bootcamp
PTW Rails BootcampPTW Rails Bootcamp
PTW Rails Bootcamp
 
WebNet Conference 2012 - Designing complex applications using html5 and knock...
WebNet Conference 2012 - Designing complex applications using html5 and knock...WebNet Conference 2012 - Designing complex applications using html5 and knock...
WebNet Conference 2012 - Designing complex applications using html5 and knock...
 
Rapid API Development ArangoDB Foxx
Rapid API Development ArangoDB FoxxRapid API Development ArangoDB Foxx
Rapid API Development ArangoDB Foxx
 
Jooctrine - Doctrine ORM in Joomla!
Jooctrine - Doctrine ORM in Joomla!Jooctrine - Doctrine ORM in Joomla!
Jooctrine - Doctrine ORM in Joomla!
 
Introduction to Laravel Framework (5.2)
Introduction to Laravel Framework (5.2)Introduction to Laravel Framework (5.2)
Introduction to Laravel Framework (5.2)
 
Connecting the Worlds of Java and Ruby with JRuby
Connecting the Worlds of Java and Ruby with JRubyConnecting the Worlds of Java and Ruby with JRuby
Connecting the Worlds of Java and Ruby with JRuby
 

Último

presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century educationjfdjdjcjdnsjd
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Drew Madelung
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Scriptwesley chun
 
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingRepurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingEdi Saputra
 
Top 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live StreamsTop 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live StreamsRoshan Dwivedi
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsJoaquim Jorge
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobeapidays
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonAnna Loughnan Colquhoun
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationSafe Software
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Miguel Araújo
 
AWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAndrey Devyatkin
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)Gabriella Davis
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationRadu Cotescu
 
Artificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : UncertaintyArtificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : UncertaintyKhushali Kathiriya
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherRemote DBA Services
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘RTylerCroy
 
Manulife - Insurer Innovation Award 2024
Manulife - Insurer Innovation Award 2024Manulife - Insurer Innovation Award 2024
Manulife - Insurer Innovation Award 2024The Digital Insurer
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityPrincipled Technologies
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...Neo4j
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...Martijn de Jong
 

Último (20)

presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century education
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Script
 
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingRepurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
 
Top 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live StreamsTop 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live Streams
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt Robison
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
AWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of Terraform
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
Artificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : UncertaintyArtificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : Uncertainty
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a Fresher
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
Manulife - Insurer Innovation Award 2024
Manulife - Insurer Innovation Award 2024Manulife - Insurer Innovation Award 2024
Manulife - Insurer Innovation Award 2024
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivity
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...
 

REST APIs in Laravel 101

  • 1. REST API Development and Testing 101 By Samantha Geitz
  • 2. A bit about me • 3 years of experience in web development • Now work for Packback • Background mostly in WordPress, a little bit of Rails, now use Laravel full-time • About 1 year experience building APIs
  • 3. What we’re going to talk about tonight • “Typical” Laravel application / MVC • What is an API, and why should you care? • Shitty way to structure an API • Better way to structure an API • Demonstration of interacting with API
  • 4. Our Application • Packback • Digital textbook rentals for college students • Resources: Users, Books • Users need to be able to “rent” books • https://github.com/samanthamic hele7/packback-rest-api-101 • Two branches: master and api_with_fractal
  • 5. Anatomy of the“Typical” Laravel Application • Model (Eloquent) + database • Controller + routes • View (Blade)
  • 6. Problems! • What happens if we want to build an iOS/Android application with our data? • What happens if we want to use AngularJS or EmberJS? • What happens when we want to rebuild the front-end in a few years? • What happens if we want to let other companies work with our data? (Twitter API, Facebook API, etc.)
  • 7. Solution: Let’s build an API! (Application Programming Interface)
  • 8. What the hell does that even mean? • APIs only care about data - not what things look like • Data in, data out • JSON is what most of the cool kids are using • Keeps data types intact • You can also use XML if you like typing a lot • Turns everything into a string
  • 9. <book> <id>1</id> <title>The Lord of the Rings</title> <author>J. R. R. Tolkien</author> </book> XML Example { "book": { "id" : 1, "title": "The Lord of the Rings", "author": "J. R. R. Tolkien" } } JSON Example
  • 10. Laravel makes it really easy • The client can access routes (which are basically just URLs) • Controllers handle logic (or call other classes to handle it for them) • Get data from or store data in database (via models) • ????? • PROFIT!!! • Return data as JSON
  • 11. Stuff that we need to do • /createUser • /fetchUser • /setUserPassword • /updatePaymentInfo • /addBook • /getBook • /deleteBook • /addBooktoUser • /removeBook
  • 12. Okay, this is getting kind of confusing
  • 13. REST to the Rescue! • Representational State Transfer • Hopefully not what you’re doing if I’m boring you
  • 14. It does CRUD • C - Create (POST) • R - Read (GET) • U - Update (PATCH/PUT) • D - Destroy (DELETE)
  • 15. Stuff that we need to do (the RESTful way) • POST /users - Create a new user • GET /users - Get all users • GET /users/{id} - Get one user by ID • PATCH /users/{id} - Update a user by ID • DELETE /users/{id} - Delete a user by ID • POST /users/{id}/books/{id} - Add a book (or books) to a user • GET /users/{id}/books/ - Get a list of books for a specific user • etc.
  • 16. Cool story, bro, but how do I actually build an API?
  • 17. Step 1: Create Databases • Run database migrations (the same way as in a regular Laravel application) • Books, users, pivot php artisan migrate
  • 18. app/database/migrations/2014_11_18_024437_create_users_table.<?php use IlluminateDatabaseSchemaBlueprint; use IlluminateDatabaseMigrationsMigration; class CreateUsersTable extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create('users', function(Blueprint $table) { $table->increments('id'); $table->string('email'); $table->string('name'); $table->string('password'); $table->timestamps(); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::drop('users'); } }
  • 19. app/database/migrations/2014_11_18_024939_create_books_table.<?php use IlluminateDatabaseSchemaBlueprint; use IlluminateDatabaseMigrationsMigration; class CreateBooksTable extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create('books', function(Blueprint $table) { $table->increments('id'); $table->string('isbn13'); $table->string('title'); $table->string('author'); $table->float('price'); $table->timestamps(); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::drop('books'); } }
  • 20. database/migrations/2014_11_18_025038_create_books_users_<?php use IlluminateDatabaseSchemaBlueprint; use IlluminateDatabaseMigrationsMigration; class CreateBooksUsersTable extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create('books_users', function(Blueprint $table) { $table->increments('id'); $table->integer('user_id')->unsigned(); $table->foreign('user_id')->references('id')->on('users'); $table->integer('book_id')->unsigned(); $table->foreign('book_id')->references('id')->on('books'); $table->timestamps(); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::table('books_users', function(Blueprint $table) { $table->dropForeign('books_users_user_id_foreign'); $table->dropForeign('books_users_book_id_foreign'); }); Schema::drop('books_users'); }
  • 21. Step 2: Seed data • Your life will be much easier if you fill your database with fake data • Faker is easy to use and has realistic fake data: https://github.com/fzaninotto/Faker • I generally do one seed file per table • Hook in database/seeds/DatabaseSeeder.php • Make sure you truncate every time the seeder is run or you will end up with a ton of data php artisan db:seed
  • 22. Seed Users app/database/seeds/UserTableSeeder.php <?php use CarbonCarbon; use FakerFactory as Faker; class UserTableSeeder extends Seeder { public function run() { $faker = Faker::create(); DB::table('users')->truncate(); for ($i = 0; $i < 50; $i++) { DB::table('users')->insert([ 'email' => $faker->email, 'name' => $faker->name, 'password' => Hash::make($faker->word), 'created_at' => Carbon::now(), 'updated_at' => Carbon::now() ]); } } }
  • 23. Seed Books app/database/seeds/BookTableSeeder.php <?php use CarbonCarbon; use FakerFactory as Faker; class BookTableSeeder extends Seeder { public function run() { $faker = Faker::create(); DB::table('books')->truncate(); for ($i = 0; $i < 50; $i++) { DB::table('books')->insert([ 'isbn13' => $faker->ean13(), 'title' => $faker->sentence, 'author' => $faker->name, 'price' => $faker->randomNumber(2) . '.' . $faker->randomNumber(2), 'created_at' => Carbon::now(), 'updated_at' => Carbon::now(), ]); } } }
  • 24. Seed User Books app/database/seeds/UserBookTableSeeder.php <?php use CarbonCarbon; class UserBookTableSeeder extends Seeder { public function run() { DB::table('books_users')->truncate(); for ($i = 1; $i < 51; $i++) { DB::table('books_users')->insert([ [ 'user_id' => $i, 'book_id' => $i, 'created_at' => Carbon::now(), 'updated_at' => Carbon::now() ], [ 'user_id' => $i, 'book_id' => 51 - $i, 'created_at' => Carbon::now(), 'updated_at' => Carbon::now() ] ]); } } }
  • 25. Step 3: Models • Very little difference compared to a more traditional Laravel app • Define a ManyToMany relationship between users and books
  • 26. app/models/User.php class User extends Eloquent implements UserInterface, RemindableInterface { use UserTrait, RemindableTrait; protected $table = 'users'; protected $fillable = ['email', 'name', 'password']; protected $hidden = array('password', 'remember_token'); public function books() { return $this->belongsToMany('Book', 'books_users'); } public function setPasswordAttribute($password) { $this->attributes['password'] = Hash::make($password); } }
  • 27. app/models/Book.php class Book extends Eloquent { protected $table = 'books'; protected $fillable = ['isbn13', 'title', 'author', 'price']; public function users() { return $this->belongsToMany('User', 'books_users'); } }
  • 28. Step 4: Routes • Should you use Laravel magic? (Route::resource() or Route::controller()) • Pros: Less code • Cons: Less code • It is generally clearer (to me) to explicitly define your routes (so you have a blueprint) • However, some people would disagree, so we’ll look at both
  • 29. RESTful routes Option 1 (Less code) Route::group(['prefix' => 'api'], function() { Route::resource('users', 'UserController'); Route::resource('books', 'BookController'); }); This will automatically look for create, edit, index, show, store, update, and destroy methods in your controller.
  • 30. RESTful Routes Option 2 (Explicit code) Route::group(['prefix' => 'api'], function() { Route::group(['prefix' => 'books'], function(){ Route::get('', array('uses' => 'BookController@index')); Route::get('{book_id}', array('uses' => 'BookController@show')); Route::post('', array('uses' => 'BookController@store')); Route::patch('{book_id}', array('uses' => 'BookController@update')); Route::delete('{book_id}', array('uses' => 'BookController@destroy')); }); Route::group(['prefix' => 'users'], function(){ Route::get('', array('uses' => 'UserController@index')); Route::get('{user_id}', array('uses' => 'UserController@show')); Route::get('{user_id}/books', array('uses' => 'UserController@showBooks')); Route::post('', array('uses' => 'UserController@store')); Route::post('{user_id}/books/{book_id}', array('uses' => 'UserController@storeBooks')); Route::patch('{user_id}', array('uses' => 'UserController@update')); Route::delete('{user_id}', array('uses' => 'UserController@destroy')); Route::delete('{user_id}/books/{book_id}', array('uses' => 'UserController@destroyBooks')); }); });
  • 31. Let’s talk about status codes • Your API needs to send back a HTTP status code so that the client knows if the succeeded or failed (and if it failed, why) • 2xx - GREAT SUCCESS • 3xx - Redirect somewhere else • 4xx - Client errors • 5xx - Service errors
  • 32. Some common status codes • 200 - generic OK • 201 - Created OK • 301 - Moved permanently and redirect to new location • 400 - Generic bad request (often used for validation on models) • 401 - Unauthorized (please sign in) • 403 - Unauthorized (you are signed in but shouldn’t be accessing this) • 404 - Does not exist • 500 - API dun goofed • 503 - API is not available for some reason • Plus lots more!
  • 33. Step 5: Controllers • You will need (at least) 5 methods: index (get all), show (get one), store, update, destroy • What about create() and edit() (if you use Route::resource())? • You don’t need them if you’re building a pure data-driven API! • Use Postman (http://www.getpostman.com/) to interact with your API instead of Blade templates
  • 34. Controllers / Index /** * Get all books * * @return Response */ public function index() { $books = Book::all(); return Response::json([ 'data' => $books ]); } /** * Get all users * * @return Response */ public function index() { $users = User::all(); return Response::json([ 'data' => $users ]); }
  • 35. Controllers / Show /** * Get a single user * * @param $user_id * @return Response */ public function show($user_id) { $user = User::findOrFail($user_id); return Response::json([ 'data' => $user ]); } /** * Get a single book * * @param $book_id * @return Response */ public function show($book_id) { $book = Book::findOrFail($book_id); return Response::json([ 'data' => $book ]); }
  • 36. Controllers / Store /** * Store a book * * @return Response */ public function store() { $input = Input::only('isbn13', 'title', 'author', 'price'); $book = Book::create($input); return Response::json([ 'data' => $book ]); } /** * Store a user * * @return Response */ public function store() { $input = Input::only('email', 'name', 'password'); $user = User::create($input); return Response::json([ 'data' => $user ]); }
  • 37. Controllers / Update /** * Update a book * * @param $book_id * @return Response */ public function update($book_id) { $input = Input::only('isbn13', 'title', 'author', 'price'); $book = Book::find($book_id); $book->update($input); return Response::json([ 'data' => $book ]); } /** * Update a user * * @param $user_id * @return Response */ public function update($user_id) { $input = Input::only('email', 'name', 'password'); $user = User::findOrFail($user_id); $user->update($input); return Response::json([ 'data' => $user ]); }
  • 38. Controllers / Destroy /** * Delete a book * * @param $book_id * @return Response */ public function destroy($book_id) { $book = User::findOrFail($book_id); $book->users()->sync([]); $book->delete(); return Response::json([ 'success' => true ]); } /** * Delete a user * * @param $user_id * @return Response */ public function destroy($user_id) { $user = User::findOrFail($user_id); $user->books()->sync([]); $user->delete(); return Response::json([ 'success' => true ]); }
  • 40. Let’s Review! • Request is sent through client (we used Postman, but could be AngularJS app, iPhone app, etc.) • Route interprets where it needs to go, sends it to appropriate controller + method • Controller takes the input and figures out what to do with it • Model (Eloquent) interacts with the database • Controller returns the data as JSON • Look, ma, no views!
  • 41. A few problems… • We’re relying on the Laravel “hidden” attribute to avoid showing sensitive information but otherwise have no control over what is actually output. This is dangerous. • What happens if our database schema changes? • For example, we need to add a daily vs semester rental price and rename the “price” database column • How can we easily show a user + associated books with one API call?
  • 43. Transformers (Not like the robots) • “Transform” data per resource so that you have a lot more control over what you’re returning and its data type • Easy to build your own, or you can use Fractal for more advanced features: http://fractal.thephpleague.com/ • Serialize, or structure, your transformed data in a more specific way • Uses items (one object) and collections (group of objects) • Easily embed related resources within each other
  • 44. Book Transformer app/Packback/Transformers/BookTransformer.php /** * Turn book object into generic array * * @param Book $book * @return array */ public function transform(Book $book) { return [ 'id' => (int) $book->id, 'isbn13' => $book->isbn13, 'title' => $book->title, 'author' => $book->author, // If we needed to rename the 'price' field to 'msrp' 'msrp' => '$' . money_format('%i', $book->price) ]; }
  • 45. User Transformer app/Packback/Transformers/UserTransformer.php /** * Turn user object into generic array * * @param User $user * @return array */ public function transform(User $user) { return [ 'id' => (int) $user->id, 'name' => $user->name, 'email' => $user->email ]; }
  • 46. /** * List of resources possible to include * * @var array */ protected $availableIncludes = [ 'books' ]; /** * Include books in user * * @param User $user * @return LeagueFractalItemResource */ public function includeBooks(User $user) { $books = $user->books; return $this->collection($books, new BookTransformer); }
  • 47. API Controller Extend the ApiController in UserController and BookController /** * Wrapper for Laravel's Response::json() method * * @param array $array * @param array $headers * @return mixed */ protected function respondWithArray(array $array, array $headers = []) { return Response::json($array, $this->statusCode, $headers); } class UserController extends ApiController class BookController extends ApiController app/controllers/ApiController.php
  • 48. /** * Respond with Fractal Item * * @param $item * @param $callback * @return mixed */ protected function respondWithItem($item, $callback) { $resource = new Item($item, $callback); $rootScope = $this->fractal->createData($resource); return $this->respondWithArray($rootScope->toArray()); } /** * Respond with Fractal Collection * * @param $collection * @param $callback * @return mixed */ protected function respondWithCollection($collection, $callback) { $resource = new Collection($collection, $callback); $rootScope = $this->fractal->createData($resource); return $this->respondWithArray($rootScope->toArray()); }
  • 49. Controller with Fractal public function index() { $books = Book::all(); return $this->respondWithCollection($books, new BookTransformer); } public function show($book_id) { $book = Book::findOrFail($book_id); return $this->respondWithItem($book, new BookTransformer); }
  • 50. Improved Postman API Calls with Fractal
  • 51. A Disclaimer • This app is an over-simplified example • Feel free to ignore everything I’ve told you tonight • Different conventions/opinions • Strict REST doesn’t make sense for every scenario • BUT the more you scale, the harder it will be to keep your code organized
  • 52. REST APIs with Laravel 102 AKA Things we didn’t have time to cover tonight • Testing :( • Pagination - return lots of records, a little bit at a time • Validation • Better error handling • Authentication • OOP best practices + design patterns
  • 53. Questions? Twitter: @samanthageitz Email: samanthamichele7@gmail.com