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

From Legacy to Symfony @ SymfonyCon Cluj 2017

From Legacy to Symfony @ SymfonyCon Cluj 2017

How can one use Symfony 4.0 and PHP 7.2 while working with a legacy application? Starting new projects on latest technology is a no-brainer but how often are you in this position? Most of the time it feels like you're stuck with what you have.

In this talk I'll share my experience migrating a legacy monolith from 2007 (powering a high traffic social network) and an API-centric web application (running an e-commerce marketplace) to Symfony.

Although the talk will be largely technical I'll also share some insights on ROI, non-technical benefits and pitching the idea to your boss.

Sebastian Grodzicki

November 16, 2017
Tweet

More Decks by Sebastian Grodzicki

Other Decks in Programming

Transcript

  1. How can one use Symfony 4.0 and PHP 7.2
 while

    working with a legacy application?
  2. phpinfo() Sebastian Grodzicki
 • CTO at SHOWROOM • former dev

    & CTO at GoldenLine • SensioLabs Certified
 Symfony Developer (Expert) • PHP developer for 15+ years !@sebgrodzicki
  3. GoldenLine • business social network founded in 2005 • in-house

    framework (“Xplod”) • LAMP stack • monolith
  4. Routing self::$map = [ [ 'uri' => '^/oauth/authorize/?(.+)?$', 'action' =>

    'oauth/authorize', ], [ 'uri' => '^/m$', 'action' => 'mobile/touch', ], // 746 more like this ];
  5. Routing public function convert(array $rule) { $route = new Route('/{uri}');

    $route->setRequirement('uri', $this->getRequirement($rule['uri'])); return $route; }
  6. Routing private function addRoute( RouteCollection $collection, array $rule, $controller =

    'legacy.web_dispatching_controller:dispatchAction' ) { $name = sprintf( '__legacy_route_%s_%s_%s', (isset($rule['requireSsl']) ? strtolower($rule['requireSsl']) : 1), (isset($rule['method']) ? strtolower($rule['method']) : ''), md5($rule['uri']) ); $route = $this->converter->convert($rule); $route->setDefault('_controller', $controller); $collection->add($name, $route); }
  7. @LegacyIfRoleNot class AutocompleterController extends Controller { const DEFAULT_LIMIT = 15;

    /** * @LegacyIfRoleNot("ROLE_SYMFONY") * * @param Request $request * @throws AccessDeniedException * @return array */ public function getAction(Request $request) { $this->denyAccessUnlessGranted('ROLE_USER'); $query = $request->query->get('query'); $limit = $request->query->get('limit') ?: self::DEFAULT_LIMIT;
  8. @LegacyIfOldBrowser class AuthenticatedController extends Controller { /** * @LegacyIfRoleNot({"IS_ANONYMOUS","ROLE_SYMFONY"}) *

    @LegacyIfOldBrowser */ public function indexAction(Request $request) { $this->denyAccessUnlessGranted('IS_AUTHENTICATED_ANONYMOUSLY'); /** @var $user User */ $user = $this->getUser(); if (!$user) { return $this->forward('HomepageBundle:Anonymous:index'); }
  9. SHOWROOM • online fashion marketplace founded in 2012 • built

    on Slim micro framework & Phalcon • API-centric
  10. • API v2 based on Symfony 3 • store front

    v2 (Symfony 3) • SHOWROOM SDK for PHP SHOWROOM @ 2016
  11. PSQL 5432 PHP 5.6 9056 NGINX
 80/443 Varnish 6081 NGINX

    8080 • SSL Termination • Access logs • Redirect HTTP to HTTPS • HTTP Cache • Load balancer • Edge Side Includes (ESI) • PHP-FPM via FastCGI • Virtual Hosts • Access logs • PHP-FPM • PHP 5.6 Elasticsearch
 9200 RabbitMQ
 5672 Redis 6379
  12. PSQL 5432 PHP 5.6 9056 NGINX
 80/443 Varnish 6081 NGINX

    8080 • SSL Termination • Access logs • Redirect HTTP to HTTPS • HTTP Cache • Load balancer • Edge Side Includes (ESI) • PHP-FPM via FastCGI • Virtual Hosts • Access logs • PHP-FPM • PHP 5.6 • PHP 7.1 Elasticsearch
 9200 RabbitMQ
 5672 Redis 6379 NGINX 8081 PHP 7.1 9071
  13. Varnish backend app1a { .host = "10.0.0.1"; .port = "8080";

    } backend app1b { .host = "10.0.0.2"; .port = "8080"; } backend app1c { .host = "10.0.0.3"; .port = "8080"; } backend app2a { .host = "10.0.0.1"; .port = "8081"; } backend app2b { .host = "10.0.0.2"; .port = "8081"; } backend app2c { .host = "10.0.0.3"; .port = “8081"; }
  14. Varnish sub vcl_init { new v1 = directors.round_robin(); v1.add_backend(app1a); v1.add_backend(app1b);

    v1.add_backend(app1c); new v2 = directors.round_robin(); v2.add_backend(app2a); v2.add_backend(app2b); v2.add_backend(app2c); }
  15. Nginx server { listen 8080; server_name api.shwrm.net; root /home/api_v1/public; location

    / { try_files $uri /index.php$is_args$args; } location ~ ^/index\.php(/|$) { fastcgi_pass 127.0.0.1:9056; include fastcgi_params; internal; } }
  16. server { listen 8081; server_name api.shwrm.net; root /home/api_v2/web; location /

    { try_files $uri /app.php$is_args$args; } location ~ ^/app\.php(/|$) { fastcgi_pass 127.0.0.1:9071; include fastcgi_params; internal; } } Nginx
  17. Varnish sub vcl_recv { if (req.http.Accept == "application/vnd.showroom.v2+json") { set

    req.backend_hint = v2.backend(); } else { set req.backend_hint = v1.backend(); } }
  18. sub vcl_recv { if ( req.url ~ "^/_(wdt|profiler|error|docs)/" || req.url

    ~ "^/assets/" || req.url ~ "^/orders/[0-9]+/refund" ) { set req.backend_hint = v2.backend(); } else { set req.backend_hint = v1.backend(); } } Varnish
  19. PSQL 5432 PHP 5.6 9056 NGINX
 80/443 Varnish 6081 NGINX

    8080 Elasticsearch
 9200 RabbitMQ
 5672 Redis 6379 NGINX 8081 PHP 7.1 9071