Slide 1

Slide 1 text

Using Laravel for Rapid Development Rob Allen & Gary Hockin April 2018

Slide 2

Slide 2 text

Today's plan • Getting started with Laravel • Creating pages • Databases • Authentication • Lunch! Rob Allen ~ @akrabat | Gary Hockin ~ @geeh

Slide 3

Slide 3 text

What is Laravel? Rob Allen ~ @akrabat | Gary Hockin ~ @geeh

Slide 4

Slide 4 text

Laravel Elegant applications delivered at warp speed. • Created by Taylor Otwell • Full stack framework • Focussed on rapid development • MVC structure • CLI tooling with artisan Rob Allen ~ @akrabat | Gary Hockin ~ @geeh

Slide 5

Slide 5 text

What do you get? • Routing • DI Container • Database ORM • Authentication • Caching • Console • Cookies • Encryption • Events • Forms • etc! Rob Allen ~ @akrabat | Gary Hockin ~ @geeh

Slide 6

Slide 6 text

Why Laravel? • Everything in the box • Opinionated • Convention over configuration • artisan CLI tool • Ecosystem • Great community • Laracasts Rob Allen ~ @akrabat | Gary Hockin ~ @geeh

Slide 7

Slide 7 text

Ecosystem • Cashier - subscription billing • Dusk - browser tests • Echo - broadcasting over sockets • Envoy - task runner • Horizon - Redis queue integration & dashboard • Passport - API authentication • Scout - Full-text search • Socialite - external OAuth authentication • Envoyer - Deployment (paid) • Spark - SAAS scaffolding (paid) Rob Allen ~ @akrabat | Gary Hockin ~ @geeh

Slide 8

Slide 8 text

Running Laravel apps • artisan serve - use built-in PHP server • Homestead - local Vagrant setup • Forge - server manager and deployment system Rob Allen ~ @akrabat | Gary Hockin ~ @geeh

Slide 9

Slide 9 text

Getting started Rob Allen ~ @akrabat | Gary Hockin ~ @geeh

Slide 10

Slide 10 text

Installation 1.Install Laravel Installer: composer global require "laravel/installer" 2.Create a new project: laravel new my-project-name 3.Run using local webserver: cd my-project-name && php artisan serve Rob Allen ~ @akrabat | Gary Hockin ~ @geeh

Slide 11

Slide 11 text

First run Rob Allen ~ @akrabat | Gary Hockin ~ @geeh

Slide 12

Slide 12 text

Coding time! Rob Allen ~ @akrabat | Gary Hockin ~ @geeh

Slide 13

Slide 13 text

So how does Laravel work?! Rob Allen ~ @akrabat | Gary Hockin ~ @geeh

Slide 14

Slide 14 text

Directory structure . ├── app/ ├── routes/ ├── bootstrap/ ├── storage/ ├── config/ ├── tests/ ├── database/ ├── artisan ├── public/ ├── .env │ ├── index.php ├── composer.json ├── resources/ ├── composer.lock │ ├── assets/ └── package.json │ ├── lang/ │ └── views/ Rob Allen ~ @akrabat | Gary Hockin ~ @geeh

Slide 15

Slide 15 text

app/ └─ app/ ├── Console/ ├── Exceptions/ ├── Http/ │ ├── Controllers/ │ │ ├── Auth/ │ │ └── Controller.php │ ├── Middleware/ │ └── Kernel.php ├── Providers/ └── User.php Rob Allen ~ @akrabat | Gary Hockin ~ @geeh

Slide 16

Slide 16 text

Dispatch process 1.Bootstrap 2.Dispatch a.Run middleware b.Execute router c.Invoke controller d.Render view Rob Allen ~ @akrabat | Gary Hockin ~ @geeh

Slide 17

Slide 17 text

Configuration config/ holds a set of PHP files; each returns an array. // config/app.php env('APP_NAME', 'Laravel'), 'env' => env('APP_ENV', 'production'), 'debug' => env('APP_DEBUG', false), 'url' => env('APP_URL', 'http://localhost'), 'timezone' => 'UTC', 'locale' => 'en', // etc... ]; Rob Allen ~ @akrabat | Gary Hockin ~ @geeh

Slide 18

Slide 18 text

.env file APP_NAME=Laravel APP_ENV=local APP_KEY=base64:Ohv+3NM3HHHpkCuG3VFK8WzSvY1AfAR4A7PlkvI= APP_DEBUG=true APP_URL=http://localhost # etc... Access using config() function: $appName = config('app.name'); Rob Allen ~ @akrabat | Gary Hockin ~ @geeh

Slide 19

Slide 19 text

Routing A route is defined in routes/web.php & consists of: • HTTP method • URI • An action (closure or class method) Route::get('/hello', function () { return 'Hello World'; }); Rob Allen ~ @akrabat | Gary Hockin ~ @geeh

