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

De Legacy à Symfony

De Legacy à Symfony

Vous avez déjà travaillé avec de vieux projet PHP (3,4), du “include-ception” ou tout simplement un framework non PSR-0? Voici un retour sur les étapes employé dans différent cas de migration de “legacy” vers Symfony 2.

Avatar for Etienne Lachance

Etienne Lachance

June 16, 2016

Other Decks in Programming

Transcript

  1. QUI SUIS-JE Sys admin de formation Programmeur depuis ~10 ans

    Propriétaire de elcweb.ca Consultation en entreprise Programmation Hébergement spécialisé Fin de l'auto promotion
  2. CONTEXT Evolution d'un projet "Legacy" sans affecter la productivité mais

    en introduisant les bonne pratique d’un nouveau framework.
  3. PAR LEGACY J'ENTEND peu/pas de documentation peu/pas de tests Code

    procédural Code spaghetti Duplication de code (copier-coller) Include-ception Couplage de responsabilité ... Non SOLID
  4. OBJECTIF Permet de refactoriser le code petit peu par petit

    peu mais d'avoir des avantages rapidement.
  5. 1. PARALLEL simple a implémenter (mod_rewrite) aucune communication direct entre

    les 2 applications utilisation de la BD ou Redis pour l'échange entre les 2 apps peu/pas d'impacte sur l'application 1
  6. 2. PROXY l'utilisateur voie uniquement une application (Symfony) necessite plus

    de travail pour la mise en place "wrapper" pour les requêtes a l'application Legacy authenti cation sécurité entre les 2 applications peu/pas d'impacte sur l'application Legacy
  7. 3. INTÉGRATION On veut changer la structure fondamental du code

    actuel. une seule application OPTION PRÉSENTÉ
  8. QU'EST-CE QUE SYMFONY? Symfony est * une collection de composante

    un framework applicatif une philosophy une communauté Symfony est a la base un framework HTTP GESTION DES REQUÊTE / RÉPONSE source: http://symfony.com/what-is-symfony
  9. EXEMPLE DE TYPE "INCLUDE-CEPTION" < ? p h p /

    / i n d e x . p h p i n c l u d e ( " i n c l u d e s / c o m m o n . p h p " ) ; i n c l u d e ( " i n c l u d e s / c o n f i g . p h p " ) ; $ m o d = $ _ G E T [ ' m o d ' ] ; i f ( $ m o d = = " " | | ! p r e g _ m a t c h ( ' / ^ [ A - Z a - z 1 - 9 0 _ ] + $ / U i ' , $ m o d ) ) $ m o d = " d a s h b o a r d " ; i n c l u d e ( " m o d u l e s / " . $ m o d . " . p h p " ) ; aucun namespace logique basé sur include() / require()
  10. LEGACY CONTROLLER n a m e s p a c

    e A p p B u n d l e \ C o n t r o l l e r ; u s e . . . ; c l a s s L e g a c y C o n t r o l l e r e x t e n d s C o n t r o l l e r { / * * @ R o u t e ( " / i n d e x . p h p " ) * / p u b l i c f u n c t i o n l e g a c y A c t i o n ( ) { / / _ _ D I R _ _ = = ' s r c / A p p B u n d l e / C o n t r o l l e r ' i n c l u d e _ _ D I R _ _ . ' / . . / i n c l u d e s / c o m m o n . p h p ' ; i n c l u d e _ _ D I R _ _ . ' / . . / i n c l u d e s / c o n f i g . p h p ' ; / / @ t o d o : r e n o m m é $ m o d p o u r $ m o d u l e $ m o d = $ _ G E T [ ' m o d ' ] ; i f ( $ m o d = = " " | | ! p r e g _ m a t c h ( ' / ^ [ A - Z a - z 1 - 9 0 _ ] + $ / U i ' , $ m o d ) ) { $ m o d = " d a s h b o a r d " ; }
  11. LEGACY CONTROLLER - SUITE / / I n c l

    u d e m o d u l e f i l e $ f i l e n a m e = _ _ D I R _ _ . ' / . . / m o d u l e s / ' . $ m o d . ' . p h p ' ; i f ( ! f i l e _ e x i s t s ( $ f i l e n a m e ) ) { t h r o w n e w N o t F o u n d H t t p E x c e p t i o n ( ' M o d u l e ' . $ m o d . ' n o t f o u n d ' ) ; } / / o b _ s t a r t : T u r n o n o u t p u t b u f f e r i n g o b _ s t a r t ( ) ; i n c l u d e $ f i l e n a m e ; r e t u r n n e w R e s p o n s e ( o b _ g e t _ c l e a n ( ) ) ; } }
  12. RÉCAPITULATION déplacer les chiers a l'extérieur du répertoire publique véri

    er si le module exist si le module n'existe pas, retourne une erreur 404 encapsuler les "echo" du code legacy dans un objet Response
  13. UTILISATEUR Implement UserInterface < ? p h p n a

    m e s p a c e A p p B u n d l e \ S e c u r i t y \ U s e r ; u s e . . . c l a s s U s e r i m p l e m e n t s U s e r I n t e r f a c e { p r i v a t e $ u s e r n a m e ; p r i v a t e $ p a s s w o r d ; p r i v a t e $ s a l t p r i r a t e $ r o l e s ; . . . }
  14. PROVIDER Est responsable d'aller chercher l'utilisateur Implement UserProviderInterface n a

    m e s p a c e A p p B u n d l e \ S e c u r i t y \ U s e r ; u s e . . . c l a s s U s e r P r o v i d e r i m p l e m e n t s U s e r P r o v i d e r I n t e r f a c e { p u b l i c f u n c t i o n l o a d U s e r B y U s e r n a m e ( $ u s e r n a m e ) { . . . } p u b l i c f u n c t i o n r e f r e s h U s e r ( U s e r I n t e r f a c e $ u s e r ) { . . . } p u b l i c f u n c t i o n s u p p o r t s C l a s s ( $ c l a s s ) { r e t u r n $ c l a s s = = = ' A p p B u n d l e \ S e c u r i t y \ U s e r \ U s e r ' ; } }
  15. ENCODER Responsable d'encoder et de valider un mot de passe

    n a m e s p a c e A p p B u n d l e \ S e c u r i t y \ E n c o d e r ; u s e S y m f o n y \ C o m p o n e n t \ S e c u r i t y \ C o r e \ E n c o d e r \ B a s e P a s s w o r d E n c o d e r ; c l a s s L e g a c y M d 5 E n c o d e r e x t e n d s B a s e P a s s w o r d E n c o d e r { p u b l i c f u n c t i o n i s P a s s w o r d V a l i d ( $ e n c o d e d , $ r a w , $ s a l t = n u l l ) : b o o l { r e t u r n $ t h i s - > c o m p a r e P a s s w o r d s ( s t r t o l o w e r ( $ e n c o d e d ) , s t r t o l o w e r ( $ t h i s - > e n c o d e P a s s w o r d ( $ r a w , $ } p u b l i c f u n c t i o n e n c o d e P a s s w o r d ( $ r a w , $ s a l t = n u l l ) : s t r i n g { r e t u r n m d 5 ( $ r a w . ' s e c r e t _ g l o b a l _ a _ l _ a p p l i c a t i o n ' ) ; } }
  16. CONFIGURATION app/con g/services.yml s e r v i c e

    s : a p p . u s e r _ p r o v i d e r : c l a s s : A p p B u n d l e \ S e c u r i t y \ U s e r \ U s e r P r o v i d e r a p p . s e c u r i t y . e n c o d e r . m d 5 : c l a s s : A p p B u n d l e \ S e c u r i t y \ E n c o d e r \ L e g a c y M d 5 E n c o d e r app/con g/security.yml s e c u r i t y : e n c o d e r s : A p p B u n d l e \ S e c u r i t y \ U s e r \ U s e r : i d : a p p . s e c u r i t y . e n c o d e r . m d 5 p r o v i d e r s : l e g a c y : i d : a p p . u s e r _ p r o v i d e r f i r e w a l l : m a i n : p a t t e r n : ^ / h t t p _ b a s i c : ~
  17. DOCTRINE / REPOSITORY Dans le contexte de Doctrine, un Repository

    est utilisé pour allez chercher l'information Centraliser les requêtes SQL Isoler les requêtes du "controlleur" Classi er par context d'objet (Utilisateur/Produit/Client)
  18. LEGACY < ? p h p / / . .

    . $ c o n n = m y s q l _ c o n n e c t ( $ d b _ h o s t , $ d b _ u s e r , $ d b _ p a s s w o r d ) ; i f ( ! $ c o n n ) { e c h o " U n a b l e t o c o n n e c t t o D B : " . m y s q l _ e r r o r ( ) ; e x i t ; } i f ( ! m y s q l _ s e l e c t _ d b ( $ d b n a m e ) ) { e c h o " U n a b l e t o s e l e c t m y d b n a m e : " . m y s q l _ e r r o r ( ) ; e x i t ; } $ s q l = " S E L E C T * F R O M p r o d u c t s W H E R E c a t e g o r y = " . m y s q l _ r e a l _ e s c a p e _ s t r i n g ( $ _ G E T [ ' c a t ' ] ) . " ; "
  19. LEGACY - SUITE $ r e s u l t

    = m y s q l _ q u e r y ( $ s q l ) ; i f ( ! $ r e s u l t ) { e c h o " C o u l d n o t s u c c e s s f u l l y r u n q u e r y ( $ s q l ) f r o m D B : " . m y s q l _ e r r o r ( ) ; e x i t ; } i f ( m y s q l _ n u m _ r o w s ( $ r e s u l t ) = = 0 ) { e c h o " N o r o w s f o u n d , n o t h i n g t o p r i n t s o a m e x i t i n g " ; e x i t ; } $ d a t a = a r r a y ( ) ; w h i l e ( $ r o w = m y s q l _ f e t c h _ a s s o c ( $ r e s u l t ) ) { $ d a t a = $ r o w ; } m y s q l _ f r e e _ r e s u l t ( $ r e s u l t ) ;
  20. GÉNÉRATION D'ENTITÉ A PARTIR D'UNE BASE DE DONNÉ EXISTANTE $

    p h p b i n / c o n s o l e d o c t r i n e : m a p p i n g : i m p o r t - - f o r c e A c m e B l o g B u n d l e x m l $ p h p b i n / c o n s o l e d o c t r i n e : m a p p i n g : c o n v e r t a n n o t a t i o n . / s r c $ p h p b i n / c o n s o l e d o c t r i n e : g e n e r a t e : e n t i t i e s A c m e B l o g B u n d l e http://symfony.com/doc/current/cookbook/doctrine/reverse_engineering.html
  21. REPOSITORY n a m e s p a c e

    A p p B u n d l e \ E n t i t y ; u s e D o c t r i n e \ O R M \ E n t i t y R e p o s i t o r y ; c l a s s P r o d u c t R e p o s i t o r y e x t e n d s E n t i t y R e p o s i t o r y { p u b l i c f u n c t i o n f i n d B y C a t e g o r y ( $ c a t e g o r y I d ) { $ s q l = " S E L E C T * F R O M p r o d u c t s W H E R E c a t e g o r y = " . m y s q l _ r e a l _ e s c a p e _ s t r i n g ( $ c a t e g o r y I d $ s t m t = $ t h i s - > g e t E n t i t y M a n a g e r ( ) - > g e t C o n n e c t i o n ( ) - > p r e p a r e ( $ s q l ) ; $ s t m t - > e x e c u t e ( ) ; r e t u r n $ s t m t - > f i n d A l l ( ) ; } } RawSQLTrait: https://gist.github.com/estheban/3eae41271f6cf5f3180a
  22. UTILISATION DANS UN CONTROLLEUR c l a s s P

    r o d u c t C o n t r o l l e r e x t e n d s C o n t r o l l e r { / * * * @ R o u t e ( " / p r o d u c t . p h p / c a t e g o r y / { i d } " ) * / p u b l i c f u n c t i o n p r o d u c t B y C a t e g o r y ( C a t e g o r y $ c a t e g o r y ) { / / t h r o w 4 0 4 s i p a s d e C a t é g o r i e t r o u v é e $ e n t i t y M a n a g e r = $ t h i s - > g e t D o c t r i n e ( ) - > g e t M a n a g e r ( ) ; r e t u r n $ e n t i t y M a n a g e r - > g e t R e p o s i t o r y ( " A p p B u n d l e : P r o d u c t " ) - > f i n d B y C a t e g o r y ( $ c a t e g o r y - > g e t I d ( ) ) ; } } Voir: @ParamConverter
  23. TEMPLATES Ne pas convertir les templates pour le "Fun" On

    peut retourner: une réponse directement (aucun template) un template en php un template en twig (natif) un template en smarty un template en ...
  24. EXEMPLE D'UN CONTROLLEUR QUI RETOURNE UNE RÉPONSE BASÉ SUR UN

    TEMPLATE p u b l i c f u n c t i o n i n d e x A c t i o n ( ) { / / s o m e l o g i c t o r e t r i e v e t h e b l o g s $ b l o g s = . . . ; $ t h i s - > r e n d e r ( ' A c m e B l o g B u n d l e : B l o g : i n d e x . h t m l . t w i g ' , a r r a y ( ' b l o g s ' = > $ b l o g s ) ) ; }
  25. EXEMPLE D'UN TEMPLATE EN TWIG { # a p p

    / R e s o u r c e s / v i e w s / b l o g / i n d e x . h t m l . t w i g # } { % e x t e n d s ' b l o g / l a y o u t . h t m l . t w i g ' % } { % b l o c k c o n t e n t % } { % f o r b l o g P o s t i n b l o g s % } < h 2 > { { b l o g P o s t . t i t l e } } < / h 2 > < p > { { b l o g P o s t . b o d y } } < / p > { % e n d f o r % } { % e n d b l o c k % }
  26. EXEMPLE DE SMARTY ET TWIG p r o t e

    c t e d f u n c t i o n r e n d e r S m a r t y ( $ t e m p l a t e , $ o u t p u t D a t a ) { $ s m a r t y = n e w S m a r t y E n g i n e ( ) ; $ s m a r t y - > a s s i g n ( $ o u t p u t D a t a ) ; r e t u r n $ t h i s - > r e n d e r ( ' @ E l c w e b L e g a c y / D e f a u l t / d e f a u l t . h t m l . t w i g ' , [ ' o u t p u t ' = > $ s m a r t y - > f e t c h ( $ t e m p l a t e ) ] ) ; } p u b l i c f u n c t i o n b o b A c t i o n ( ) { $ o u t p u t D a t a = [ ' f o o ' = > ' b a r ' ] ; r e t u r n $ t h i s - > r e n d e r S m a r t y ( ' b o b . t p l ' , $ o u t p u t D a t a ) ; }