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)
Features
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
Rewrite
Estimations 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…
Migration
Features
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 way
REQUEST
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 proxy
REQUEST
WEB SERVER
FRONT CTRL 2 FRONT CTRL 1
Event listener
legacy.kernel.listener:

class: AppBundleLegacyBridgeKernelListener

tags:

-
name: kernel.event_listener
event: kernel.exception
method: onKernelException

NotFoundHttpException
public 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

*

* @ORMTable(name=“ingredient_translation",
* indexes={
* @ORMIndex(name=“IDX_C1A8BF6BF396750”,
* columns={“id"})
* })

* @ORMEntity

*/

class IngredientTranslation

{
…

}
Entities
class Wow

{
/**

* @ORMColumn(name="p0", type="integer")

* @ORMId

*/

private $p0;
/**

* @ORMColumn(name="p1", type="string", …)

*/

private $p1;

…

}
Entities
class Wow

{
/**

* @ORMColumn(name="p0", type="integer")

* @ORMId

*/

private $id;
/**

* @ORMColumn(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
SessionBagInterface
MetadataBag
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);
SimplePreAuthenticator
public function createToken(
Request $request, $providerKey)

{
$session = $request->getSession();

$bag = $session->getBag('App');

if (!$bag->has("user_id") ||
!$bag->has("username")) {

throw new BadCredentialsException(‘!');

}

…

}

SimplePreAuthenticator
public 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

From * to Symfony2