Diese Präsentation wurde erfolgreich gemeldet.
Wir verwenden Ihre LinkedIn Profilangaben und Informationen zu Ihren Aktivitäten, um Anzeigen zu personalisieren und Ihnen relevantere Inhalte anzuzeigen. Sie können Ihre Anzeigeneinstellungen jederzeit ändern.
Symfony:
Your Next Microframework
by your friend:
Ryan Weaver
@weaverryan
by your friend:
Ryan Weaver
@weaverryan
KnpUniversity.com

github.com/weaverryan
Who is this guy?
> Lead for the Symfony documentation

> KnpLabs US - Symfony Con...
Thinking about 2
Problems
@weaverryan
Problem 1:

Symfony Sucks
@weaverryan
@weaverryan
@weaverryan
@weaverryan
@weaverryan
Symfony

is too hard
@weaverryan
The Symfony Framework

is too hard
@weaverryan
The components are not usually the
problem
Why?
@weaverryan
Route

Controller

Response
@weaverryan
WTF?
Useful Objects
1) Common tasks require

too much code
@weaverryan
2) Symfony is too big
@weaverryan
Too many files

==

A Perceived Complexity
@weaverryan
@weaverryan
~ 25 files
~ 10 directories
for Hello World
Problem 2:

Is my project 

macro or micro?
@weaverryan
Macro => Use Symfony
@weaverryan
Micro => Use Silex
@weaverryan
The fact we have this
option is incredible

but…
@weaverryan
Silex has a slightly
different tech stack
@weaverryan
Silex doesn’t have bundles
@weaverryan
Silex can’t evolve to a full
stack Symfony App
@weaverryan
What if we just made
Symfony smaller?
@weaverryan
6 files
62 lines of code
<?php



use SymfonyComponentHttpKernelKernel;

use SymfonyComponentConfigLoaderLoaderInterface;



class AppKernel extend...
How small can we go?
@weaverryan
What is a Symfony
Application?
@weaverryan
What is a Symfony App?
@weaverryan
1.A set of bundles
2.A container of services
3.Routes
Let’s create a new

Symfony project

from nothing
@weaverryan
{

"require": {

"symfony/symfony": "^2.8"

}

}
@weaverryan
composer.json
<?php



use SymfonyComponentConfigLoaderLoaderInterface;

use SymfonyComponentHttpKernelKernel;



require __DIR__.'/vend...
<?php



use SymfonyBundleFrameworkBundleKernelMicroKernelTrait;

use SymfonyComponentDependencyInjectionContainerBuilder;...
public function registerBundles()

{

return array(

new SymfonyBundleFrameworkBundleFrameworkBundle()

);

}
AppKernel
protected function configureContainer(ContainerBuilder $c, $loader)

