Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Leveraging Laravel: Launching Side Projects Quickly With Laravel

Leveraging Laravel: Launching Side Projects Quickly With Laravel

My talk from Laracon US 2015, Sunshine PHP 2016, and Nomad PHP February 2016

http://giscus.co/

http://github.com/tightenco/giscus

Matt Stauffer

August 11, 2015
Tweet

More Decks by Matt Stauffer

Other Decks in Technology

Transcript

  1. LEVERAGING LARAVEL @STAUFFERMATT
    LEVERAGING LARAVEL
    LAUNCHING SIDE PROJECTS
    QUICKLY WITH LARAVEL

    View Slide

  2. LEVERAGING LARAVEL @STAUFFERMATT
    LEVERAGING LARAVEL @STAUFFERMATT

    View Slide

  3. LEVERAGING LARAVEL @STAUFFERMATT
    LEVERAGING LARAVEL @STAUFFERMATT

    View Slide

  4. LEVERAGING LARAVEL @STAUFFERMATT
    LEVERAGING LARAVEL @STAUFFERMATT

    View Slide

  5. LEVERAGING LARAVEL @STAUFFERMATT
    LEVERAGING LARAVEL @STAUFFERMATT

    View Slide

  6. LEVERAGING LARAVEL @STAUFFERMATT
    A FEW OF MY SIDE PROJECTS

    View Slide

  7. LEVERAGING LARAVEL @STAUFFERMATT
    LEVERAGING LARAVEL @STAUFFERMATT

    View Slide

  8. LEVERAGING LARAVEL @STAUFFERMATT

    View Slide

  9. LEVERAGING LARAVEL @STAUFFERMATT
    LEVERAGING LARAVEL @STAUFFERMATT

    View Slide

  10. LEVERAGING LARAVEL @STAUFFERMATT
    LEVERAGING LARAVEL @STAUFFERMATT

    View Slide

  11. LEVERAGING LARAVEL @STAUFFERMATT

    View Slide

  12. LEVERAGING LARAVEL @STAUFFERMATT
    LEVERAGING LARAVEL @STAUFFERMATT

    View Slide

  13. LEVERAGING LARAVEL @STAUFFERMATT
    LEVERAGING LARAVEL @STAUFFERMATT

    View Slide

  14. LEVERAGING LARAVEL @STAUFFERMATT

    View Slide

  15. LEVERAGING LARAVEL @STAUFFERMATT
    LEVERAGING LARAVEL @STAUFFERMATT

    View Slide

  16. LEVERAGING LARAVEL @STAUFFERMATT
    RAD IS RAPID APPLICATION DEVELOPMENT
    Contrast to waterfall development
    Tied to Agile & other management/development practices
    Adjusting requirements as more knowledge gained
    In short: Develop applications… rapidly… then iterate

    View Slide

  17. LEVERAGING LARAVEL @STAUFFERMATT
    WHY DO WE CARE
    ABOUT RAD?

    View Slide

  18. LEVERAGING LARAVEL @STAUFFERMATT
    LEVERAGING LARAVEL @STAUFFERMATT

    View Slide

  19. LEVERAGING LARAVEL @STAUFFERMATT
    LEVERAGING LARAVEL @STAUFFERMATT

    View Slide

  20. LEVERAGING LARAVEL @STAUFFERMATT

    View Slide

  21. LEVERAGING LARAVEL @STAUFFERMATT
    LEVERAGING LARAVEL @STAUFFERMATT

    View Slide

  22. LEVERAGING LARAVEL @STAUFFERMATT
    LEVERAGING LARAVEL @STAUFFERMATT

    View Slide

  23. LEVERAGING LARAVEL @STAUFFERMATT
    LEVERAGING LARAVEL @STAUFFERMATT

    View Slide

  24. LEVERAGING LARAVEL @STAUFFERMATT
    LEVERAGING LARAVEL @STAUFFERMATT

    View Slide

  25. LEVERAGING LARAVEL @STAUFFERMATT
    WORKING FOR BIG AGENCIES
    TAUGHT ME HOW TO PRIORITIZE
    MY TIME AND TRIAGE MY
    REMAINING WORK

    View Slide

  26. LEVERAGING LARAVEL @STAUFFERMATT
    RAD says
    Prototype features
    Define Minimum Viable Product
    Launch early, Iterate Often

    View Slide

  27. LEVERAGING LARAVEL @STAUFFERMATT
    JUST SHIP IT

    View Slide

  28. LEVERAGING LARAVEL @STAUFFERMATT
    LEVERAGING LARAVEL @STAUFFERMATT

    View Slide

  29. LEVERAGING LARAVEL @STAUFFERMATT
    LEVERAGING LARAVEL @STAUFFERMATT

    View Slide

  30. LEVERAGING LARAVEL @STAUFFERMATT
    LEVERAGING LARAVEL @STAUFFERMATT

    View Slide

  31. LEVERAGING LARAVEL @STAUFFERMATT
    EVERYTHING IS
    DIFFERENT NOW.

    View Slide

  32. LEVERAGING LARAVEL @STAUFFERMATT
    LARAVEL’S RAD SOUL MEANS:
    Get the repetitive cruft out of the way
    so you can make awesome apps,

    fast.
    LEVERAGING LARAVEL @STAUFFERMATT

    View Slide

  33. LEVERAGING LARAVEL @STAUFFERMATT
    LEVERAGING LARAVEL @STAUFFERMATT

    View Slide

  34. LEVERAGING LARAVEL @STAUFFERMATT
    MOVING QUICKLY FROM IDEA TO MVP:

    THREE APPROACHES
    LEVERAGING LARAVEL @STAUFFERMATT
    1. Build the backend first with simple CRUD views

    (Create, Read, Update, Delete)
    2. Build frontend views with no/stubbed data
    3. Build individual features all through, one at a time

    View Slide

  35. LEVERAGING LARAVEL @STAUFFERMATT
    LEVERAGING LARAVEL @STAUFFERMATT

    View Slide

  36. LEVERAGING LARAVEL @STAUFFERMATT
    LEVERAGING LARAVEL @STAUFFERMATT

    View Slide

  37. LEVERAGING LARAVEL @STAUFFERMATT
    LEVERAGING LARAVEL @STAUFFERMATT

    View Slide

  38. LEVERAGING LARAVEL @STAUFFERMATT
    LEVERAGING LARAVEL @STAUFFERMATT

    View Slide

  39. LEVERAGING LARAVEL @STAUFFERMATT
    LEVERAGING LARAVEL @STAUFFERMATT

    View Slide

  40. LEVERAGING LARAVEL @STAUFFERMATT

    View Slide

  41. LEVERAGING LARAVEL @STAUFFERMATT

    View Slide

  42. LEVERAGING LARAVEL @STAUFFERMATT
    LEVERAGING LARAVEL @STAUFFERMATT

    View Slide

  43. LEVERAGING LARAVEL @STAUFFERMATT
    #YOUHAD

    ONEJOB

    View Slide

  44. LEVERAGING LARAVEL @STAUFFERMATT

    View Slide

  45. LEVERAGING LARAVEL @STAUFFERMATT

    View Slide

  46. LEVERAGING LARAVEL @STAUFFERMATT
    JTBD-LIGHT WHEN BUILDING SIDE PROJECTS
    Identify minimum functionality required
    to do this job (like TDD),

    then build that out frontend-to-backend;
    launch, gather feedback, repeat

    View Slide

  47. LEVERAGING LARAVEL @STAUFFERMATT
    LET’S build
    SOMETHING.

    View Slide

  48. LEVERAGING LARAVEL @STAUFFERMATT
    *(ONE MORE REASON OUR IDEAS DON’T BECOME REALITY:
    Moving from a general idea of how a technology works
    to understanding how to concretely implement it right now
    can often eat up all the time on your side projects)

    View Slide

  49. LEVERAGING LARAVEL @STAUFFERMATT
    WHAT JOB DOES MY TARGET
    AUDIENCE WANT TO GET DONE?
    ?

    View Slide

  50. LEVERAGING LARAVEL @STAUFFERMATT

    View Slide

  51. LEVERAGING LARAVEL @STAUFFERMATT
    “I want a tool that notifies me
    when someone comments
    on one of my Gists”

    View Slide

  52. LEVERAGING LARAVEL @STAUFFERMATT
    @TODO: VALIDATE

    View Slide

  53. LEVERAGING LARAVEL @STAUFFERMATT

    View Slide

  54. LEVERAGING LARAVEL @STAUFFERMATT
    OK, WHAT SCREENS WILL WE NEED?
    Landing (sales) page
    User signup (enters payment
    information and agrees to pay $3/mo)
    User dashboard

    View Slide

  55. LEVERAGING LARAVEL @STAUFFERMATT
    LET’S DRAW IT OUT.
    LEVERAGING LARAVEL @STAUFFERMATT

    View Slide

  56. LEVERAGING LARAVEL @STAUFFERMATT

    View Slide

  57. LEVERAGING LARAVEL @STAUFFERMATT

    View Slide

  58. LEVERAGING LARAVEL @STAUFFERMATT
    LEVERAGING LARAVEL @STAUFFERMATT

    View Slide

  59. LEVERAGING LARAVEL @STAUFFERMATT

    View Slide

  60. LEVERAGING LARAVEL @STAUFFERMATT
    LEVERAGING LARAVEL @STAUFFERMATT

    View Slide

  61. LEVERAGING LARAVEL @STAUFFERMATT
    Develop with Homestead
    Create Laravel Application
    Use Elixir & Bootstrap
    Configure Users & Socialite
    Stub Routes, Controllers, and Views
    Make the core functionality
    Take Payments with Cashier
    Deploy with Forge
    PROCESS

    View Slide

  62. LEVERAGING LARAVEL @STAUFFERMATT
    Develop with Homestead
    Create Laravel Application
    Use Elixir & Bootstrap
    Configure Users & Socialite
    Stub Routes, Controllers, and Views
    Make the core functionality
    Take Payments with Cashier
    Deploy with Forge
    DEVELOPMENT ENVIRONMENT
    BOOTSTRAP APPLICATION
    WRITE SPECIFIC FUNCTIONALITY
    PAYMENTS
    DEPLOY

    View Slide

  63. LEVERAGING LARAVEL @STAUFFERMATT
    {
    SAME ACROSS
    MOST PROJECTS
    {
    SAME ACROSS
    MOST PROJECTS
    Develop with Homestead
    Create Laravel Application
    Use Elixir & Bootstrap
    Configure Users & Socialite
    Stub Routes, Controllers, and Views
    Make the core functionality
    Take Payments with Cashier
    Deploy with Forge

    View Slide

  64. LEVERAGING LARAVEL @STAUFFERMATT
    Develop with Homestead
    Create Laravel Application
    Use Elixir & Bootstrap
    Configure Users & Socialite
    Stub Routes, Controllers, and Views
    Make the core functionality
    Take Payments with Cashier
    Deploy with Forge
    PROCESS

    View Slide

  65. LEVERAGING LARAVEL @STAUFFERMATT
    LEVERAGING LARAVEL @STAUFFERMATT
    http://laravel.com/docs/homestead

    View Slide

  66. LEVERAGING LARAVEL @STAUFFERMATT
    Develop with Homestead
    Create Laravel Application
    Use Elixir & Bootstrap
    Configure Users & Socialite
    Stub Routes, Controllers, and Views
    Make the core functionality
    Take Payments with Cashier
    Deploy with Forge
    PROCESS

    View Slide

  67. LEVERAGING LARAVEL @STAUFFERMATT
    $ laravel new giscus

    View Slide

  68. LEVERAGING LARAVEL @STAUFFERMATT
    $ laravel new giscus
    ... some
    ... boring
    ... installation
    ... stuff
    Application ready! Build something amazing.

    View Slide

  69. LEVERAGING LARAVEL @STAUFFERMATT
    $ cd giscus
    $ cp .env.example .env
    $ php artisan key:generate
    $ php artisan serve

    View Slide

  70. LEVERAGING LARAVEL @STAUFFERMATT

    View Slide

  71. LEVERAGING LARAVEL @STAUFFERMATT
    Develop with Homestead
    Create Laravel Application
    Use Elixir & Bootstrap
    Configure Users & Socialite
    Stub Routes, Controllers, and Views
    Make the core functionality
    Take Payments with Cashier
    Deploy with Forge
    PROCESS

    View Slide

  72. LEVERAGING LARAVEL @STAUFFERMATT
    LEVERAGING LARAVEL @STAUFFERMATT

    View Slide

  73. LEVERAGING LARAVEL @STAUFFERMATT
    // gulpfile.js
    var elixir = require(‘laravel-elixir’);
    /*
    |--------------------------------------------------------------------------
    | Elixir Asset Management
    |--------------------------------------------------------------------------
    |
    | Elixir provides a clean, fluent API for defining some basic Gulp tasks
    | for your Laravel application. By default, we are compiling the Sass
    | file for our application, as well as publishing vendor resources.
    |
    */
    elixir(function(mix) {
    mix.sass(‘app.scss’);
    });

    View Slide

  74. LEVERAGING LARAVEL @STAUFFERMATT
    $ npm install
    $ gulp watch

    View Slide

  75. LEVERAGING LARAVEL @STAUFFERMATT
    // In resources/assets/sass/app.scss
    // Un-comment this, and boom, you’ve got Bootstrap:
    @import “node_modules/bootstrap-sass/assets/stylesheets/bootstrap”;

    View Slide

  76. LEVERAGING LARAVEL @STAUFFERMATT

    View Slide

  77. LEVERAGING LARAVEL @STAUFFERMATT

    View Slide

  78. LEVERAGING LARAVEL @STAUFFERMATT

    View Slide

  79. LEVERAGING LARAVEL @STAUFFERMATT

    View Slide

  80. LEVERAGING LARAVEL @STAUFFERMATT
    LEVERAGING LARAVEL @STAUFFERMATT

    View Slide

  81. LEVERAGING LARAVEL @STAUFFERMATT

    View Slide

  82. LEVERAGING LARAVEL @STAUFFERMATT
    LEVERAGING LARAVEL @STAUFFERMATT

    View Slide

  83. LEVERAGING LARAVEL @STAUFFERMATT

    View Slide

  84. LEVERAGING LARAVEL @STAUFFERMATT
    Develop with Homestead
    Create Laravel Application
    Use Elixir & Bootstrap
    Configure Users & Socialite
    Stub Routes, Controllers, and Views
    Make the core functionality
    Take Payments with Cashier
    Deploy with Forge
    PROCESS

    View Slide

  85. LEVERAGING LARAVEL @STAUFFERMATT
    LEVERAGING LARAVEL @STAUFFERMATT
    What’s going to back this data?
    Eloquent User model
    Laravel Socialite
    GitHub (OAuth)

    View Slide

  86. LEVERAGING LARAVEL @STAUFFERMATT
    GITHUB AUTH WITH SOCIALITE
    LEVERAGING LARAVEL @STAUFFERMATT
    BASICS:
    Install Socialite with Composer
    Set up GitHub Application
    Paste OAuth Credentials into Laravel config file
    Set up a few routes for OAuth
    https://mattstauffer.co/blog/using-github-
    authentication-for-login-with-laravel-socialite

    View Slide

  87. LEVERAGING LARAVEL @STAUFFERMATT

    View Slide

  88. LEVERAGING LARAVEL @STAUFFERMATT
    Develop with Homestead
    Create Laravel Application
    Use Elixir & Bootstrap
    Configure Users & Socialite
    Stub Routes, Controllers, and Views
    Make the core functionality
    Take Payments with Cashier
    Deploy with Forge
    PROCESS

    View Slide

  89. LEVERAGING LARAVEL @STAUFFERMATT
    WHAT ARE OUR ROUTES?
    Home page
    GitHub auth
    (GitHub auth callback)
    Initial sign-up
    Dashboard
    Logout

    View Slide

  90. LEVERAGING LARAVEL @STAUFFERMATT
    LEVERAGING LARAVEL @STAUFFERMATT
    WHAT ARE OUR ROUTES?
    Home page
    GitHub auth
    (GitHub auth callback)
    Initial sign-up
    Dashboard
    Logout
    /
    /auth/github
    /auth/github/callback
    /sign-up
    /dashboard
    /logout

    View Slide

  91. LEVERAGING LARAVEL @STAUFFERMATT
    STUB CONTROLLERS AND VIEWS
    // app/Http/routes.php
    Route::get('/', '[email protected]');
    Route::get('auth/github', '[email protected]');
    Route::post('auth/github/callback',
    '[email protected]');
    Route::get('sign-up', '[email protected]');
    Route::get('dashboard', '[email protected]');
    Route::get('logout', '[email protected]');

    View Slide

  92. LEVERAGING LARAVEL @STAUFFERMATT
    STUB CONTROLLERS AND VIEWS
    class SalesController extends Controller
    {
    public function index()
    {
    return view('sales');
    }
    }

    View Slide

  93. LEVERAGING LARAVEL @STAUFFERMATT
    STUB CONTROLLERS AND VIEWS
    class SignupController extends Controller
    {
    public function index()
    {
    return view(‘sign-up');
    }
    }

    View Slide

  94. LEVERAGING LARAVEL @STAUFFERMATT
    STUB CONTROLLERS AND VIEWS
    class DashboardController extends Controller
    {
    public function index()
    {
    return view('dashboard');
    }
    }

    View Slide

  95. LEVERAGING LARAVEL @STAUFFERMATT
    STUB CONTROLLERS AND VIEWS
    use Illuminate\Support\Facades\Auth;
    use Illuminate\Support\Facades\Redirect;
    class AuthController extends Controller
    {
    // ... lots of Socialite stuff
    public function logout()
    {
    Auth::logout();
    return redirect('/');
    }
    }

    View Slide

  96. LEVERAGING LARAVEL @STAUFFERMATT
    BUILD VIEWS: MASTER BLADE LAYOUT













    View Slide

  97. LEVERAGING LARAVEL @STAUFFERMATT
    BUILD VIEWS: MASTER BLADE LAYOUT








    @yield('content')

    @yield('footerScripts')


    View Slide

  98. LEVERAGING LARAVEL @STAUFFERMATT
    BUILD VIEWS: CHILD EXTENSIONS

    View Slide

  99. LEVERAGING LARAVEL @STAUFFERMATT
    BUILD VIEWS: CHILD EXTENSIONS

    View Slide

  100. LEVERAGING LARAVEL @STAUFFERMATT
    BUILD VIEWS: CHILD EXTENSIONS

    View Slide

  101. LEVERAGING LARAVEL @STAUFFERMATT
    layouts/app.blade.php
    @yield(‘content’) @yield(‘footerScripts’)
    sign-up.blade.php @extends(‘layouts.app’)
    @section(‘content’) @section(‘footerScripts’)
    sales.blade.php @extends(‘layouts.app’)
    @section(‘content’) @section(‘footerScripts’)

    View Slide

  102. LEVERAGING LARAVEL @STAUFFERMATT

    View Slide

  103. LEVERAGING LARAVEL @STAUFFERMATT
    Develop with Homestead
    Create Laravel Application
    Use Elixir & Bootstrap
    Configure Users & Socialite
    Stub Routes, Controllers, and Views
    Make the core functionality
    Take Payments with Cashier
    Deploy with Forge
    PROCESS

    View Slide

  104. LEVERAGING LARAVEL @STAUFFERMATT

    View Slide

  105. LEVERAGING LARAVEL @STAUFFERMATT
    FIRST: WHAT SHOULD THE FEATURE OPERATE
    LIKE AT THE HIGHEST LEVEL?
    Cron running through all users
    For each user, get any new Gist
    comments since last cron
    Send notification email for
    each new comment

    View Slide

  106. LEVERAGING LARAVEL @STAUFFERMATT
    // Pseudo code
    foreach ($users as $user) {
    $user->notifyOfNewGistComments();
    }

    View Slide

  107. LEVERAGING LARAVEL @STAUFFERMATT
    // Get all users from Eloquent
    User::all()->each(function ($user) {
    // Queue a command and pass in the user
    Queue::push(NotifyUserOfNewGistComments::class, [
    ‘user’ => $user
    ]);
    });

    View Slide

  108. LEVERAGING LARAVEL @STAUFFERMATT
    ...
    class NotifyUserOfNewGistComments extends Job
    {
    ...
    public function fire($job, $data)
    {
    // Authorize as this user
    // Get all new gist comments for this user
    // Kick off a notification email for comment
    }
    }

    View Slide

  109. LEVERAGING LARAVEL @STAUFFERMATT
    ...
    class NotifyUserOfNewGistComments extends Job
    {
    ...
    public function fire($job, $data)
    {
    $this->client->authorizeAs($data['user']->stuff);
    foreach ($this->client->newGistComments() as $comment) {
    Queue::push(NotifyUserOfNewGistComment::class, [
    'user' => $data['user'],
    'comment' => $comment
    ]);
    }
    }
    }

    View Slide

  110. LEVERAGING LARAVEL @STAUFFERMATT
    ...
    class NotifyUserOfNewGistComment extends Job
    {
    ...
    public function fire($job, $data)
    {
    // Send an email to $data[‘user’] with info about $data[‘comment’]
    }
    }

    View Slide

  111. LEVERAGING LARAVEL @STAUFFERMATT
    LEVERAGING LARAVEL @STAUFFERMATT

    View Slide

  112. LEVERAGING LARAVEL @STAUFFERMATT
    LEVERAGING LARAVEL @STAUFFERMATT

    View Slide

  113. LEVERAGING LARAVEL @STAUFFERMATT
    $ composer install knplabs/github-api:~1.4

    View Slide

  114. LEVERAGING LARAVEL @STAUFFERMATT
    public function __construct(\Github\Client $client)
    {
    $this->client = $client;
    }
    Update injection…

    View Slide

  115. LEVERAGING LARAVEL @STAUFFERMATT
    $this->client->authenticate(
    $data[‘user’]->github_token,
    Client::AUTH_HTTP_TOKEN
    );
    Update authorization…

    View Slide

  116. LEVERAGING LARAVEL @STAUFFERMATT
    public function fire()
    {
    foreach ($this->client->api('gists')->all() as $gist) {
    foreach ($this->client->api('gist')->comments()->all($gist['id']) as $comment) {
    $this->handleComment($comment, $gist, $data['user']);
    }
    }
    }

    View Slide

  117. LEVERAGING LARAVEL @STAUFFERMATT
    public function handleComment($comment, $gist, $user)
    {
    if ($this->commentNeedsNotification($comment)) {
    $this->notifyComment($comment, $gist, $user);
    }
    }

    View Slide

  118. LEVERAGING LARAVEL @STAUFFERMATT
    public function commentNeedsNotification($comment)
    {
    return NotifiedComment::where('github_id', $comment['id'])
    ->where('updated_at', $comment['updated_at'])
    ->count() == 0;
    }
    public function notifyComment($comment, $gist, $user)
    {
    Queue::push(NotifyUserOfNewGistComment::class, [
    'user' => $user,
    'comment' => $comment,
    'gist' => $gist
    ]);
    }

    View Slide

  119. LEVERAGING LARAVEL @STAUFFERMATT
    ...
    class NotifyUserOfNewGistComment extends Job
    {
    ...
    public function fire($job, $data)
    {
    $this->sendNotificationEmail(
    $data[‘comment’],
    $data[‘gist’],
    $data[‘user’],
    );
    $this->markCommentAsNotified($data[‘comment’]);
    }
    }

    View Slide

  120. LEVERAGING LARAVEL @STAUFFERMATT
    private function sendNotificationEmail($comment, $gist, $user)
    {
    Mail::send(
    'emails.new-comment',
    [
    'comment' => $comment,
    'gist' => $gist,
    'user' => $user
    ],
    function ($message) use ($user) {
    $message
    ->to($data['user']->email, $data['user']->name)
    ->subject('You have a new Gist Comment!');
    }
    );
    }

    View Slide

  121. LEVERAGING LARAVEL @STAUFFERMATT
    private function markCommentAsNotified($comment)
    {
    $eloquentComment = NotifiedComment::firstOrNew([
    'github_id' => $comment['id']
    ]);
    $eloquentComment->github_updated_at = $comment['updated_at'];
    $eloquentComment->save();
    }

    View Slide

  122. LEVERAGING LARAVEL @STAUFFERMATT
    $ php artisan make:migration create_notified_comments_table

    View Slide

  123. LEVERAGING LARAVEL @STAUFFERMATT
    Schema::create('notified_comments', function (Blueprint $table) {
    $table->increments('id');
    $table->integer('github_id')->unique();
    $table->timestamp('github_updated_at')->nullable();
    $table->timestamps();
    });

    View Slide

  124. LEVERAGING LARAVEL @STAUFFERMATT
    $ php artisan make:model NotifiedComment

    View Slide

  125. LEVERAGING LARAVEL @STAUFFERMATT
    protected $fillable = ['github_id'];

    View Slide

  126. LEVERAGING LARAVEL @STAUFFERMATT

    You received a new comment on a Gist,
    {{ $gist['description'] }}.





    {{ $comment['user']['login'] }}

    commented

    {{ $date->diffForHumans() }}


    {!! Markdown::parse($comment['body']) !!}


    View Slide

  127. LEVERAGING LARAVEL @STAUFFERMATT
    // app/Console/Kernel.php
    $schedule->call(function () {
    User::all()->each(function ($user) {
    Queue::push(NotifyUserOfNewGistComments::class, [
    'user' => $user
    ]);
    });
    })->hourly();

    View Slide

  128. LEVERAGING LARAVEL @STAUFFERMATT
    LEVERAGING LARAVEL @STAUFFERMATT

    View Slide

  129. LEVERAGING LARAVEL @STAUFFERMATT
    Develop with Homestead
    Create Laravel Application
    Use Elixir & Bootstrap
    Configure Users & Socialite
    Stub Routes, Controllers, and Views
    Make the core functionality
    Take Payments with Cashier
    Deploy with Forge
    PROCESS

    View Slide

  130. LEVERAGING LARAVEL @STAUFFERMATT
    TAKING PAYMENTS WITH CASHIER
    1) CREATE PLAN IN YOUR STRIPE ACCOUNT

    View Slide

  131. LEVERAGING LARAVEL @STAUFFERMATT
    TAKING PAYMENTS WITH CASHIER
    2) INSTALL CASHIER
    Then add
    to service providers array in
    $ composer require laravel/cashier:~5.0
    Laravel\Cashier\CashierServiceProvider::class
    config/app.php

    View Slide

  132. LEVERAGING LARAVEL @STAUFFERMATT
    TAKING PAYMENTS WITH CASHIER
    $ php artisan cashier:table users
    $ php artisan migrate
    3) ADD CASHIER FIELDS TO USERS TABLE

    View Slide

  133. LEVERAGING LARAVEL @STAUFFERMATT
    TAKING PAYMENTS WITH CASHIER
    use Laravel\Cashier\Billable;
    use Laravel\Cashier\Contracts\Billable as BillableContract;
    class User extends Model implements BillableContract
    {
    use Billable;
    protected $dates = ['trial_ends_at', 'subscription_ends_at'];
    ...
    4) ADD CASHIER TRAITS TO USER MODEL

    View Slide

  134. LEVERAGING LARAVEL @STAUFFERMATT
    TAKING PAYMENTS WITH CASHIER
    // services.php
    'stripe' => [
    'model' => App\User::class,
    'key' => env('STRIPE_API_KEY'),
    'secret' => env('STRIPE_API_SECRET'),
    ],
    5) SET STRIPE API KEY & SECRET

    View Slide

  135. LEVERAGING LARAVEL @STAUFFERMATT

    View Slide

  136. LEVERAGING LARAVEL @STAUFFERMATT
    TAKING PAYMENTS WITH CASHIER

    src="https://checkout.stripe.com/checkout.js" class="stripe-button"
    data-key="pk_test_n6DGsasdoifjpqowerjPOERW"
    data-amount="300"
    data-name="Giscus"
    data-description="Monthly Subscription ($3/mo)"
    data-image="/128x128.png">


    6) COPY STRIPE EMBEDDED HTML FROM DOCS INTO YOUR APP

    View Slide

  137. LEVERAGING LARAVEL @STAUFFERMATT

    View Slide

  138. LEVERAGING LARAVEL @STAUFFERMATT
    TAKING PAYMENTS WITH CASHIER
    Route::get('sign-up', function () {
    return view('sign-up-form-from-stripe');
    });
    Route::post('sign-up', function () {
    $token = Input::get('stripeToken');
    Auth::user()->subscription('monthly')->create($token);
    return 'Subscribed!';
    });
    7) CREATE ROUTES FOR THE STRIPE CREDIT CARD FORM

    View Slide

  139. LEVERAGING LARAVEL @STAUFFERMATT
    TAKING PAYMENTS WITH CASHIER
    8) ADD A SUBSCRIBED MIDDLEWARE
    then edit:
    $ php artisan make:middleware Subscribed
    public function handle($request, $next)
    {
    if (! Auth::user()->subscribed()) {
    return redirect('sign-up');
    }
    return $next->$request;
    }

    View Slide

  140. LEVERAGING LARAVEL @STAUFFERMATT
    TAKING PAYMENTS WITH CASHIER
    8) ADD A SUBSCRIBED MIDDLEWARE (CONTINUED)
    Then add to app/Http/kernel.php
    as a route middleware

    View Slide

  141. LEVERAGING LARAVEL @STAUFFERMATT
    LEVERAGING LARAVEL @STAUFFERMATT
    TAKING PAYMENTS WITH CASHIER
    9) ADD A ROUTE FOR YOUR CANCEL BUTTON
    Route::get('user/cancel', function() {
    Auth::user()->subscription()->cancel();
    return redirect('/');
    });

    View Slide

  142. LEVERAGING LARAVEL @STAUFFERMATT
    TAKING PAYMENTS WITH CASHIER
    10) SHOW INVOICES
    // In a view somewhere…
    @foreach (Auth::user()->invoices() as $invoice)
    {{ $invoice->dateString() }} |
    {{ $invoice->dollars() }} |
    Download
    @endforeach
    // routes.php…
    Route::get('user/invoice/{invoice}', function ($invoiceId) {
    return Auth::user()->downloadInvoice($invoiceId, [
    'vendor' => 'Tighten Co.',
    'product' => 'Giscus',
    ]);
    });

    View Slide

  143. LEVERAGING LARAVEL @STAUFFERMATT
    TAKING PAYMENTS WITH CASHIER
    Route::post(
    'stripe/webhook',
    '\Laravel\Cashier\[email protected]'
    );
    11) HANDLE WEB HOOKS

    View Slide

  144. LEVERAGING LARAVEL @STAUFFERMATT
    Develop with Homestead
    Create Laravel Application
    Use Elixir & Bootstrap
    Configure Users & Socialite
    Stub Routes, Controllers, and Views
    Make the core functionality
    Take Payments with Cashier
    Deploy with Forge
    PROCESS

    View Slide

  145. LEVERAGING LARAVEL @STAUFFERMATT
    LEVERAGING LARAVEL @STAUFFERMATT

    View Slide

  146. LEVERAGING LARAVEL @STAUFFERMATT
    (INTERLUDE: TESTS)

    View Slide

  147. LEVERAGING LARAVEL @STAUFFERMATT
    LEVERAGING LARAVEL @STAUFFERMATT

    View Slide

  148. LEVERAGING LARAVEL @STAUFFERMATT
    LEVERAGING LARAVEL @STAUFFERMATT

    View Slide

  149. LEVERAGING LARAVEL @STAUFFERMATT
    LEVERAGING LARAVEL @STAUFFERMATT

    View Slide

  150. LEVERAGING LARAVEL @STAUFFERMATT
    LEVERAGING LARAVEL @STAUFFERMATT

    View Slide

  151. LEVERAGING LARAVEL @STAUFFERMATT
    LEVERAGING LARAVEL @STAUFFERMATT

    View Slide

  152. LEVERAGING LARAVEL @STAUFFERMATT
    LEVERAGING LARAVEL @STAUFFERMATT

    View Slide

  153. LEVERAGING LARAVEL @STAUFFERMATT
    LEVERAGING LARAVEL @STAUFFERMATT

    View Slide

  154. LEVERAGING LARAVEL @STAUFFERMATT
    LEVERAGING LARAVEL @STAUFFERMATT

    View Slide

  155. LEVERAGING LARAVEL @STAUFFERMATT
    LEVERAGING LARAVEL @STAUFFERMATT

    View Slide

  156. LEVERAGING LARAVEL @STAUFFERMATT
    Set up email (Mandrill, Mailgun, etc.) and other services
    to function correctly from your live site
    8) CONNECT TO THIRD-PARTY SERVICES

    View Slide

  157. LEVERAGING LARAVEL @STAUFFERMATT
    LEVERAGING LARAVEL @STAUFFERMATT

    View Slide

  158. LEVERAGING LARAVEL @STAUFFERMATT
    LEVERAGING LARAVEL @STAUFFERMATT

    View Slide

  159. LEVERAGING LARAVEL @STAUFFERMATT

    View Slide

  160. LEVERAGING LARAVEL @STAUFFERMATT
    YOU HAVE GREAT IDEAS.
    ELIMINATE BARRIERS TO SHIPPING.
    SHIP EARLY, GET FEEDBACK, ITERATE.
    PICK ONE FEATURE; WRITE THE API; MAKE IT FUNCTION.
    Takeaways

    View Slide

  161. LEVERAGING LARAVEL @STAUFFERMATT
    go forth
    and create
    great apps

    View Slide