Slide 1

Slide 1 text

A PHP Framework For Web Artisans

Slide 2

Slide 2 text

Ben Edmunds @benedmunds http://benedmunds.com Who is this guy?

Slide 3

Slide 3 text

Ben Edmunds Open Source Author PHP Town Hall Podcast CTO at Mindfulware Who is this guy?

Slide 4

Slide 4 text

What is it? PHP Web Framework Full-stack (what does that even mean anymore) Open Source

Slide 5

Slide 5 text

Who’s behind it? Taylor Otwell @taylorotwell

Slide 6

Slide 6 text

I already use X. Why should I use Laravel?

Slide 7

Slide 7 text

Why use it? Expressive Syntax Route::get(‘user/{id}’, function($id) { $user = User::find($id); return view(‘home') ->with('user', $user); });

Slide 8

Slide 8 text

Why use it? Utilizes the latest PHP features Namespaces PSR-4 Autoloading Interfaces IoC

Slide 9

Slide 9 text

Why use it? Service Providers De-Coupled Flexible DRY Event Handling

Slide 10

Slide 10 text

Why use it? Contracts = Groups of Interfaces Loose Coupling Testability Explicit Flexible

Slide 11

Slide 11 text

Why use it? Facades = Quick Start $object = new class; $object->set('key', 'value'); Class::set('key', 'value');

Slide 12

Slide 12 text

Why use it? Well Documented http://laravel.com/docs

Slide 13

Slide 13 text

Why use it? Artisan CLI Tool $ php artisan migrate

Slide 14

Slide 14 text

Why use it? Built on Composer http://packagist.com Entirely Modular PSR-2, PSR-3, PSR-4, PSR-7 Compliant

Slide 15

Slide 15 text

Why use it? Test Coverage Focus on Testable Code

Slide 16

Slide 16 text

Why use it? Full Stack Framework Full Stack Ecosystem

Slide 17

Slide 17 text

Why use it? Homestead Pre-made Vagrant Box Nginx MySQL/PostgreSQL Beanstalkd Redis Memcached PHP / HHVM Node

Slide 18

Slide 18 text

Why use it? PAAS to quickly deploy PHP apps to the “cloud” Digital Ocean Linode AWS

Slide 19

Slide 19 text

Why use it? Full application quick start Authentication Teams Billing SASS-y

Slide 20

Slide 20 text

Let’s do some comparisons

Slide 21

Slide 21 text

Comparison MVC Design Lightweight Fast Excellent Docs Compatibility Technical Debt

Slide 22

Slide 22 text

Comparison MVC Design Heavy but has Silex Slow-ish Complex Good Docs Modular Backed by SensioLabs

Slide 23

Slide 23 text

Beyond MVC Design Easy to get started Consistent/Stable Fast Excellent Docs Threw out previous framework ideas and started over Comparison

Slide 24

Slide 24 text

OK, I’ll try it. How do I get started?

Slide 25

Slide 25 text

Download Composer Based Install $ composer create-project laravel/laravel --prefer-dist

Slide 26

Slide 26 text

Structure Commands Providers Controller || Route || Both Middleware Services Views Model / Repository / FLEXIBILITY

Slide 27

Slide 27 text

Routes

Slide 28

Slide 28 text

Routes Create routes at: routes/web.php routes/api.php Web = web middleware API = api middleware App\Providers\RouteServiceProvider to add new route files

Slide 29

Slide 29 text

Routes What methods are available: Route::get(); Route::post(); Route::put(); Route::patch(); Route::delete(); Route::any(); //all of the above

Slide 30

Slide 30 text

Routes Register multiple verbs for a single route: Router::match([‘get’, ‘post’], ‘/’, function(){ //this will run for both GET and POST });

Slide 31

Slide 31 text

Routes routes/web.php Route::get('/', function(){ echo ‘Boom!’; });

Slide 32

Slide 32 text

Testing

Slide 33

Slide 33 text

Testing Runs all tests located at: /tests/ $ php artisan test

Slide 34

Slide 34 text

Testing routes/web.php Route::get('/', function(){ echo ‘Boom!’; });

Slide 35

Slide 35 text

Testing /tests/ExampleTest.php Test it! Test it good! class ExampleTest extends TestCase { function testBasicExample() { $this->visit('/') ->see(‘Boom!');

Slide 36

Slide 36 text

Testing $ php artisan test Run it! PHPUnit 3.6.10 by Sebastian Bergmann. Configuration read from ... Time: 0 seconds, Memory: 6.25Mb OK (1 test, 1 assertion) Output

Slide 37

Slide 37 text

API?

Slide 38

Slide 38 text

What about an API? Routes to the rescue!

Slide 39

Slide 39 text

API routes/api.php Route::get(‘user/{id}’, function($id){ return json_encode([ ‘user‘ => User::find($id), ‘success‘ => true ]); });

Slide 40

Slide 40 text

API routes/api.php Route::get(‘user/{id}’, function($id){ return [ ‘user‘ => User::find($id), ‘success‘ => true ]; });

Slide 41

Slide 41 text

API App\Providers\RouteServiceProvider protected function mapApiRoutes() { Route::group([ 'middleware' => ['api', 'auth:api'], 'namespace' => $this->namespace, 'prefix' => 'api', ], function ($router) { require base_path('routes/api.php'); });

Slide 42

Slide 42 text

API App\Providers\RouteServiceProvider protected function mapApiRoutes() { Route::group([ 'middleware' => ['api', 'auth:api'], 'namespace' => $this->namespace, 'prefix' => 'api', ], function ($router) { require base_path('routes/api.php'); });

Slide 43

Slide 43 text

API /tests/api/UserTest.php class UserTest extends TestCase { public function testGetUser() { $this->get(‘/api/user/1’) ->seeJson([ ‘success‘ => true ]);

Slide 44

Slide 44 text

Controllers

Slide 45

Slide 45 text

Controllers OK, routes are cool and all, but what if I want to use controllers?

Slide 46

Slide 46 text

Controllers routes/web.php Route::post('status', 'StatusController@create'); class StatusController extends Controller { public function create(Request $request) { … app/Http/controllers/StatusController.php

Slide 47

Slide 47 text

Shit just got real

Slide 48

Slide 48 text

Middleware

Slide 49

Slide 49 text

Middleware Route Filters BETTER FASTER STRONGER Middleware!

Slide 50

Slide 50 text

Middleware Popular Uses: Auth ACL Session Caching Debug Logging Analytics Rate Limiting

Slide 51

Slide 51 text

Middleware Route::post('status', ‘StatusController@create’, [‘middleware’ => ‘auth’] );

Slide 52

Slide 52 text

Middleware Route::post('status', ‘StatusController@create’, [‘middleware’ => [ ‘first’, ‘second’, ‘third’, ]] );

Slide 53

Slide 53 text

Middleware class AjaxMiddleware implements Middleware { public function handle($request, Closure $next) { if (!$request->ajax()) return response('Unauthorized.', 401); return $next($request); }

Slide 54

Slide 54 text

Middleware Groups for DRY routing: Route::group(['middleware' => 'auth'], function(){ Route::get('/statuses', function(){ … }); …

Slide 55

Slide 55 text

Database

Slide 56

Slide 56 text

Database Query Builder Eloquent ORM Migrations Seeding

Slide 57

Slide 57 text

Query Builder Simple and Easy to Understand Used extensively by Eloquent ORM

Slide 58

Slide 58 text

Query Builder $user = DB::table('statuses') ->where(‘email’, '[email protected]’) ->first(); Query Row by Email

Slide 59

Slide 59 text

Query Builder $id = DB::table('statuses') ->insertGetId([ ‘user_id' => 1, 'email' => ‘[email protected]', 'text' => ‘Vegas Baby! #zendcon’, ]); Insert & Get ID

Slide 60

Slide 60 text

Eloquent ORM Simple Expressive Efficient

Slide 61

Slide 61 text

Eloquent ORM use Illuminate\Database\Eloquent\Model; class Status extends Model { } Define an Eloquent model

Slide 62

Slide 62 text

Eloquent ORM $status = App\Status::where(‘user_id’, 1) ->first(); Simple query

Slide 63

Slide 63 text

Eloquent ORM $statuses = App\Status::where(‘views', '>', 100) ->get(); Slightly more advanced query

Slide 64

Slide 64 text

Eloquent ORM Relationships class Status extends Model { public function user() { return $this->belongsTo(‘App\User'); } } App\Status::find(1)->user->email; Retrieve Status Creator Email

Slide 65

Slide 65 text

Eloquent ORM Normal Usage $statuses = App\Status::all(); foreach ($statuses as $status) echo $status->user->email;

Slide 66

Slide 66 text

Eloquent ORM Normal Usage $statuses = App\Status::all(); foreach ($statuses as $status) echo $status->user->email; SELECT * FROM "statuses" foreach result { SELECT * FROM "users" WHERE "id" = 1 } 100 statuses = 101 queries

Slide 67

Slide 67 text

WTF!? ORMs Suck!

Slide 68

Slide 68 text

Eloquent ORM $statuses = App\Status::with(‘user’)->get(); foreach ($statuses as $status) echo $status->user->email; Eager Loading FTW!

Slide 69

Slide 69 text

Eloquent ORM $statuses = App\Status::with(‘user’)->get(); foreach ($statuses as $status) echo $status->user->email; 100 statuses = 2 queries SELECT * FROM "statuses" SELECT * FROM "users" WHERE "id" IN (1, 2, 3, 4, 5, ...) Eager Loading FTW!

Slide 70

Slide 70 text

Eloquent ORM creating created updating updated saving saved deleting deleted restoring restored Events

Slide 71

Slide 71 text

Views

Slide 72

Slide 72 text

Views Route::get('/', function(){ return view('home.index'); //resources/views/home/index.blade.php }); Returning a view from a route

Slide 73

Slide 73 text

Views Route::get('/', function(){ return view(‘home.index') ->with('email', '[email protected]'); Sending data to a view

Slide 74

Slide 74 text

Views Sending data to a view with magic methods Route::get('/', function(){ $view = view('home.index'); $view->email = ‘[email protected]’; return $view;

Slide 75

Slide 75 text

Views Blade Templates Email Address: {{ $email }}

Slide 76

Slide 76 text

Views Blade Templates Email Address: {{ $email or ‘Please enter email’ }}

Slide 77

Slide 77 text

Views Blade Templates @include(‘user.registration’)

Slide 78

Slide 78 text

Echo

Slide 79

Slide 79 text

Echo Web sockets made easy php artisan make:event MessageReceived /app/Events/MessageReceived.php

Slide 80

Slide 80 text

Echo Pusher JS or Socket.io

Slide 81

Slide 81 text

Cashier

Slide 82

Slide 82 text

Cashier Simple Payment Management Stripe Braintree

Slide 83

Slide 83 text

Scout

Slide 84

Slide 84 text

Scout API Authentication JWT OAuth 2 Laravel and Vue JS

Slide 85

Slide 85 text

Form Requests

Slide 86

Slide 86 text

Form Requests Designed just for form handling/validation class CreateStatusRequest extends FormRequest { public function rules() { return [ ‘email’ => ‘required|email', ‘text' => ‘required', ]; }

Slide 87

Slide 87 text

Form Requests class StatusController extends Controller { public function create(CreateStatusRequest $request){ … }

Slide 88

Slide 88 text

Facades

Slide 89

Slide 89 text

Facades $var = Session::get('foo'); Resolves behind the scenes Getting a session variable

Slide 90

Slide 90 text

Facades Controller Injection to the rescue! Managing Class Responsibilities?

Slide 91

Slide 91 text

Facades class HomeController extends Controller { public function __construct(Request $request){ $value = $request->session()->get('key'); } Controller Injection

Slide 92

Slide 92 text

Drama Da da DOM

Slide 93

Slide 93 text

That’s a Wrap Utilizes the best PHP has to offer Well designed API with great docs Ready to scale architecture Go make cool things and have fun

Slide 94

Slide 94 text

Community http://github.com/laravel/laravel http://docs.laravel.com http://forums.laravel.com

Slide 95

Slide 95 text

Resources Dayle Rees - Code Smart Laravel: From Apprentice to Artisan LaraCasts

Slide 96

Slide 96 text

Securing PHP Apps SecuringPhpApps.com Resources

Slide 97

Slide 97 text

THANKS! Ben Edmunds @benedmunds http://benedmunds.com https://joind.in/talk/62c46