From * to Symfony2

Post on 16-Jan-2017

176 views 1 download

Transcript of From * to Symfony2

From * to Symfony 2

* Sf1, Zf1, PHP plain, …

Manuel “Kea” Baldassarri

If anything can go wrong, it will

Capt. Edward A. Murphy

Agenda

• rewrite vs. migration

• code organization

• routing

• database

• authentication aka session

Program complexity grows until it exceeds the capability of the programmer who must maintain it.

Murphy's laws

Rewrite vs

migration

Rewrite (theory)Fe

atur

es

0

30

60

90

120

t0 t1 t2 t3 t4 t5

Old site New site

If anything can go wrong, it will

Murphy's laws

Rewrite (real)

0

30

60

90

120

t0 t1 t2 t3 t4 t5

Old site New site real

RewriteEstimations are wrong, the legacy code is worse than your wildest imagination, the customer wants new features, you have to maintain the current site and develop the new code base, you code fast, port the same feature from the old site to the new one, import db, deploy, switch…

MigrationFe

atur

es

0

30

60

90

120

t0 t1 t2 t3 t4 t5

Old tech New tech Total

Rewrite: practice

Only two steps if you decide to rewrite your paper

• Foto con mac e blocco

Rewrite

$ rm -Rf project $ symfony new project

Pre migration

PHP > 5.3

Symfony 1.5

LExpress/symfony1

PHPCompatibility

$ phpcs --standard=PHPCompatibility \ --runtime-set testVersion 5.6

Code structure: as you wish

Routing: multiple entry

point

Catch’em all route/** * @Route("/{filename}.php") */public function catchEmAllAction($filename) { ob_start(); include $filename.”.php”;

$content = ob_get_clean(); $this->doSomeHeadersStuff(headers_list()); return new Response($content); }

Routing: 2 front controllers

Two front controllers

/path/to/legacy/public/index.php

/path/to/sf2/web/app.php

Easy wayREQUEST

WEB SERVER

FRONT CTRL 1 FRONT CTRL 2

Subdomain

http://www.mysite.com

http://new.mysite.com

OLD

NEW

Url prefix

http://www.mysite.com/

http://www.mysite.com/new/

OLD

NEW

Sf2 proxyREQUEST

WEB SERVER

FRONT CTRL 2 FRONT CTRL 1

Event listener

legacy.kernel.listener: class: AppBundle\LegacyBridge\KernelListener tags: - name: kernel.event_listener event: kernel.exception method: onKernelException

NotFoundHttpExceptionpublic function onKernelException($event){ $exception = $event->getException(); if ($exception instanceof NotFoundHttpException) { ob_start(); include "/path/to/old/index.php"; $content = ob_get_clean(); $this->doSomeHeadersStuff(headers_list());

$event->setResponse(new Response($content)); } }

Database

Database

• Cleanup

• Import metadata/structure

• Create entity

• [Add annotation]

Metadata

$ php app/console \ doctrine:mapping:import \ --force AppBundle xml

Entities

$ php app/console \ doctrine:generate:entities AppBundle

Annotation

$ php app/console \ doctrine:mapping:convert annotation ./src

Annotation/** * IngredientTranslation * * @ORM\Table(name=“ingredient_translation", * indexes={ * @ORM\Index(name=“IDX_C1A8BF6BF396750”, * columns={“id"}) * }) * @ORM\Entity */ class IngredientTranslation{…}

Entitiesclass Wow{ /** * @ORM\Column(name="p0", type="integer") * @ORM\Id */ private $p0;

/** * @ORM\Column(name="p1", type="string", …) */ private $p1; … }

Entitiesclass Wow{ /** * @ORM\Column(name="p0", type="integer") * @ORM\Id */ private $id;

/** * @ORM\Column(name="p1", type="string", …) */ private $title; … }

Authentication aka

Session

Login in Sf2 app

Add layer to read Sf2 session

Forge a compatible $_SESSION

or

Login in “Old” app

Use preAuthentication

SessionBagInterfaceMetadataBag

FlashBag AutoExpireFlashBag

AttributeBag NamespacedAttributeBag

$_SESSION (old app logged in)

[ 'App' => [ 'user_id' => 10, ‘username' => 'kea' ] ]

$_SESSION (anonym)

[ '_sf2_attributes' => [ ] '_sf2_flashes' => [ ] '_sf2_meta' => [ ... ]]

$_SESSION (logged in)

[ '_sf2_attributes' => [ '_security_application' =>

<serialised token> …

] …

]

Register bag onKernelRequest

$bag = new NamespacedAttributeBag('App');$bag->setName('App'); $session->registerBag($bag);

SimplePreAuthenticatorpublic function createToken( Request $request, $providerKey){ $session = $request->getSession(); $bag = $session->getBag('App'); if (!$bag->has("user_id") || !$bag->has("username")) { throw new BadCredentialsException(‘!'); } …}

SimplePreAuthenticatorpublic function createToken( Request $request, $providerKey){ … return new PreAuthenticatedToken( 'anon.', [ "id" => $bag->has("user_id"), "username" => $bag->has("username") ], $providerKey );}

SimplePreAuthenticator

public function authenticateToken( TokenInterface $token, UserProviderInterface $userProvider, $providerKey){ $credentials = $token->getCredentials(); $user = $this ->userProvider ->loadUserByIdAndUsername( $credentials[“id"], $credentials[“username"] ); … }

The bundle

TheodoEvolutionSessionBundle

Alternative way

Single Sign On

Templating

Templating

Rewrite pros

•green field

•no old code to manage

Rewrite cons

•data import

•time to market

•two sites to maintain

Migration pros

•time to market

•gradual learning

•fade out of old code

•no data migration

Migration cons

•spaghetti code for long time

•learn how to pair two technologies

Thank You

References and credits

https://github.com/wimg/PHPCompatibility https://github.com/LExpress/symfony1 http://symfony.com/doc/current/cookbook/doctrine/reverse_engineering.html https://github.com/theodo/TheodoEvolutionSessionBundle https://github.com/marfillaster/ButterweedSF1EmbedderBundle https://www.flickr.com/photos/clairity/1267539354 https://www.flickr.com/photos/usfwshq/6777513684