Slide 1

Slide 1 text

From Legacy to Symfony Sebastian Grodzicki

Slide 2

Slide 2 text

– Sebastian Grodzicki How can one use Symfony 4.0 and PHP 7.2
 while working with a legacy application?

Slide 3

Slide 3 text

Sebastian Grodzicki • CTO at SHOWROOM • former dev & CTO at GoldenLine • SensioLabs Certified
 Symfony Developer (Expert) • PHP developer for 15+ years

Slide 4

Slide 4 text

• business social network founded in 2005 • in-house framework (“Xplod”) • LAMP stack • monolith

Slide 5

Slide 5 text

GoldenLine

Slide 6

Slide 6 text

• developer on-boarding took almost
 6 months • no documentation • no tests • complexity

Slide 7

Slide 7 text

– Joel Spolsky, CEO of Stack Overflow The single worst strategic mistake that any software company can make:
 rewrite the code from scratch.

Slide 8

Slide 8 text

• using Composer • using #1 Symfony component (Console) • decided to migrate to Symfony 2.1 2012

Slide 9

Slide 9 text

Proof of Concept

Slide 10

Slide 10 text

@LegacyIfRoleNot

Slide 11

Slide 11 text

Routing self::$map = [ [ 'uri' => '^/oauth/authorize/?(.+)?$', 'action' => 'oauth/authorize', ], [ 'uri' => '^/m$', 'action' => 'mobile/touch', ], // 746 more like this ];

Slide 12

Slide 12 text

Routing public function convert(array $rule) { $route = new Route('/{uri}'); $route->setRequirement('uri', $this->getRequirement($rule['uri'])); return $route; }

Slide 13

Slide 13 text

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); }

Slide 14

Slide 14 text

@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;

Slide 15

Slide 15 text

Feature flags

Slide 16

Slide 16 text

Boostrap

Slide 17

Slide 17 text

Internet Explorer 6

Slide 18

Slide 18 text

@LegacyIfOldBrowser

Slide 19

Slide 19 text

@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'); }

Slide 20

Slide 20 text

GET vs POST GET /foobar

Slide 21

Slide 21 text

GET vs POST POST /foobar

Slide 22

Slide 22 text

CSRF

Slide 23

Slide 23 text

CSRF public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults( [ 'csrf_field_name' => 'csrf', 'csrf_provider' => $this->csrfProvider, ] ); }

Slide 24

Slide 24 text

GoldenLine • developer on-boarding took almost 6 months • no documentation • no tests • complexity

Slide 25

Slide 25 text

Best Social Website Best Symfony Website

Slide 26

Slide 26 text

SHOWROOM

Slide 27

Slide 27 text

• online fashion marketplace founded in 2012 • built on Slim micro framework & Phalcon • API-centric

Slide 28

Slide 28 text

• locked on Phalcon 2 & PHP 5.6 • no documentation • no tests • frustration

Slide 29

Slide 29 text

• API v2 based on Symfony 3 • store front v2 (Symfony 3) • SHOWROOM SDK for PHP 2016

Slide 30

Slide 30 text

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

Slide 31

Slide 31 text

PSQL 5432 PHP 5.6 9056 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 PHP 7.1 9071 NGINX 8081 NGINX
 80/443

Slide 32

Slide 32 text

Varnish

Slide 33

Slide 33 text

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"; }

Slide 34

Slide 34 text

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); }

Slide 35

Slide 35 text

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; } }

Slide 36

Slide 36 text

Nginx 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; } }

Slide 37

Slide 37 text

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(); } }

Slide 38

Slide 38 text

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

Slide 39

Slide 39 text

PostgreSQL

Slide 40

Slide 40 text

PSQL 5432 Varnish 6081 NGINX 8080 Elasticsearch
 9200 RabbitMQ
 5672 Redis 6379 PHP 7.1 9071 NGINX 8080 PHP 5.6 9056 NGINX
 80/443

Slide 41

Slide 41 text

PostgreSQL Table View

Slide 42

Slide 42 text

ESI

Slide 43

Slide 43 text

Microservices Core API Shipping API HTTP

Slide 44

Slide 44 text

Microservices Core API Analytics

Slide 45

Slide 45 text

• locked on Phalcon 2 & PHP 5.6 • no documentation • no tests • frustration

Slide 46

Slide 46 text

Questions?

Slide 47

Slide 47 text

https://joind.in/talk/70e0c Thank you!