{

$c->loadFromExtension('framework', array(

'secret...
protected function configureRoutes(RouteCollectionBuilder $routes)

{

$routes->add('/random/{limit}', 'kernel:randomActio...
public function randomAction($limit)

{

return new JsonResponse(array(

'number' => rand(0, $limit)

));

}
AppKernel
<?php



// ...



require __DIR__.'/vendor/autoload.php';





class AppKernel extends Kernel

{

// ...

}



$kernel = ...
How many files?
@weaverryan
How many lines of code?
2 files
52 lines of code
This is a full stack
framework
@weaverryan
@weaverryan
1. Service Container
2. Routing
3. Events
4. ESI & Sub-Requests
5. Compatible with 3rd party bundles
Fast as Hell
@weaverryan
The goal is not to create
single-file apps
@weaverryan
Clarity & Control
@weaverryan
Building a
Realistic App
@weaverryan
github.com/weaverryan/docs-micro_kernel
Requirements:
@weaverryan
1. Add some organization
2. Load annotation routes
3. Web Debug Toolbar + Profiler
4. Twig
Reorganize
class AppKernel extends Kernel

{

}

// web/index.php

$kernel = new AppKernel('dev', true);

$request = Reque...
public function registerBundles()

{

$bundles = array(

new FrameworkBundle(),

new TwigBundle(),

new SensioFrameworkExt...
protected function configureContainer(ContainerBuilder $c, $loader)

{

$loader->load(__DIR__.'/config/config.yml');



if...
app/config/config.yml
framework:

secret: S0ME_SECRET

templating:

engines: ['twig']

profiler: { only_exceptions: false }
...
protected function configureContainer(ContainerBuilder $c, $loader)

{

$loader->load(__DIR__.'/config/config.yml');



if...
protected function configureRoutes(RouteCollectionBuilder $routes)

{

if (isset($this->bundles['WebProfilerBundle'])) {

...
Clarity & Control
@weaverryan
@weaverryan
protected function configureContainer(ContainerBuilder $c, $loader)

{

$loader->load(__DIR__ . '/config/confi...
@weaverryan
protected function configureContainer(ContainerBuilder $c, $loader)

{

$loader->load(__DIR__.'/config/config....
@weaverryan
Build Services
protected function configureContainer(ContainerBuilder $c, $loader)

{

// ...



$c->register(...
@weaverryan
Build Routes
protected function configureRoutes(RouteCollectionBuilder $routes)

{

// ...

$routes->add('/san...
@weaverryan
Bundless
Applications?
@weaverryan
Wait, what does a
bundle even give me?
A bundle gives you:
@weaverryan
1. Services
2. A resource root (e.g. path to load templates)
3. Magic functionality (e.g. ...
@weaverryan
1) Services
protected function configureContainer(ContainerBuilder $c, $loader)

{

// ...



$c->register('sa...
@weaverryan
2) Resource Root
2) Resource Root
protected function configureContainer(ContainerBuilder $c, $loader)

{

// ...



$c->loadFromExtension('...
@weaverryan
3) Magic Functionality
1. Register commands as services
2. Configure Doctrine mappings to load your
Entity dire...
@weaverryan
4) Shortcuts
santa:

controller: AppBundle:Santa:xmas

controller: AppBundleControllerSantaController::xmasAct...
@weaverryan
One New Trick
protected function configureRoutes(RouteCollectionBuilder $routes)

{

$routes->import(__DIR__.’...
Multiple Kernels?
@weaverryan
Multiple kernels, why?
@weaverryan
1. micro service architecture in monolithic
repository
2. performance (less routes, ser...
Multiple kernels was
always possible
@weaverryan
Now they’re obvious
@weaverryan
// app/ApiKernel.php
class ApiKernel extends Kernel

{

use MicroKernelTrait;



public function registerBundles()

{

$bu...
class ApiKernel extends Kernel

{

// ...



protected function configureContainer($c, $loader)

{

$loader->load(__DIR__....
class ApiKernel extends Kernel

{

// ...



protected function configureRoutes($routes)

{

$routes->import(

__DIR__.'/....
Boot the correct kernel
however you want
@weaverryan
// web/index.php
use SymfonyComponentHttpFoundationRequest;



require __DIR__.'/../app/autoload.php';



$request = Reque...
But how does it work?
@weaverryan
There is one person

who *hates* the name

MicroKernelTrait
@weaverryan
@weaverryan
@weaverryan
trait MicroKernelTrait

{

abstract protected function configureRoutes(RouteCollectionBuilder $routes);

abstract protecte...
So what now?
@weaverryan
I have a big project…
@weaverryan
Use it for clarity
I’m teaching
@weaverryan
Show it for simplicity
I have a small app
@weaverryan
Show it for power
@weaverryan
PHP & Symfony Video Tutorials
KnpUniversity.com
Thank You!
Symfony: Your Next Microframework (SymfonyCon 2015)
Symfony: Your Next Microframework (SymfonyCon 2015)
Symfony: Your Next Microframework (SymfonyCon 2015)
Symfony: Your Next Microframework (SymfonyCon 2015)
Nächste SlideShare
Wird geladen in …5
×

Symfony: Your Next Microframework (SymfonyCon 2015)

6.248 Aufrufe

Veröffentlicht am

Microservices are a huge trend, and microframeworks are perfect for them: put together just a few files, write some code, and your done!

But Symfony is a big framework, right? Wrong! Symfony can be as small as a single file!

In this talk, we'll learn how to use Symfony as a micro-framework for your next project. Your app will stay small and clear, but without needing to give up the features or third-party bundles that you love. And if the project grows, it can evolve naturally into a full Symfony project.

So yes, Symfony can also be a microframework. Tell the world!

Veröffentlicht in: Technologie
  • Slide 41+42: How do you managed to put full stack framework into 52 lines of code in 2 files? What about those thousands of lines in /vendor, which have to be processed as well on each request?
       Antworten 
    Sind Sie sicher, dass Sie …  Ja  Nein
    Ihre Nachricht erscheint hier
  • Silex can evolve to a full stack framework https://github.com/saxulum/saxulum
       Antworten 
    Sind Sie sicher, dass Sie …  Ja  Nein
    Ihre Nachricht erscheint hier

Symfony: Your Next Microframework (SymfonyCon 2015)

  1. 1. Symfony: Your Next Microframework by your friend: Ryan Weaver @weaverryan by your friend: Ryan Weaver @weaverryan
  2. 2. KnpUniversity.com github.com/weaverryan Who is this guy? > Lead for the Symfony documentation
 > KnpLabs US - Symfony Consulting, training & general Kumbaya > Writer for KnpUniversity.com Tutorials > Husband of the much more talented @leannapelham
  3. 3. Thinking about 2 Problems @weaverryan
  4. 4. Problem 1: Symfony Sucks @weaverryan
  5. 5. @weaverryan
  6. 6. @weaverryan
  7. 7. @weaverryan
  8. 8. @weaverryan
  9. 9. Symfony is too hard @weaverryan
  10. 10. The Symfony Framework is too hard @weaverryan The components are not usually the problem
  11. 11. Why? @weaverryan
  12. 12. Route Controller Response @weaverryan WTF? Useful Objects
  13. 13. 1) Common tasks require
 too much code @weaverryan
  14. 14. 2) Symfony is too big @weaverryan
  15. 15. Too many files == A Perceived Complexity @weaverryan
  16. 16. @weaverryan ~ 25 files ~ 10 directories for Hello World
  17. 17. Problem 2: Is my project macro or micro? @weaverryan
  18. 18. Macro => Use Symfony @weaverryan
  19. 19. Micro => Use Silex @weaverryan
  20. 20. The fact we have this option is incredible but… @weaverryan
  21. 21. Silex has a slightly different tech stack @weaverryan
  22. 22. Silex doesn’t have bundles @weaverryan
  23. 23. Silex can’t evolve to a full stack Symfony App @weaverryan
  24. 24. What if we just made Symfony smaller? @weaverryan
  25. 25. 6 files 62 lines of code
  26. 26. <?php
 
 use SymfonyComponentHttpKernelKernel;
 use SymfonyComponentConfigLoaderLoaderInterface;
 
 class AppKernel extends Kernel
 {
 public function registerBundles()
 {
 return array(
 new SymfonyBundleFrameworkBundleFrameworkBundle(),
 new SymfonyBundleTwigBundleTwigBundle(),
 );
 }
 
 public function registerContainerConfiguration($loader)
 {
 $loader->load(
 __DIR__.'/config/config_'.$this->getEnvironment().'.yml'
 );
 }
 }
  27. 27. How small can we go? @weaverryan
  28. 28. What is a Symfony Application? @weaverryan
  29. 29. What is a Symfony App? @weaverryan 1.A set of bundles 2.A container of services 3.Routes
  30. 30. Let’s create a new Symfony project from nothing @weaverryan
  31. 31. {
 "require": {
 "symfony/symfony": "^2.8"
 }
 } @weaverryan composer.json
  32. 32. <?php
 
 use SymfonyComponentConfigLoaderLoaderInterface;
 use SymfonyComponentHttpKernelKernel;
 
 require __DIR__.'/vendor/autoload.php';
 
 class AppKernel extends Kernel
 {
 public function registerBundles()
 {
 }
 
 public function registerContainerConfiguration($loader)
 {
 }
 }
 index.php
  33. 33. <?php
 
 use SymfonyBundleFrameworkBundleKernelMicroKernelTrait;
 use SymfonyComponentDependencyInjectionContainerBuilder;
 use SymfonyComponentRoutingRouteCollectionBuilder; // ...
 
 class AppKernel extends Kernel
 {
 use MicroKernelTrait;
 
 public function registerBundles()
 {
 }
 
 protected function configureRoutes(RouteCollectionBuilder $routes)
 {
 }
 
 protected function configureContainer(ContainerBuilder $c, $loader)
 {
 }
 }
 index.php 1) A set of bundles 2) Routes 3) A container of services
  34. 34. public function registerBundles()
 {
 return array(
 new SymfonyBundleFrameworkBundleFrameworkBundle()
 );
 } AppKernel
  35. 35. protected function configureContainer(ContainerBuilder $c, $loader)
 {
 $c->loadFromExtension('framework', array(
 'secret' => 'S0ME_SECRET',
 ));
 } AppKernel // config.yml framework:
 secret: S0ME_SECRET
  36. 36. protected function configureRoutes(RouteCollectionBuilder $routes)
 {
 $routes->add('/random/{limit}', 'kernel:randomAction');
 } AppKernel New in 2.8! service:methodName (Symfony’s controller as a service syntax)
  37. 37. public function randomAction($limit)
 {
 return new JsonResponse(array(
 'number' => rand(0, $limit)
 ));
 } AppKernel
  38. 38. <?php
 
 // ...
 
 require __DIR__.'/vendor/autoload.php';
 
 
 class AppKernel extends Kernel
 {
 // ...
 }
 
 $kernel = new AppKernel('dev', true);
 $request = Request::createFromGlobals();
 $response = $kernel->handle($request);
 $response->send();
 $kernel->terminate($request, $response);
 index.php
  39. 39. How many files? @weaverryan How many lines of code?
  40. 40. 2 files 52 lines of code
  41. 41. This is a full stack framework @weaverryan
  42. 42. @weaverryan 1. Service Container 2. Routing 3. Events 4. ESI & Sub-Requests 5. Compatible with 3rd party bundles
  43. 43. Fast as Hell @weaverryan
  44. 44. The goal is not to create single-file apps @weaverryan
  45. 45. Clarity & Control @weaverryan
  46. 46. Building a Realistic App @weaverryan github.com/weaverryan/docs-micro_kernel
  47. 47. Requirements: @weaverryan 1. Add some organization 2. Load annotation routes 3. Web Debug Toolbar + Profiler 4. Twig
  48. 48. Reorganize class AppKernel extends Kernel
 {
 }
 // web/index.php
 $kernel = new AppKernel('dev', true);
 $request = Request::createFromGlobals();
 $response = $kernel->handle($request);
 $response->send();
  49. 49. public function registerBundles()
 {
 $bundles = array(
 new FrameworkBundle(),
 new TwigBundle(),
 new SensioFrameworkExtraBundle()
 );
 
 if ($this->getEnvironment() == 'dev') {
 $bundles[] = new WebProfilerBundle();
 }
 
 return $bundles;
 } app/AppKernel.php
  50. 50. protected function configureContainer(ContainerBuilder $c, $loader)
 {
 $loader->load(__DIR__.'/config/config.yml');
 
 if (isset($this->bundles['WebProfilerBundle'])) {
 $c->loadFromExtension('web_profiler', array(
 'toolbar' => true,
 'intercept_redirects' => false,
 ));
 }
 } app/AppKernel.php @weaverryan
  51. 51. app/config/config.yml framework:
 secret: S0ME_SECRET
 templating:
 engines: ['twig']
 profiler: { only_exceptions: false } @weaverryan
  52. 52. protected function configureContainer(ContainerBuilder $c, $loader)
 {
 $loader->load(__DIR__.'/config/config.yml');
 
 if (isset($this->bundles['WebProfilerBundle'])) {
 $c->loadFromExtension('web_profiler', array(
 'toolbar' => true,
 'intercept_redirects' => false,
 ));
 }
 } app/AppKernel.php @weaverryan Goodbye config_dev.yml
  53. 53. protected function configureRoutes(RouteCollectionBuilder $routes)
 {
 if (isset($this->bundles['WebProfilerBundle'])) {
 $routes->import(
 '@WebProfilerBundle/Resources/config/routing/wdt.xml',
 '_wdt'
 );
 $routes->import(
 '@WebProfilerBundle/Resources/config/routing/profiler.xml',
 '/_profiler'
 );
 }
 
 $routes->import(__DIR__.'/../src/App/Controller/', '/', 'annotation')
 } app/AppKernel.php Goodbye routing_dev.yml
  54. 54. Clarity & Control @weaverryan
  55. 55. @weaverryan protected function configureContainer(ContainerBuilder $c, $loader)
 {
 $loader->load(__DIR__ . '/config/config.yml');
 
 $c->setParameter('secret', getenv('SECRET'));
 $c->loadFromExtension('doctrine', [
 'dbal' => [
 'driver' => 'pdo_mysql',
 'host' => getenv('DATABASE_HOST'),
 'user' => getenv('DATABASE_USER'),
 'password' => getenv('DATABASE_PASS'),
 ]
 ]);
 // ...
 } Environment Variables
  56. 56. @weaverryan protected function configureContainer(ContainerBuilder $c, $loader)
 {
 $loader->load(__DIR__.'/config/config.yml');
 
 if (in_array($this->getEnvironment(), ['dev', 'test'])) {
 
 $c->loadFromExtension('framework', [
 'profiler' => ['only_exceptions' => false]
 ]);
 
 }
 
 // ...
 } Environment Control
  57. 57. @weaverryan Build Services protected function configureContainer(ContainerBuilder $c, $loader)
 {
 // ...
 
 $c->register('santa.controller', SantaController::class)
 ->setAutowired(true);
 
 }
  58. 58. @weaverryan Build Routes protected function configureRoutes(RouteCollectionBuilder $routes)
 {
 // ...
 $routes->add('/santa', 'AppBundle:Santa:northPole');
 
 $routes->add(‘/naughty-list/{page}’, 'AppBundle:Santa:list')
 ->setRequirement('list', 'd+')
 ->setDefault('page', 1);
 }
  59. 59. @weaverryan Bundless Applications?
  60. 60. @weaverryan Wait, what does a bundle even give me?
  61. 61. A bundle gives you: @weaverryan 1. Services 2. A resource root (e.g. path to load templates) 3. Magic functionality (e.g. commands) 4. Shortcuts (_controller, AppBundle:User)
  62. 62. @weaverryan 1) Services protected function configureContainer(ContainerBuilder $c, $loader)
 {
 // ...
 
 $c->register('santa.controller', SantaController::class)
 ->setAutowired(true);
 
 }
  63. 63. @weaverryan 2) Resource Root
  64. 64. 2) Resource Root protected function configureContainer(ContainerBuilder $c, $loader)
 {
 // ...
 
 $c->loadFromExtension('twig', [
 'paths' => [__DIR__.'/Resources/views' => 'north_pole']
 ]);
 } public function randomAction($limit)
 {
 $number = rand(0, $limit);
 
 return $this->render(‘@north_pole/micro/random.html.twig’, [
 'number' => $number
 ]);
 }
  65. 65. @weaverryan 3) Magic Functionality 1. Register commands as services 2. Configure Doctrine mappings to load your Entity directory
  66. 66. @weaverryan 4) Shortcuts santa:
 controller: AppBundle:Santa:xmas
 controller: AppBundleControllerSantaController::xmasAction $em->getRepository('AppBundle:App');
 $em->getRepository('AppBundleEntityApp');
  67. 67. @weaverryan One New Trick protected function configureRoutes(RouteCollectionBuilder $routes)
 {
 $routes->import(__DIR__.’@AppBundle/Controller/‘, '/', 'annotation')
 } protected function configureRoutes(RouteCollectionBuilder $routes)
 {
 $routes->import(__DIR__.'/../src/App/Controller/', '/', 'annotation')
 }
  68. 68. Multiple Kernels? @weaverryan
  69. 69. Multiple kernels, why? @weaverryan 1. micro service architecture in monolithic repository 2. performance (less routes, services & listeners)
  70. 70. Multiple kernels was always possible @weaverryan
  71. 71. Now they’re obvious @weaverryan
  72. 72. // app/ApiKernel.php class ApiKernel extends Kernel
 {
 use MicroKernelTrait;
 
 public function registerBundles()
 {
 $bundles = array(
 new FrameworkBundle(),
 new SensioFrameworkExtraBundle()
 );
 
 return $bundles;
 }
 } No TwigBundle
  73. 73. class ApiKernel extends Kernel
 {
 // ...
 
 protected function configureContainer($c, $loader)
 {
 $loader->load(__DIR__.'/config/config.yml');
 $loader->load(__DIR__.'/config/api.yml');
 }
 } Use PHP logic to load share config, and custom config
  74. 74. class ApiKernel extends Kernel
 {
 // ...
 
 protected function configureRoutes($routes)
 {
 $routes->import(
 __DIR__.'/../src/Api/Controller/',
 '/api',
 'annotation'
 );
 }
 
 public function getCacheDir()
 {
 return __DIR__.’/../var/cache/api/' .$this->getEnvironment();
 }
 } Load different routes cacheDir ~= the cache key
  75. 75. Boot the correct kernel however you want @weaverryan
  76. 76. // web/index.php use SymfonyComponentHttpFoundationRequest;
 
 require __DIR__.'/../app/autoload.php';
 
 $request = Request::createFromGlobals();
 
 if (strpos($request->getPathInfo(), '/api') === 0) {
 require __DIR__.'/../app/ApiKernel.php';
 $kernel = new ApiKernel('dev', true);
 } else {
 require __DIR__.'/../app/WebKernel.php';
 $kernel = new WebKernel('dev', true);
 }
 
 $response = $kernel->handle($request);
 $response->send();

  77. 77. But how does it work? @weaverryan
  78. 78. There is one person who *hates* the name MicroKernelTrait @weaverryan
  79. 79. @weaverryan
  80. 80. @weaverryan
  81. 81. trait MicroKernelTrait
 {
 abstract protected function configureRoutes(RouteCollectionBuilder $routes);
 abstract protected function configureContainer(ContainerBuilder $c, $loader);
 
 public function registerContainerConfiguration($loader)
 {
 $loader->load(function ($container) use ($loader) {
 $container->loadFromExtension('framework', array(
 'router' => array(
 'resource' => 'kernel:loadRoutes',
 'type' => 'service',
 ),
 ));
 
 $this->configureContainer($container, $loader);
 });
 }
 
 public function loadRoutes(LoaderInterface $loader)
 {
 $routes = new RouteCollectionBuilder($loader);
 $this->configureRoutes($routes);
 
 return $routes->build();
 }
 } Closure Loader New service route loader
  82. 82. So what now? @weaverryan
  83. 83. I have a big project… @weaverryan Use it for clarity
  84. 84. I’m teaching @weaverryan Show it for simplicity
  85. 85. I have a small app @weaverryan Show it for power
  86. 86. @weaverryan PHP & Symfony Video Tutorials KnpUniversity.com Thank You!

×