Slide 20

Slide 20 text

Router methods Route::get('/hello', $callable); Route::post('/hello', $callable); Route::put('/hello', $callable); Route::patch('/hello', $callable); Route::delete('/hello', $callable); Route::options('/hello', $callable); Route::any('/hello', $callable); Route::match(['get', 'post'], '/hello', $callable); Route::redirect('/bonjour', '/hello', 301); Route::view('/hello', 'route-name'); Rob Allen ~ @akrabat | Gary Hockin ~ @geeh

Slide 21

Slide 21 text

URI pattern • Literal string match Route::get('/hello', function () {…}); • Parameters are wrapped in { } $app->get('/hello/{name}', function ($name) {…}); • Optional parameters end with ? $app->get('/hello/{name?}', function ($name='Rob') {… • Constrain parameters via Regex $app->get('/hello/{name}', …) ->where('name', '[A-Za-z]+'); Rob Allen ~ @akrabat | Gary Hockin ~ @geeh

Slide 22

Slide 22 text

Routes can be named Assign a name to a route so you can generate URLs from it $app->get('/hello/{name}', …)->name('hello'); // Generating URLs... $url = route('hello', ['name' => 'Rob']); // Generating Redirects... return redirect()->route('hello', ['name' => 'Rob']); Rob Allen ~ @akrabat | Gary Hockin ~ @geeh

Slide 23

Slide 23 text

Controllers & actions In addition to closures, you can specify an action method in a controller: $app->get('/hello/{name}', 'UserController@profile'); UserController: The \App\Http\Controllers\UserController class profile: The profile() method in UserController Rob Allen ~ @akrabat | Gary Hockin ~ @geeh

Slide 24

Slide 24 text

Actions • Receive route parameters • Can optionally receive Request object • Manage business logic operations • Return a Response object or a View object Rob Allen ~ @akrabat | Gary Hockin ~ @geeh

Slide 25

Slide 25 text

Actions $user]); } } Rob Allen ~ @akrabat | Gary Hockin ~ @geeh

Slide 26

Slide 26 text

Blade templates • Call view() to render template: • Store templates in resources/views directory • Use the .blade.php file extension Rob Allen ~ @akrabat | Gary Hockin ~ @geeh

Slide 27

Slide 27 text

Action template @extends('layout') @section('content')

User Profile

    @foreach ($user->hobbies as $hobby)
  • {{ $hobby }}
  • @endforeach
@endsection Rob Allen ~ @akrabat | Gary Hockin ~ @geeh

Slide 28

Slide 28 text

Print variables @extends('layout') @section('content')

User Profile

    @foreach ($user->hobbies as $hobby)
  • {{ $hobby }}
  • @endforeach
@endsection Rob Allen ~ @akrabat | Gary Hockin ~ @geeh

Slide 29

Slide 29 text

Control statements @extends('layout') @section('content')

User Profile

    @foreach ($user->hobbies as $hobby)
  • {{ $hobby }}
  • @endforeach
@endsection Rob Allen ~ @akrabat | Gary Hockin ~ @geeh

Slide 30

Slide 30 text

Template inheritance @extends('layout') @section('content')

User Profile

    @foreach ($user->hobbies as $hobby)
  • {{ $hobby }}
  • @endforeach
@endsection Rob Allen ~ @akrabat | Gary Hockin ~ @geeh

Slide 31

Slide 31 text

Template inheritance • For cohesive look and feel • includes default CSS, JS & structural HTML • Build a base skeleton • Define sections for children to override • Each child chooses which template to inherit from Rob Allen ~ @akrabat | Gary Hockin ~ @geeh

Slide 32

Slide 32 text

Base layout @yield('title', 'Site name') @yield('content') Rob Allen ~ @akrabat | Gary Hockin ~ @geeh

Slide 33

Slide 33 text

Let's build an application! Rob Allen ~ @akrabat | Gary Hockin ~ @geeh

Slide 34

Slide 34 text

Simple Todo List Our todo list will display a list of items to be done. Item properties: • title: text of what's to be done • doby: date when it must be done by • completed: has it been done? The first page will list all our todos… Rob Allen ~ @akrabat | Gary Hockin ~ @geeh

Slide 35

Slide 35 text

Coding time! Rob Allen ~ @akrabat | Gary Hockin ~ @geeh

Slide 36

Slide 36 text

Databases Rob Allen ~ @akrabat | Gary Hockin ~ @geeh

Slide 37

Slide 37 text

Eloquent • Simple to use Active Record implementation • Each table has a Model • Conventions: • User model is connected to the users table • Each table has a primary key call id • created_at and updated_at columns exist on your table Rob Allen ~ @akrabat | Gary Hockin ~ @geeh

