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

60187fe0ab07ea5a46572a3ab05f61dd?s=128

Matt Stauffer

August 11, 2015
Tweet

Transcript

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

    LARAVEL
  2. LEVERAGING LARAVEL @STAUFFERMATT LEVERAGING LARAVEL @STAUFFERMATT

  3. LEVERAGING LARAVEL @STAUFFERMATT LEVERAGING LARAVEL @STAUFFERMATT

  4. LEVERAGING LARAVEL @STAUFFERMATT LEVERAGING LARAVEL @STAUFFERMATT

  5. LEVERAGING LARAVEL @STAUFFERMATT LEVERAGING LARAVEL @STAUFFERMATT

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

  7. LEVERAGING LARAVEL @STAUFFERMATT LEVERAGING LARAVEL @STAUFFERMATT

  8. LEVERAGING LARAVEL @STAUFFERMATT

  9. LEVERAGING LARAVEL @STAUFFERMATT LEVERAGING LARAVEL @STAUFFERMATT

  10. LEVERAGING LARAVEL @STAUFFERMATT LEVERAGING LARAVEL @STAUFFERMATT

  11. LEVERAGING LARAVEL @STAUFFERMATT

  12. LEVERAGING LARAVEL @STAUFFERMATT LEVERAGING LARAVEL @STAUFFERMATT

  13. LEVERAGING LARAVEL @STAUFFERMATT LEVERAGING LARAVEL @STAUFFERMATT

  14. LEVERAGING LARAVEL @STAUFFERMATT

  15. LEVERAGING LARAVEL @STAUFFERMATT LEVERAGING LARAVEL @STAUFFERMATT

  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
  17. LEVERAGING LARAVEL @STAUFFERMATT WHY DO WE CARE ABOUT RAD?

  18. LEVERAGING LARAVEL @STAUFFERMATT LEVERAGING LARAVEL @STAUFFERMATT

  19. LEVERAGING LARAVEL @STAUFFERMATT LEVERAGING LARAVEL @STAUFFERMATT

  20. LEVERAGING LARAVEL @STAUFFERMATT

  21. LEVERAGING LARAVEL @STAUFFERMATT LEVERAGING LARAVEL @STAUFFERMATT

  22. LEVERAGING LARAVEL @STAUFFERMATT LEVERAGING LARAVEL @STAUFFERMATT

  23. LEVERAGING LARAVEL @STAUFFERMATT LEVERAGING LARAVEL @STAUFFERMATT

  24. LEVERAGING LARAVEL @STAUFFERMATT LEVERAGING LARAVEL @STAUFFERMATT

  25. LEVERAGING LARAVEL @STAUFFERMATT WORKING FOR BIG AGENCIES TAUGHT ME HOW

    TO PRIORITIZE MY TIME AND TRIAGE MY REMAINING WORK
  26. LEVERAGING LARAVEL @STAUFFERMATT RAD says Prototype features Define Minimum Viable

    Product Launch early, Iterate Often
  27. LEVERAGING LARAVEL @STAUFFERMATT JUST SHIP IT

  28. LEVERAGING LARAVEL @STAUFFERMATT LEVERAGING LARAVEL @STAUFFERMATT

  29. LEVERAGING LARAVEL @STAUFFERMATT LEVERAGING LARAVEL @STAUFFERMATT

  30. LEVERAGING LARAVEL @STAUFFERMATT LEVERAGING LARAVEL @STAUFFERMATT

  31. LEVERAGING LARAVEL @STAUFFERMATT EVERYTHING IS DIFFERENT NOW.

  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
  33. LEVERAGING LARAVEL @STAUFFERMATT LEVERAGING LARAVEL @STAUFFERMATT

  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
  35. LEVERAGING LARAVEL @STAUFFERMATT LEVERAGING LARAVEL @STAUFFERMATT

  36. LEVERAGING LARAVEL @STAUFFERMATT LEVERAGING LARAVEL @STAUFFERMATT

  37. LEVERAGING LARAVEL @STAUFFERMATT LEVERAGING LARAVEL @STAUFFERMATT

  38. LEVERAGING LARAVEL @STAUFFERMATT LEVERAGING LARAVEL @STAUFFERMATT

  39. LEVERAGING LARAVEL @STAUFFERMATT LEVERAGING LARAVEL @STAUFFERMATT

  40. LEVERAGING LARAVEL @STAUFFERMATT

  41. LEVERAGING LARAVEL @STAUFFERMATT

  42. LEVERAGING LARAVEL @STAUFFERMATT LEVERAGING LARAVEL @STAUFFERMATT

  43. LEVERAGING LARAVEL @STAUFFERMATT #YOUHAD
 ONEJOB

  44. LEVERAGING LARAVEL @STAUFFERMATT

  45. LEVERAGING LARAVEL @STAUFFERMATT

  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
  47. LEVERAGING LARAVEL @STAUFFERMATT LET’S build SOMETHING.

  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)
  49. LEVERAGING LARAVEL @STAUFFERMATT WHAT JOB DOES MY TARGET AUDIENCE WANT

    TO GET DONE? ?
  50. LEVERAGING LARAVEL @STAUFFERMATT

  51. LEVERAGING LARAVEL @STAUFFERMATT “I want a tool that notifies me

    when someone comments on one of my Gists”
  52. LEVERAGING LARAVEL @STAUFFERMATT @TODO: VALIDATE

  53. LEVERAGING LARAVEL @STAUFFERMATT

  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
  55. LEVERAGING LARAVEL @STAUFFERMATT LET’S DRAW IT OUT. LEVERAGING LARAVEL @STAUFFERMATT

  56. LEVERAGING LARAVEL @STAUFFERMATT

  57. LEVERAGING LARAVEL @STAUFFERMATT

  58. LEVERAGING LARAVEL @STAUFFERMATT LEVERAGING LARAVEL @STAUFFERMATT

  59. LEVERAGING LARAVEL @STAUFFERMATT

  60. LEVERAGING LARAVEL @STAUFFERMATT LEVERAGING LARAVEL @STAUFFERMATT

  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
  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
  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
  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
  65. LEVERAGING LARAVEL @STAUFFERMATT LEVERAGING LARAVEL @STAUFFERMATT http://laravel.com/docs/homestead

  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
  67. LEVERAGING LARAVEL @STAUFFERMATT $ laravel new giscus

  68. LEVERAGING LARAVEL @STAUFFERMATT $ laravel new giscus ... some ...

    boring ... installation ... stuff Application ready! Build something amazing.
  69. LEVERAGING LARAVEL @STAUFFERMATT $ cd giscus $ cp .env.example .env

    $ php artisan key:generate $ php artisan serve
  70. LEVERAGING LARAVEL @STAUFFERMATT

  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
  72. LEVERAGING LARAVEL @STAUFFERMATT LEVERAGING LARAVEL @STAUFFERMATT

  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’); });
  74. LEVERAGING LARAVEL @STAUFFERMATT $ npm install $ gulp watch

  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”;
  76. LEVERAGING LARAVEL @STAUFFERMATT <link rel=“stylesheet” href=“/css/app.css”>

  77. LEVERAGING LARAVEL @STAUFFERMATT

  78. LEVERAGING LARAVEL @STAUFFERMATT

  79. LEVERAGING LARAVEL @STAUFFERMATT

  80. LEVERAGING LARAVEL @STAUFFERMATT LEVERAGING LARAVEL @STAUFFERMATT

  81. LEVERAGING LARAVEL @STAUFFERMATT

  82. LEVERAGING LARAVEL @STAUFFERMATT LEVERAGING LARAVEL @STAUFFERMATT

  83. LEVERAGING LARAVEL @STAUFFERMATT

  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
  85. LEVERAGING LARAVEL @STAUFFERMATT LEVERAGING LARAVEL @STAUFFERMATT What’s going to back

    this data? Eloquent User model Laravel Socialite GitHub (OAuth)
  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
  87. LEVERAGING LARAVEL @STAUFFERMATT

  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
  89. LEVERAGING LARAVEL @STAUFFERMATT WHAT ARE OUR ROUTES? Home page GitHub

    auth (GitHub auth callback) Initial sign-up Dashboard Logout
  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
  91. LEVERAGING LARAVEL @STAUFFERMATT STUB CONTROLLERS AND VIEWS // app/Http/routes.php Route::get('/',

    'SalesController@index'); Route::get('auth/github', 'AuthController@github'); Route::post('auth/github/callback', 'AuthController@githubCallback'); Route::get('sign-up', 'SignupController@index'); Route::get('dashboard', 'DashboardController@index'); Route::get('logout', 'AuthController@logout');
  92. LEVERAGING LARAVEL @STAUFFERMATT STUB CONTROLLERS AND VIEWS <?php namespace App\Http\Controllers;

    class SalesController extends Controller { public function index() { return view('sales'); } }
  93. LEVERAGING LARAVEL @STAUFFERMATT STUB CONTROLLERS AND VIEWS <?php namespace App\Http\Controllers;

    class SignupController extends Controller { public function index() { return view(‘sign-up'); } }
  94. LEVERAGING LARAVEL @STAUFFERMATT STUB CONTROLLERS AND VIEWS <?php namespace App\Http\Controllers;

    class DashboardController extends Controller { public function index() { return view('dashboard'); } }
  95. LEVERAGING LARAVEL @STAUFFERMATT STUB CONTROLLERS AND VIEWS <?php namespace App\Http\Controllers;

    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('/'); } }
  96. LEVERAGING LARAVEL @STAUFFERMATT BUILD VIEWS: MASTER BLADE LAYOUT <!-- resources/views/layouts/app.blade.php

    --> <html> <head> <!-- etc. --> </head> <body> <div class="container"> <!-- header, nav, etc. --> <!-- Content here --> </div> <!-- Footer scripts here --> </body> </html>
  97. LEVERAGING LARAVEL @STAUFFERMATT BUILD VIEWS: MASTER BLADE LAYOUT <!-- resources/views/layouts/app.blade.php

    --> <html> <head> <!-- etc. --> </head> <body> <div class="container"> <!-- header, nav, etc. --> @yield('content') </div> @yield('footerScripts') </body> </html>
  98. LEVERAGING LARAVEL @STAUFFERMATT BUILD VIEWS: CHILD EXTENSIONS <!-- resources/views/home.blade.php -—>

    @extends('layouts.app')
  99. LEVERAGING LARAVEL @STAUFFERMATT BUILD VIEWS: CHILD EXTENSIONS <!-- resources/views/home.blade.php -—>

    @extends('layouts.app') @section(‘content’) Test @stop
  100. LEVERAGING LARAVEL @STAUFFERMATT BUILD VIEWS: CHILD EXTENSIONS <!-- resources/views/home.blade.php -—>

    @extends('layouts.app') @section('content') Test @stop @section('footerScripts') <script> $(function() { /* do stuff */ }); </script> @stop
  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’)
  102. LEVERAGING LARAVEL @STAUFFERMATT

  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
  104. LEVERAGING LARAVEL @STAUFFERMATT

  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
  106. LEVERAGING LARAVEL @STAUFFERMATT // Pseudo code foreach ($users as $user)

    { $user->notifyOfNewGistComments(); }
  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 ]); });
  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 } }
  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 ]); } } }
  110. LEVERAGING LARAVEL @STAUFFERMATT ... class NotifyUserOfNewGistComment extends Job { ...

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

  112. LEVERAGING LARAVEL @STAUFFERMATT LEVERAGING LARAVEL @STAUFFERMATT

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

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

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

  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']); } } }
  117. LEVERAGING LARAVEL @STAUFFERMATT public function handleComment($comment, $gist, $user) { if

    ($this->commentNeedsNotification($comment)) { $this->notifyComment($comment, $gist, $user); } }
  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 ]); }
  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’]); } }
  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!'); } ); }
  121. LEVERAGING LARAVEL @STAUFFERMATT private function markCommentAsNotified($comment) { $eloquentComment = NotifiedComment::firstOrNew([

    'github_id' => $comment['id'] ]); $eloquentComment->github_updated_at = $comment['updated_at']; $eloquentComment->save(); }
  122. LEVERAGING LARAVEL @STAUFFERMATT $ php artisan make:migration create_notified_comments_table

  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(); });
  124. LEVERAGING LARAVEL @STAUFFERMATT $ php artisan make:model NotifiedComment

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

  126. LEVERAGING LARAVEL @STAUFFERMATT <!-- resources/views/emails/new-comment.blade.php --> <p>You received a new

    comment on a Gist, <a href="{{ $gist['html_url'] }}">{{ $gist['description'] }}</a>.</p> <table><tr> <td><img src="{{ $comment['user']['avatar_url'] }}"></td> <td> <div> <a href="{{ $comment['user']['html_url'] }}"> {{ $comment['user']['login'] }} </a> commented <a href="{{ $gist['html_url'] }}#gistcomment-{{ $comment['id'] }}"> {{ $date->diffForHumans() }} </a> </div> {!! Markdown::parse($comment['body']) !!} </td> </tr></table>
  127. LEVERAGING LARAVEL @STAUFFERMATT // app/Console/Kernel.php $schedule->call(function () { User::all()->each(function ($user)

    { Queue::push(NotifyUserOfNewGistComments::class, [ 'user' => $user ]); }); })->hourly();
  128. LEVERAGING LARAVEL @STAUFFERMATT LEVERAGING LARAVEL @STAUFFERMATT

  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
  130. LEVERAGING LARAVEL @STAUFFERMATT TAKING PAYMENTS WITH CASHIER 1) CREATE PLAN

    IN YOUR STRIPE ACCOUNT
  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
  132. LEVERAGING LARAVEL @STAUFFERMATT TAKING PAYMENTS WITH CASHIER $ php artisan

    cashier:table users $ php artisan migrate 3) ADD CASHIER FIELDS TO USERS TABLE
  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
  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
  135. LEVERAGING LARAVEL @STAUFFERMATT

  136. LEVERAGING LARAVEL @STAUFFERMATT TAKING PAYMENTS WITH CASHIER <form action="" method="POST">

    <script 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"> </script> </form> 6) COPY STRIPE EMBEDDED HTML FROM DOCS INTO YOUR APP
  137. LEVERAGING LARAVEL @STAUFFERMATT

  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
  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; }
  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
  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('/'); });
  142. LEVERAGING LARAVEL @STAUFFERMATT TAKING PAYMENTS WITH CASHIER 10) SHOW INVOICES

    // In a view somewhere… @foreach (Auth::user()->invoices() as $invoice) <li>{{ $invoice->dateString() }} | {{ $invoice->dollars() }} | <a href="/user/invoice/{{ $invoice->id }}">Download</a></li> @endforeach // routes.php… Route::get('user/invoice/{invoice}', function ($invoiceId) { return Auth::user()->downloadInvoice($invoiceId, [ 'vendor' => 'Tighten Co.', 'product' => 'Giscus', ]); });
  143. LEVERAGING LARAVEL @STAUFFERMATT TAKING PAYMENTS WITH CASHIER Route::post( 'stripe/webhook', '\Laravel\Cashier\WebhookController@handleWebhook'

    ); 11) HANDLE WEB HOOKS
  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
  145. LEVERAGING LARAVEL @STAUFFERMATT LEVERAGING LARAVEL @STAUFFERMATT

  146. LEVERAGING LARAVEL @STAUFFERMATT (INTERLUDE: TESTS)

  147. LEVERAGING LARAVEL @STAUFFERMATT LEVERAGING LARAVEL @STAUFFERMATT

  148. LEVERAGING LARAVEL @STAUFFERMATT LEVERAGING LARAVEL @STAUFFERMATT

  149. LEVERAGING LARAVEL @STAUFFERMATT LEVERAGING LARAVEL @STAUFFERMATT

  150. LEVERAGING LARAVEL @STAUFFERMATT LEVERAGING LARAVEL @STAUFFERMATT

  151. LEVERAGING LARAVEL @STAUFFERMATT LEVERAGING LARAVEL @STAUFFERMATT

  152. LEVERAGING LARAVEL @STAUFFERMATT LEVERAGING LARAVEL @STAUFFERMATT

  153. LEVERAGING LARAVEL @STAUFFERMATT LEVERAGING LARAVEL @STAUFFERMATT

  154. LEVERAGING LARAVEL @STAUFFERMATT LEVERAGING LARAVEL @STAUFFERMATT

  155. LEVERAGING LARAVEL @STAUFFERMATT LEVERAGING LARAVEL @STAUFFERMATT

  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
  157. LEVERAGING LARAVEL @STAUFFERMATT LEVERAGING LARAVEL @STAUFFERMATT

  158. LEVERAGING LARAVEL @STAUFFERMATT LEVERAGING LARAVEL @STAUFFERMATT

  159. LEVERAGING LARAVEL @STAUFFERMATT

  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
  161. LEVERAGING LARAVEL @STAUFFERMATT go forth and create great apps