Going Bare - Writing the web without a framework - Cascadia PHP 2018

Going Bare - Writing the web without a framework - Cascadia PHP 2018

Talk given at Cascadia PHP 2018

If you've only ever experienced web development through a web framework, you're missing out. Have you ever been tempted to rewrite a codebase in your favorite framework? That's a smell that you need to come to this talk.

Being comfortable developing without a framework is a crucial skill to have for refactoring legacy applications. In this talk I show you how to harness the power of going "frameworkless" so you'll feel empowered to make better decisions in your next web project. Be set free from your web-framework ball and chain.


Sammy Kaye Powers

September 15, 2018


  1. Going Bare Writing the web without a framework Sammy Kaye

    Powers 2018-09-15
  2. joind.in/talk/2e67a @SammyK #cascadiaphp18 Slides Get the joind.in/talk/2e67a

  3. joind.in/talk/2e67a @SammyK #cascadiaphp18 frameworks The point is not <3 frameworks!

  4. joind.in/talk/2e67a @SammyK #cascadiaphp18 opinion It’s OK to have an

  5. joind.in/talk/2e67a @SammyK #cascadiaphp18 experiment It’s OK to

  6. joind.in/talk/2e67a @SammyK #cascadiaphp18 Bootstrapping / ˈbo ͞ otˌstraˌpiNG / Define:

    (…at least for this talk) Code that acts as an entry point into an app.
  7. joind.in/talk/2e67a @SammyK #cascadiaphp18 Boilerplate / ˈboilərˌplāt / Define: The “glue”

    code that ties components together. (…at least for this talk)
  8. joind.in/talk/2e67a @SammyK #cascadiaphp18 Frameworks are a tool

  9. joind.in/talk/2e67a @SammyK #cascadiaphp18 Going bare is a skill (that you

    don’t get with a framework)
  10. joind.in/talk/2e67a @SammyK #cascadiaphp18 The of going bare skill • Writing

    bootstrap & boilerplate • Choosing exact components • Use different paradigms • Use those skills on domain code (Get to know the component ecosystem) (Like singleton, et al) (Gives you more control over how components interact) (Makes you better at writing your domain code)
  11. joind.in/talk/2e67a @SammyK #cascadiaphp18 Myths about going frameworkless

  12. joind.in/talk/2e67a @SammyK #cascadiaphp18 Myth #1 You must write everything from

  13. joind.in/talk/2e67a @SammyK #cascadiaphp18 Myth #2 You’re inherently anti-framework or anti-convention

  14. joind.in/talk/2e67a @SammyK #cascadiaphp18 Myth #3 You’ll spend most of your

    time on boilerplate instead of on domain code
  15. joind.in/talk/2e67a @SammyK #cascadiaphp18 Myth #4 You must be an architecture

  16. joind.in/talk/2e67a @SammyK #cascadiaphp18 Myth #5 You like pain

  17. joind.in/talk/2e67a @SammyK #cascadiaphp18 Pros Framework Cons

  18. joind.in/talk/2e67a @SammyK #cascadiaphp18 Pros

  19. joind.in/talk/2e67a @SammyK #cascadiaphp18 Pros

  20. joind.in/talk/2e67a @SammyK #cascadiaphp18 Pros crazy fast You get started

  21. joind.in/talk/2e67a @SammyK #cascadiaphp18 Pros First-time install time minutes! 5

  22. joind.in/talk/2e67a @SammyK #cascadiaphp18 Pros

  23. joind.in/talk/2e67a @SammyK #cascadiaphp18 Pros boilerplate all the things You don’t

    have to Con but it can be a
  24. joind.in/talk/2e67a @SammyK #cascadiaphp18 Pros bootstrap & boilerplate code You don’t

    have to maintain
  25. joind.in/talk/2e67a @SammyK #cascadiaphp18 Pros battle-tested The code is

  26. joind.in/talk/2e67a @SammyK #cascadiaphp18 Pros conventions Ready-to-follow Con but it can

    be a
  27. joind.in/talk/2e67a @SammyK #cascadiaphp18 Pros documentation Most frameworks have great

  28. joind.in/talk/2e67a @SammyK #cascadiaphp18 Pros marketable It makes you more

  29. joind.in/talk/2e67a @SammyK #cascadiaphp18 Pros pragmatic They are often

  30. joind.in/talk/2e67a @SammyK #cascadiaphp18 cons? What about the

  31. joind.in/talk/2e67a @SammyK #cascadiaphp18 Cons legacy codebases Useless for

  32. joind.in/talk/2e67a @SammyK #cascadiaphp18 Cons cruft They fill your project with

  33. joind.in/talk/2e67a @SammyK #cascadiaphp18 Cons Cruft • Deployment takes longer •

    Upgrading pulls in all the new features
  34. joind.in/talk/2e67a @SammyK #cascadiaphp18 Cons tightly couple Easier to due to

  35. joind.in/talk/2e67a @SammyK #cascadiaphp18

  36. 5.3

  37. 5.7 2018-09-04

  38. None
  39. 5.7 Did not support laravelcollective/html mccool/laravel-auto-presenter

  40. None
  41. None
  42. joind.in/talk/2e67a @SammyK #cascadiaphp18 Cons upgrading Framework-specific deps can keep you

  43. joind.in/talk/2e67a @SammyK #cascadiaphp18 The The Cons Pros seem great are

  44. joind.in/talk/2e67a @SammyK #cascadiaphp18 Why would you go bare? (To answer

    we must ask…)
  45. joind.in/talk/2e67a @SammyK #cascadiaphp18 When should you go bare?

  46. joind.in/talk/2e67a @SammyK #cascadiaphp18

  47. joind.in/talk/2e67a @SammyK #cascadiaphp18 Greenfield Legacy Depends

  48. joind.in/talk/2e67a @SammyK #cascadiaphp18 1% 99% 90% 10% Go Bare Framwork

    Greenfield Legacy Going bare vs framework
  49. joind.in/talk/2e67a @SammyK #cascadiaphp18 How do you go bare?

  50. joind.in/talk/2e67a @SammyK #cascadiaphp18 from scratch You could just write

  51. joind.in/talk/2e67a @SammyK #cascadiaphp18

  52. joind.in/talk/2e67a @SammyK #cascadiaphp18 That means writing all the things Router

    DBAL/ORM Dep Injection Logger
  53. joind.in/talk/2e67a @SammyK #cascadiaphp18 reinventing the wheel But that’s like

  54. joind.in/talk/2e67a @SammyK #cascadiaphp18 Better Way™ There’s a

  55. joind.in/talk/2e67a @SammyK #cascadiaphp18 po- nents Com-

  56. joind.in/talk/2e67a @SammyK #cascadiaphp18 components has a healthy ecosystem of

  57. joind.in/talk/2e67a @SammyK #cascadiaphp18 using them You’re probably already

  58. joind.in/talk/2e67a @SammyK #cascadiaphp18 built on them Most frameworks are zend-router

    zend-db zend-di zend-log
  59. joind.in/talk/2e67a @SammyK #cascadiaphp18 choose ur candy Going bare lets you

    Look at all those smarties! Yum!
  60. joind.in/talk/2e67a @SammyK #cascadiaphp18 I like smarties

  61. joind.in/talk/2e67a @SammyK #cascadiaphp18 Router DBAL/ORM Dep Injection Logger

  62. joind.in/talk/2e67a @SammyK #cascadiaphp18 zend-router fast-route php-router phroute Routers Tons of

  63. joind.in/talk/2e67a @SammyK #cascadiaphp18 Easily installed with

  64. joind.in/talk/2e67a @SammyK #cascadiaphp18 bag o’ candy A framework is like

    a Comes with licorice? Yuck!
  65. joind.in/talk/2e67a @SammyK #cascadiaphp18 I don’t like licorice

  66. joind.in/talk/2e67a @SammyK #cascadiaphp18 components When you go bare don’t just

    magically start working together
  67. joind.in/talk/2e67a @SammyK #cascadiaphp18 Key: Get comfy with bootstrapping & boilerplate

    code It’s really not that bad
  68. joind.in/talk/2e67a @SammyK #cascadiaphp18 examples Real-world

  69. joind.in/talk/2e67a @SammyK #cascadiaphp18 conventions When going bare, there aren’t any

    …so this is a way, not the way
  70. joind.in/talk/2e67a @SammyK #cascadiaphp18 Greenfield Let’s start with

  71. joind.in/talk/2e67a @SammyK #cascadiaphp18 Case study Raw CSV Calculate
 & save

    to DB Show report Client’s server Our server
  72. joind.in/talk/2e67a @SammyK #cascadiaphp18 Case study Download CSV & calculate CLI

    View the report HTTP Endpoint
  73. joind.in/talk/2e67a @SammyK #cascadiaphp18 coding domain in 5 mins Install framework

  74. joind.in/talk/2e67a @SammyK #cascadiaphp18 61components installed before we code https://framework.zend.com/downloads

  75. joind.in/talk/2e67a @SammyK #cascadiaphp18 go micro We could… Slim Silex (et

  76. joind.in/talk/2e67a @SammyK #cascadiaphp18 Silex DEAD!

  77. joind.in/talk/2e67a @SammyK #cascadiaphp18 go bare! :) But let’s

  78. joind.in/talk/2e67a @SammyK #cascadiaphp18 Start in the CLI (Just like when

    you use a framework!)
  79. joind.in/talk/2e67a @SammyK #cascadiaphp18 1. Make an empty composer.json or… $

    composer init
  80. joind.in/talk/2e67a @SammyK #cascadiaphp18 2. Make a folder for domain code

    $ mkdir src
  81. joind.in/talk/2e67a @SammyK #cascadiaphp18 3. Add autoloading $ composer \ dumpautoload

    And then run…
  82. joind.in/talk/2e67a @SammyK #cascadiaphp18 Now just install your components & tie

    them together
  83. joind.in/talk/2e67a @SammyK #cascadiaphp18 Key: Get comfy with bootstrapping & boilerplate

    code It’s really not that bad
  84. joind.in/talk/2e67a @SammyK #cascadiaphp18 Case study Download CSV & calculate CLI

    View the report HTTP Endpoint
  85. joind.in/talk/2e67a @SammyK #cascadiaphp18 Install a console component $ composer require

    symfony/console (or maybe you like zendframework/zend-console)
  86. joind.in/talk/2e67a @SammyK #cascadiaphp18 src/Console/Runner.php

  87. joind.in/talk/2e67a @SammyK #cascadiaphp18 We get to make our first bootstrap

  88. joind.in/talk/2e67a @SammyK #cascadiaphp18 run (sans .php extension) $ chmod +x

  89. joind.in/talk/2e67a @SammyK #cascadiaphp18 $ ./run

  90. joind.in/talk/2e67a @SammyK #cascadiaphp18 B.A.U. Now it’s just src/Console/Runner.php

  91. joind.in/talk/2e67a @SammyK #cascadiaphp18 src/Console/CalculateReportsCommand.php

  92. joind.in/talk/2e67a @SammyK #cascadiaphp18 $ ./run

  93. joind.in/talk/2e67a @SammyK #cascadiaphp18

  94. joind.in/talk/2e67a @SammyK #cascadiaphp18 Congrats!

  95. joind.in/talk/2e67a @SammyK #cascadiaphp18 Install the DI container $ composer require

    pimple/pimple (Choose your poison)
  96. joind.in/talk/2e67a @SammyK #cascadiaphp18 Need to make singleton ready src/Application.php

  97. joind.in/talk/2e67a @SammyK #cascadiaphp18 Singleton Isn’t that an anti-pattern?

  98. joind.in/talk/2e67a @SammyK #cascadiaphp18 https://en.wikipedia.org/wiki/Singleton_pattern

  99. joind.in/talk/2e67a @SammyK #cascadiaphp18

  100. joind.in/talk/2e67a @SammyK #cascadiaphp18 Singleton •Ensures one & only one instance

    •Global access (static function) •Initialization on first access
  101. joind.in/talk/2e67a @SammyK #cascadiaphp18 Fatal error: Call to private App\Application::__construct() src/Application.php

  102. joind.in/talk/2e67a @SammyK #cascadiaphp18 src/Application.php Global access + instantiate on first

  103. joind.in/talk/2e67a @SammyK #cascadiaphp18 Get an instance of Application

  104. joind.in/talk/2e67a @SammyK #cascadiaphp18 Prevent cloning src/Application.php

  105. joind.in/talk/2e67a @SammyK #cascadiaphp18 src/Application.php Prevent unserialization

  106. joind.in/talk/2e67a @SammyK #cascadiaphp18 •Ensures one & only one instance •Global

    access (static function) •Initialization on first access
  107. joind.in/talk/2e67a @SammyK #cascadiaphp18 Case study Download CSV & calculate CLI

    View the report HTTP Endpoint
  108. joind.in/talk/2e67a @SammyK #cascadiaphp18 We get to make our final bootstrap

  109. joind.in/talk/2e67a @SammyK #cascadiaphp18 public/index.php

  110. joind.in/talk/2e67a @SammyK #cascadiaphp18 Eh?

  111. joind.in/talk/2e67a @SammyK #cascadiaphp18 src/Application.php However you register service providers into

    the container (different DI containers have their own API)
  112. joind.in/talk/2e67a @SammyK #cascadiaphp18 Why not in constructor?

  113. joind.in/talk/2e67a @SammyK #cascadiaphp18 src/Application.php

  114. joind.in/talk/2e67a @SammyK #cascadiaphp18 Install a router $ composer require nikic/fast-route

    (Choose your poison)
  115. joind.in/talk/2e67a @SammyK #cascadiaphp18 service provider Make a routing Pimple syntax

    - mileage my vary
  116. joind.in/talk/2e67a @SammyK #cascadiaphp18 Register in container src/Application.php

  117. joind.in/talk/2e67a @SammyK #cascadiaphp18 src/Router.php

  118. joind.in/talk/2e67a @SammyK #cascadiaphp18 Ugly A.F. src/routes.php

  119. joind.in/talk/2e67a @SammyK #cascadiaphp18 Different project, same component src/routes.php

  120. joind.in/talk/2e67a @SammyK #cascadiaphp18 public/index.php run We got bootstrap Runs CLI

    Runs HTTP
  121. joind.in/talk/2e67a @SammyK #cascadiaphp18 We got boilerplate src/Router.php src/Console/Runner.php symfony/console nikic/fast-route

  122. joind.in/talk/2e67a @SammyK #cascadiaphp18 Still not convinced?

  123. joind.in/talk/2e67a @SammyK #cascadiaphp18 What about Legacy

  124. joind.in/talk/2e67a @SammyK #cascadiaphp18 Why would you go bare? It’s a

    skill you can use for legacy apps
  125. joind.in/talk/2e67a @SammyK #cascadiaphp18 I’ll just rewrite this in x framework…

  126. joind.in/talk/2e67a @SammyK #cascadiaphp18 Totes samezies except routing

  127. joind.in/talk/2e67a @SammyK #cascadiaphp18 Route exists? Not found Router Yes No

    Code 404
  128. joind.in/talk/2e67a @SammyK #cascadiaphp18 Route exists? Legacy router New router Yes

    No New code
  129. joind.in/talk/2e67a @SammyK #cascadiaphp18 app/webroot/index.php Old CakePHP bootstrap file

  130. joind.in/talk/2e67a @SammyK #cascadiaphp18 src/bootstrap.php Same as public/index.php for HTTP

  131. joind.in/talk/2e67a @SammyK #cascadiaphp18 src/Router.php

  132. joind.in/talk/2e67a @SammyK #cascadiaphp18 tests? What about

  133. joind.in/talk/2e67a @SammyK #cascadiaphp18 Install PHPUnit $ composer require phpunit/phpunit --dev

  134. joind.in/talk/2e67a @SammyK #cascadiaphp18 phpunit.xml

  135. joind.in/talk/2e67a @SammyK #cascadiaphp18 tests/bootstrap.php

  136. joind.in/talk/2e67a @SammyK #cascadiaphp18 src/Application.php

  137. joind.in/talk/2e67a @SammyK #cascadiaphp18 Run the test suite $ ./vendor/bin/phpunit

  138. joind.in/talk/2e67a @SammyK #cascadiaphp18 How to choose your components

  139. joind.in/talk/2e67a @SammyK #cascadiaphp18 Use more than one framework #1

  140. joind.in/talk/2e67a @SammyK #cascadiaphp18 Search packagist.org #2 (Make sure it has

    good docs & is actively maintained)
  141. joind.in/talk/2e67a @SammyK #cascadiaphp18 experiments Try some

  142. joind.in/talk/2e67a @SammyK #cascadiaphp18 100% middleware My next experiment: (I could

    totes use Zend Expressive or just go bare)
  143. joind.in/talk/2e67a @SammyK #cascadiaphp18 pros? framework ‘member the

  144. joind.in/talk/2e67a @SammyK #cascadiaphp18 Framework pros Crazy fast to get started

    …but you’ll get faster at going bare
  145. joind.in/talk/2e67a @SammyK #cascadiaphp18 Framework pros to maintain …most the time

    it’s really not that bad No bootstrap & boilerplate code
  146. joind.in/talk/2e67a @SammyK #cascadiaphp18 Framework pros The code is …so are

    the components you use when going bare battle tested
  147. joind.in/talk/2e67a @SammyK #cascadiaphp18 Framework pros Great …so are the components

    you use when going bare documentation
  148. joind.in/talk/2e67a @SammyK #cascadiaphp18 Framework pros Makes you more …going bare

    is a marketable skill marketable
  149. joind.in/talk/2e67a @SammyK #cascadiaphp18 Framework pros They are often …in many

    contexts going bare is more pragmatic pragmatic
  150. joind.in/talk/2e67a @SammyK #cascadiaphp18 myths? Did we bust the

  151. joind.in/talk/2e67a @SammyK #cascadiaphp18 #1 You must write everything from scratch

    Nope, use components
  152. joind.in/talk/2e67a @SammyK #cascadiaphp18 #2 You’re inherently anti- framework or anti-convention

    Nope, frameworks are great for most greenfield projects
  153. joind.in/talk/2e67a @SammyK #cascadiaphp18 #3 You’ll spend most of your time

    on bootstrapping instead of on domain code It takes a little longer at first but you’ll get faster with practice
  154. joind.in/talk/2e67a @SammyK #cascadiaphp18 #4 You must be an architecture astronaut

    Going bare is more pragmatic for legacy codebases
  155. joind.in/talk/2e67a @SammyK #cascadiaphp18 #5 You like pain No, we just

    like to improve our skills
  156. joind.in/talk/2e67a @SammyK #cascadiaphp18

  157. joind.in/talk/2e67a @SammyK #cascadiaphp18 Remember: It’s all about tradeoffs.

  158. joind.in/talk/2e67a @SammyK #cascadiaphp18 Resources

  159. joind.in/talk/2e67a @SammyK #cascadiaphp18 Create a PHP application without a framework

    Patrick Louys https://github.com/PatrickLouys/no- framework-tutorial
  160. joind.in/talk/2e67a @SammyK #cascadiaphp18 Refactoring Martin Fowler

  161. joind.in/talk/2e67a @SammyK #cascadiaphp18 <3 frameworks I I also <3 my

    skill for Going Bare
  162. Sammy Kaye Powers Thanks! /talk/2e67a @SammyK SammyK.me Host of @PHPRoundtable