Slide 38

Slide 38 text

Model $ php artisan make:model User Model created successfully. Creates App\User:

Slide 39

Slide 39 text

Fetching data Use all() to quickly grab all records: $users = User::all(); foreach($users as $user) { echo $user->name; } or use the fluent interface to build your query: $users = User::where('deleted', 0) ->orderBy('name', 'desc') ->take(20) ->get(); Rob Allen ~ @akrabat | Gary Hockin ~ @geeh

Slide 40

Slide 40 text

Fetching a single record Use find() or first(): $user = User::find(1); // or $rob = User::where('username', 'akrabat')->first(); Rob Allen ~ @akrabat | Gary Hockin ~ @geeh

Slide 41

Slide 41 text

Inserting/updating Create a new Model instance and call save() on it: $user = new User(); $user->username = 'geeh'; $user->save(); Calling save() on a retrieved model will update the database: $user = User::where('username', 'geeh')->first(); $user->name = 'Gary'; $user->save(); Rob Allen ~ @akrabat | Gary Hockin ~ @geeh

Slide 42

Slide 42 text

Timesavers Fetch a user or instantiate if it doesn't exist: $user = User::firstOrNew(['username' => 'geeh']); Update or create a new record if it doesn't exist: $user = User::updateorCreate( ['username' => 'geeh'], // where clause ['name' => 'Gary'] // data to update ); Rob Allen ~ @akrabat | Gary Hockin ~ @geeh

Slide 43

Slide 43 text

Deleting Find a Model and call delete() on it: $user = User::where('username', 'geeh')->first(); $user->delete(); Or, call destroy() if you know the primary key: User::destroy(2); Or, delete() on a query result: User::where('active', 0)->delete(); Rob Allen ~ @akrabat | Gary Hockin ~ @geeh

Slide 44

Slide 44 text

Soft delete Create a deleted_at column in your table and Eloquent will automatically exclude these records from your queries: class User extends Model { use SoftDeletes; protected $dates = ['deleted_at']; } Rob Allen ~ @akrabat | Gary Hockin ~ @geeh

Slide 45

Slide 45 text

Relationships Relationships are defined as methods on your model Eloquent supports: • One to one • One to many • Many to many Rob Allen ~ @akrabat | Gary Hockin ~ @geeh

Slide 46

Slide 46 text

One to one relationships A user has an address. Links via addresses:user_id. class User extends Model { public function address() { return $this->hasOne('App\Address'); } } // usage: $address = User::find(1)->address; Rob Allen ~ @akrabat | Gary Hockin ~ @geeh

Slide 47

Slide 47 text

One to one relationships Reverse: class Address extends Model { public function user() { return $this->belongsTo('App\User'); } } // usage: $user = Address::find(1)->user; Rob Allen ~ @akrabat | Gary Hockin ~ @geeh

Slide 48

Slide 48 text

One to many relationships A user has many talks. Links via talks:user_id. class User extends Model { public function talks() { return $this->hasMany('App\Talk'); } } // usage: $talks = User::find(1)->talks; foreach ($talks as $talk) { /* … */ } Rob Allen ~ @akrabat | Gary Hockin ~ @geeh

Slide 49

Slide 49 text

One to many relationships Reverse: class Talk extends Model { public function user() { $this->belongsTo('App\User'); } } // usage: $user = Address::find(1)->user; Rob Allen ~ @akrabat | Gary Hockin ~ @geeh

Slide 50

Slide 50 text

Many to many relationships A user attends many events. Links via events_users. class User extends Model { public function events() { return $this->belongsToMany('App\Event'); } } // usage: $events = $user->events()->orderBy('event_date')->get(); foreach ($events as $event) { /* … */ } Rob Allen ~ @akrabat | Gary Hockin ~ @geeh

Slide 51

Slide 51 text

Many to many relationships Reverse is the same as definition for User. class Event extends Model { public function users() { return $this->belongsToMany('App\User'); } } // usage: $users = $e->users()->where('name', 'like', 'R%')->get(); foreach ($users as $user) { /* … */ } Rob Allen ~ @akrabat | Gary Hockin ~ @geeh

Slide 52

Slide 52 text

Migrations Store schema changes in code Create a migration: $ php artisan make:migration create_users_table Created Migration: 2018_03_31_143419_create_users_table Run migrations: $ php artisan migrate Rob Allen ~ @akrabat | Gary Hockin ~ @geeh

Slide 53

Slide 53 text

CreateUsersTable up(): The changes you want to make class CreateUsersTable extends Migration { public function up() { Schema::create('users', function (Blueprint $table) { $table->increments('id'); $table->timestamps(); }); } Rob Allen ~ @akrabat | Gary Hockin ~ @geeh

Slide 54

Slide 54 text

CreateUsersTable down(): Reverse your changes public function down() { Schema::dropIfExists('users'); } } Rob Allen ~ @akrabat | Gary Hockin ~ @geeh

Slide 55

Slide 55 text

Schema building Schema::create('users', function (Blueprint $table) { $table->increments('id'); $table->timestamps(); $table->string('username', 50); $table->string('name', 100); $table->date('date_of_birth')->nullable(); $table->boolean('active')->default(true); $table->unique('username'); }); Rob Allen ~ @akrabat | Gary Hockin ~ @geeh

Slide 56

Slide 56 text

Seeding Seed you database with test data Create a seeder: $ php artisan make:seeder UsersTableSeeder Run seeds: $ php artisan db:seed Rob Allen ~ @akrabat | Gary Hockin ~ @geeh

Slide 57

Slide 57 text

UsersTableSeeder class UsersTableSeeder extends Seeder { public function run() { DB::table('users')->insert([ ['username' => 'akrabat', 'name' => 'Rob'], ['username' => 'geeh', 'name' => 'Gary'], ]); } } Rob Allen ~ @akrabat | Gary Hockin ~ @geeh

Slide 58

Slide 58 text

Coding time! Rob Allen ~ @akrabat | Gary Hockin ~ @geeh

Slide 59

Slide 59 text

Form handling Rob Allen ~ @akrabat | Gary Hockin ~ @geeh

Slide 60

Slide 60 text

Forms • Write your form in HTML • Validate in a separate action controller • Supports Post-Redirect-Get pattern out of the box Rob Allen ~ @akrabat | Gary Hockin ~ @geeh

Slide 61

Slide 61 text

Set up routes One route for the form, one for processing it: // routes/web.php: Route::get('/user/edit/{id}', 'UserController@edit') ->name('user-edit'); Route::post('/user/doedit/{id}', 'UserController@doEdit') ->name('user-doedit'); Rob Allen ~ @akrabat | Gary Hockin ~ @geeh

Slide 62

Slide 62 text

A form On the /profile/edit/{id} page:

Update your profile

Name Update Rob Allen ~ @akrabat | Gary Hockin ~ @geeh

Slide 63

Slide 63 text

Validate request data class UserController extends Controller { public function doEdit(Request $request) { $data = $request->validate([ 'name' => 'required|max:100', ]); // The data is valid - save it return redirect()->route('user-profile'); } } Rob Allen ~ @akrabat | Gary Hockin ~ @geeh

Slide 64

Slide 64 text

$request->validate() • Validates the POSTed data against the rules array • Returns the data on success • Redirects back to the previous URL on failure (our form) Rules: • Format: 'fieldname' => 'rules|separated|by|pipes' • There's lots of validation rules; Look them up! Rob Allen ~ @akrabat | Gary Hockin ~ @geeh

Slide 65

Slide 65 text

Display errors • The $errors variable is available in your template • Use $errors->any() to test if you have any errors • Access errors: • Collection: $errors->all() • Individual: $errors->get('name') Rob Allen ~ @akrabat | Gary Hockin ~ @geeh

Slide 66

Slide 66 text

Coding time! Rob Allen ~ @akrabat | Gary Hockin ~ @geeh

Slide 67

Slide 67 text

Authentication Rob Allen ~ @akrabat | Gary Hockin ~ @geeh

Slide 68

Slide 68 text

Authentication • Provided for you out-of-the-box: • App\User model • Controllers for registration, login, forgot password & reset password • View templates in resources/views/auth • Database migrations for users & password_resets tables • Enable: $ php artisan make:auth $ php artisan migrate Rob Allen ~ @akrabat | Gary Hockin ~ @geeh

Slide 69

Slide 69 text

Operations Do we have a logged in user? $isLoggedIn = Auth::check(); Retrieve the logged in user: $user = Auth::user(); // or in a controller action: $user = $request->user(); Protect routes: Add the auth middleware to a route to restrict to logged in users Rob Allen ~ @akrabat | Gary Hockin ~ @geeh

Slide 70

Slide 70 text

Coding time! Rob Allen ~ @akrabat | Gary Hockin ~ @geeh

Slide 71

Slide 71 text

That's it! Rob Allen ~ @akrabat | Gary Hockin ~ @geeh

Slide 72

Slide 72 text

Resources • https://github.com/akrabat/laravel-bookshelf • https://laravel.com • https://laracasts.com • https://laravel-news.com • Laravel: Up and Running by Matt Stauffer Rob Allen ~ @akrabat | Gary Hockin ~ @geeh

Slide 73

Slide 73 text

Thank you! https://joind.in/talk/94c85 Rob Allen ~ @akrabat | Gary Hockin ~ @geeh