Slide 1

Slide 1 text

From Legacy to Symfony Sebastian Grodzicki !@sebgrodzicki

Slide 2

Slide 2 text

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

Slide 3

Slide 3 text

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

Slide 4

Slide 4 text

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

Slide 5

Slide 5 text

No content

Slide 6

Slide 6 text

GoldenLine Developer on-boarding
 took almost 6 months

Slide 7

Slide 7 text

GoldenLine No documentation

Slide 8

Slide 8 text

GoldenLine No tests

Slide 9

Slide 9 text

GoldenLine Complexity

Slide 10

Slide 10 text

“The single worst strategic mistake that any software company can make: rewrite the code from scratch.”

Slide 11

Slide 11 text

GoldenLine @ 2012 Composer

Slide 12

Slide 12 text

GoldenLine @ 2012 #1 Symfony component
 Console

Slide 13

Slide 13 text

GoldenLine @ 2012 Symfony 2.1

Slide 14

Slide 14 text

Proof of Concept

Slide 15

Slide 15 text

@LegacyIfRoleNot

Slide 16

Slide 16 text

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

Slide 17

Slide 17 text

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

Slide 18

Slide 18 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 19

Slide 19 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 20

Slide 20 text

Feature flags

Slide 21

Slide 21 text

Boostrap

Slide 22

Slide 22 text

Internet Explorer 6

Slide 23

Slide 23 text

@LegacyIfOldBrowser

Slide 24

Slide 24 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 25

Slide 25 text

GET vs POST GET /foobar

Slide 26

Slide 26 text

GET vs POST POST /foobar

Slide 27

Slide 27 text

CSRF

Slide 28

Slide 28 text

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

Slide 29

Slide 29 text

GoldenLine Developer on-boarding took almost 6 months

Slide 30

Slide 30 text

GoldenLine No documentation

Slide 31

Slide 31 text

GoldenLine No tests

Slide 32

Slide 32 text

GoldenLine Complexity

Slide 33

Slide 33 text

Symfony Awards 2013 Best Social Website

Slide 34

Slide 34 text

Symfony Awards 2013 Best Symfony Website

Slide 35

Slide 35 text

SHOWROOM

Slide 36

Slide 36 text

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

Slide 37

Slide 37 text

SHOWROOM Locked on
 Phalcon 2 & PHP 5.6

Slide 38

Slide 38 text

No documentation SHOWROOM

Slide 39

Slide 39 text

No tests SHOWROOM

Slide 40

Slide 40 text

Frustration SHOWROOM

Slide 41

Slide 41 text

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

Slide 42

Slide 42 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 43

Slide 43 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 • PHP 7.1 Elasticsearch
 9200 RabbitMQ
 5672 Redis 6379 NGINX 8081 PHP 7.1 9071

Slide 44

Slide 44 text

Varnish

Slide 45

Slide 45 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 46

Slide 46 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 47

Slide 47 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 48

Slide 48 text

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

Slide 49

Slide 49 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 50

Slide 50 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 51

Slide 51 text

PostgreSQL

Slide 52

Slide 52 text

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

Slide 53

Slide 53 text

PostgreSQL Table View

Slide 54

Slide 54 text

ESI ESI

Slide 55

Slide 55 text

Microservices HTTP Core API Shipping API

Slide 56

Slide 56 text

Microservices Core API Analytics

Slide 57

Slide 57 text

SHOWROOM Locked on
 Phalcon 2 & PHP 5.6

Slide 58

Slide 58 text

No documentation SHOWROOM

Slide 59

Slide 59 text

No tests SHOWROOM

Slide 60

Slide 60 text

Frustration SHOWROOM

Slide 61

Slide 61 text

Questions? https://joind.in/talk/ddace

Slide 62

Slide 62 text

Thank you! https://joind.in/talk/ddace