Slide 1

Slide 1 text

MAINTAINING LEGACY APPLICATIONS WITH COMPOSER AND LARAVEL by Bernhard Breytenbach

Slide 2

Slide 2 text

ABOUT ME Started with PHP in 2005 Supporter of all things Open Source! https://github.com/Xethron Laravel Migrations Generator Developer at MDS Technologies @BBreyten on Twitter joind.in/talk/788d8

Slide 3

Slide 3 text

WHAT IS LEGACY SOFTWARE? “The secondary value of software is its behaviour... It’s achieved when the current software meets the current needs of the current user... But the needs of the users change, and they do so frequently... Thus the primary value of software is its ability to change.” — Robert C. Martin (Uncle Bob)

Slide 4

Slide 4 text

WHAT IS LEGACY SOFTWARE? Legacy software is software that is unable to change easily Software that is difficult to read and reuse

Slide 5

Slide 5 text

“DON’T MAINTAIN, REWRITE!”

Slide 6

Slide 6 text

NETSCAPE NAVIGATOR

Slide 7

Slide 7 text

THE DANGERS OF REWRITE

Slide 8

Slide 8 text

REFACTORING Refactoring is the process of restructuring existing code without changing its external behaviour, in order to improve readability and reduce code complexity, as to improve source code maintainability and create a more expressive internal architecture or object model to improve extensibility. https://en.wikipedia.org/wiki/Code_refactoring

Slide 9

Slide 9 text

RULES OF REFACTORING Small iterative changes Make sure everything still works Send to QA, Push to Production Release regularly (weekly at most) Do the next small change

Slide 10

Slide 10 text

VERSION CONTROL

Slide 11

Slide 11 text

DEPLOYMENT

Slide 12

Slide 12 text

PICK A CODING STANDARD PSR1 / PSR2 / Symfony Only one standard php-cs-fixer: https://github.com/FriendsOfPhp/PHP-CS-Fixer

Slide 13

Slide 13 text

DIRECTORY STRUCTURE public/ src/ vendor/ bootstrap/

Slide 14

Slide 14 text

MOVE FUNCTIONALITY INTO CLASSES Get rid of includes One class per file Files should declare new symbols, or cause side effects, but not do both.

Slide 15

Slide 15 text

REPLACE MAGIC NUMBERS WITH CONSTANTS i f ( $ s t a t u s ­ > i d = = = 1 5 ) i f ( $ u s e r ­ > t y p e = = = 3 ) i f ( $ c o d e = = = 4 1 8 ) i f ( $ s t a t u s ­ > i d = = = S t a t u s : : C A N C E L L E D ) i f ( $ u s e r ­ > t y p e = = = U s e r : : T Y P E _ A D M I N ) i f ( $ c o d e = = = R e s p o n s e : : H T T P _ I _ A M _ A _ T E A P O T )

Slide 16

Slide 16 text

BREAK UP LARGE CLASSES/FUNCTIONS Large functions is where classes go to hide.

Slide 17

Slide 17 text

PLAN OF ACTION Take Charge! Baby steps Fail fast, fail cheap

Slide 18

Slide 18 text

SETUP AUTOLOADING < ? p h p s p l _ a u t o l o a d _ r e g i s t e r ( f u n c t i o n ( $ c l a s s ) { $ p r e f i x = ' F o o \ \ B a r \ \ ' ; $ b a s e _ d i r = _ _ D I R _ _ . ' / s r c / ' ; $ l e n = s t r l e n ( $ p r e f i x ) ; i f ( s t r n c m p ( $ p r e f i x , $ c l a s s , $ l e n ) ! = = 0 ) { r e t u r n ; } $ r e l a t i v e _ c l a s s = s u b s t r ( $ c l a s s , $ l e n ) ; $ f i l e = $ b a s e _ d i r . s t r _ r e p l a c e ( ' \ \ ' , ' / ' , $ r e l a t i v e _ c l a s s ) . ' . p h p ' ; / / i f t h e f i l e e x i s t s , r e q u i r e i t i f ( f i l e _ e x i s t s ( $ f i l e ) ) { r e q u i r e $ f i l e ; } } ) ;

Slide 19

Slide 19 text

COMPOSER

Slide 20

Slide 20 text

WHAT IS COMPOSER?

Slide 21

Slide 21 text

WHY USE COMPOSER?

Slide 22

Slide 22 text

BUT I CAN WRITE IT MYSELF?

Slide 23

Slide 23 text

SETTING UP COMPOSER

Slide 24

Slide 24 text

BOOTSTRAP COMPOSER r e q u i r e " v e n d o r / a u t o l o a d . p h p "

Slide 25

Slide 25 text

LOAD THIRD PARTY LIBRARIES VIA COMPOSER Require third party libraries with Composer Look for files using those libraries Make sure they require your bootstrapping file

Slide 26

Slide 26 text

COMPOSER AUTOLOADING { " a u t o l o a d " : { " c l a s s m a p " : [ " l e g a c y ­ c l a s s e s " , " s o m e O t h e r F o l d e r " ] , " p s r ­ 0 " : { " M d s \ \ C o l l i v e r y " : " m y ­ a p p / " , } , " p s r ­ 4 " : { " M d s \ \ V i s a P a k " : " a l s o ­ m y ­ a p p / " , } } }

Slide 27

Slide 27 text

START USING OTHER THIRD PARTY LIBRARIES! Carbon

Slide 28

Slide 28 text

SETTING UP LARAVEL

Slide 29

Slide 29 text

APACHE < V i r t u a l H o s t * : 8 0 > D o c u m e n t R o o t / v a r / w w w / l e g a c y / h t d o c s S e r v e r A d m i n b e r n h a r d @ c o f f e e c o d e . c o . z a S e r v e r N a m e w w w . l e g a c y . l o c a l S e r v e r A l i a s l e g a c y . l o c a l T r a n s f e r L o g / v a r / l o g / a p a c h e 2 / l e g a c y _ a c c e s s . l o g E r r o r L o g / v a r / l o g / a p a c h e 2 / l e g a c y _ e r r o r . l o g < D i r e c t o r y / v a r / w w w / l e g a c y / h t d o c s > R e w r i t e E n g i n e O n # R e d i r e c t T r a i l i n g S l a s h e s . . . R e w r i t e R u l e ^ ( . * ) / $ / $ 1 [ L , R = 3 0 1 ] R e w r i t e C o n d % { R E Q U E S T _ F I L E N A M E } ! ­ d R e w r i t e C o n d % { R E Q U E S T _ F I L E N A M E } ! ­ f R e w r i t e R u l e ^ a p p . p h p [ L ] < / D i r e c t o r y > < / V i r t u a l H o s t >

Slide 30

Slide 30 text

ROUTES < ? p h p R o u t e : : g e t ( ' r e g i s t e r ' , R e g i s t e r C o n t r o l l e r : : c l a s s . ' @ i n d e x ' ) ; R o u t e : : g e t ( ' r e g i s t e r . p h p ' , R e g i s t e r C o n t r o l l e r : : c l a s s . ' @ i n d e x ' ) ;

Slide 31

Slide 31 text

BOOTSTRAPPING LARAVEL < ? p h p u s e A c m e \ B o o t s t r a p \ R a v e n S e r v i c e P r o v i d e r ; u s e I l l u m i n a t e \ F i l e s y s t e m \ F i l e s y s t e m ; u s e I l l u m i n a t e \ F o u n d a t i o n \ P r o v i d e r R e p o s i t o r y ; u s e I l l u m i n a t e \ H t t p \ R e q u e s t ; d a t e _ d e f a u l t _ t i m e z o n e _ s e t ( ' A f r i c a / J o h a n n e s b u r g ' ) ; r e q u i r e _ _ D I R _ _ . ' / a u t o l o a d . p h p ' ; / * * @ v a r \ I l l u m i n a t e \ F o u n d a t i o n \ A p p l i c a t i o n $ a p p * / $ a p p = r e q u i r e _ o n c e _ _ D I R _ _ . ' / a p p . p h p ' ; $ a p p ­ > i n s t a n c e ( ' r e q u e s t ' , R e q u e s t : : c a p t u r e ( ) ) ; $ a p p ­ > b o o t s t r a p W i t h ( [ I l l u m i n a t e \ F o u n d a t i o n \ B o o t s t r a p \ D e t e c t E n v i r o n m e n t : : c l a s s , I l l u m i n a t e \ F o u n d a t i o n \ B o o t s t r a p \ L o a d C o n f i g u r a t i o n : : c l a s s , I l l u m i n a t e \ F o u n d a t i o n \ B o o t s t r a p \ C o n f i g u r e L o g g i n g : : c l a s s , A c m e \ B o o t s t r a p \ H a n d l e E x c e p t i o n s : : c l a s s , I l l u m i n a t e \ F o u n d a t i o n \ B o o t s t r a p \ R e g i s t e r F a c a d e s : : c l a s s , ] ) ; / *

Slide 32

Slide 32 text

USING LARAVEL OUTSIDE OF LARAVEL

Slide 33

Slide 33 text

SIMPLE: REQUESTS/COLLECTIONS < ? p h p i f ( i s s e t ( $ _ G E T [ ' n a m e ' ] ) ) { $ n a m e = $ _ G E T [ ' n a m e ' ] ; } e l s e { $ n a m e = ' D e m o U s e r ' ; } / / ­ ­ ­ $ n a m e = R e q u e s t : : g e t ( ' n a m e ' ) ;

Slide 34

Slide 34 text

SIMPLE: REQUESTS/COLLECTIONS < ? p h p $ a r r a y = n e w \ I l l u m i n a t e \ S u p p o r t \ C o l l e c t i o n ( ) ; $ a r r a y ­ > f i l t e r ( ) ; $ a r r a y ­ > m a p ( ) ; $ a r r a y ­ > r e d u c e ( ) ;

Slide 35

Slide 35 text

IOC < ? p h p $ c o l l i v e r y = a p p ( ' c o l l i v e r y ' ) ;

Slide 36

Slide 36 text

ELOQUENT/DATABASE < ? p h p $ u s e r s = U s e r : : a l l ( ) ; D B : : c o n n e c t i o n ( ' m y s q l ' ) ­ > t a b l e ( ' u s e r s ' ) ­ > w h e r e N u l l ( ' d e l e t e d A t ' ) ­ > g e t ( ) ;

Slide 37

Slide 37 text

VIEWS < ? p h p $ u s e r = A u t h : : u s e r ( ) ; e c h o v i e w ( ' i n d e x ' , c o m p a c t ( ' u s e r ' ) ) ­ > r e n d e r ( ) ;

Slide 38

Slide 38 text

EMAILS < ? p h p $ h t m l m s g h e a d = " < h t m l > < h e a d > < / h e a d > < b o d y > < p > < d i v a l i g n = \ " l e f t \ " w i d t h = \ " 6 0 0 p t ; \ " > < / d i v $ h t m l m s g h e a d . = " < p > < s p a n s t y l e = \ " f o n t ­ s i z e : 1 2 p t ; f o n t ­ f a m i l y : ' A r i a l ' , ' s a n s ­ s e r i f ' \ " $ h t m l m s g f o o t = " < s p a n s t y l e = \ " f o n t ­ s i z e : 1 0 p t ; f o n t ­ f a m i l y : ' A r i a l ' , ' s a n s ­ s e r i f ' \ " > < b r $ h t m l m s g f o o t . = " < s p a n s t y l e = \ " f o n t ­ s i z e : 1 6 p t ; f o n t ­ f a m i l y : ' T i m e N e w R o m a n ' , ' s a n s ­ s e r i $ h t m l m s g f o o t . = " < b r / > " . $ _ S E S S I O N [ ' e m a i l ' ] . " < / s p a n > < p > < b > < s p a n s t y l e = \ " f o n t ­ s i z e : 1 0 p t ; c o l o r : n a v y ; f o n t ­ f a m i l y : ' A r i a l ' , ' s a n s ­ s e r i f ' \ " > < p > < b > < s p a n s t y l e = \ " f o n t ­ s i z e : 1 0 p t ; c o l o r : n a v y ; f o n t ­ f a m i l y : ' A r i a l ' , ' s a n s ­ s e r i f ' \ " > < p > < d i v a l i g n = \ " l e f t \ " w i d t h = \ " 6 0 0 p t ; \ " > < i m g s r c = \ " c i d : m a i l _ b o t t o m \ " > < / d i v > < / p > < / b o d y > < / h t m l > " ; i n c l u d e _ o n c e ' . . / s r c / p h p m a i l e r / c l a s s . p h p m a i l e r . p h p ' ; $ m a i l = n e w P H P M a i l e r ( t r u e ) ; $ m a i l ­ > I s H T M L ( t r u e ) ; $ m a i l ­ > C h a r S e t = " U T F ­ 8 " ; t r y { $ m a i l ­ > A d d A d d r e s s ( $ _ P O S T [ ' e m a i l ' ] , $ _ P O S T [ ' n a m e ' ] ) ; $ m a i l ­ > S e t F r o m ( $ _ S E S S I O N [ ' e m a i l ' ] ) ; $ m a i l ­ > A d d R e p l y T o ( $ _ S E S S I O N [ ' e m a i l ' ] ) ; $ m a i l ­ > A d d E m b e d d e d I m a g e ( ' m a i l _ t o p . p n g ' , ' m a i l _ t o p ' , ' m a i l _ t o p . p n g ' ) ; $ m a i l ­ > A d d E m b e d d e d I m a g e ( ' m a i l _ b o t t o m . p n g ' , ' m a i l _ b o t t o m ' , ' m a i l _ b o t t o m . p n g ' ) ; $ m a i l ­ > S u b j e c t = " G r e e t i n g s P H P J o b u r g ! " ; $ m a i l ­ > M s g H T M L ( $ h t m l m s g h e a d . " " . n l 2 b r ( $ _ P O S T [ ' m e s s a g e ' ] ) . " " . $ h t m l m s g f o o t ) ;

Slide 39

Slide 39 text

EMAILS < ? p h p t r y { $ d a t a = [ ' t o N a m e ' = > R e q u e s t : : g e t ( ' n a m e ' ) , ' f r o m N a m e ' = > $ _ S E S S I O N [ ' n a m e ' ] , ' f r o m E m a i l ' = > $ _ S E S S I O N [ ' e m a i l ' ] , ' h t m l B o d y ' = > n l 2 b r ( R e q u e s t : : g e t ( ' m e s s a g e ' ) ) ] ; M a i l : : s e n d ( ' e m a i l s . s t a n d a r d ' , $ d a t a , f u n c t i o n ( M e s s a g e $ m e s s a g e ) { $ m e s s a g e ­ > f r o m ( $ _ S E S S I O N [ ' e m a i l ' ] , $ _ S E S S I O N [ ' n a m e ' ] ) ­ > t o ( R e q u e s t : : g e t ( ' e m a i l ' ) , R e q u e s t : : g e t ( ' n a m e ' ) ) ­ > r e p l y T o ( $ _ S E S S I O N [ ' e m a i l ' ] ) ­ > s u b j e c t ( ' G r e e t i n g s P H P J o b u r g ! ' ) ; } ) ; p r i n t ( " < d i v c l a s s = \ " s u c c e s s \ " > E m a i l s e n t t o < b > " . R e q u e s t : : g e t ( ' n a m e ' ) . " < / b > o n e m } c a t c h ( E x c e p t i o n $ e r r ) { e c h o $ e r r ­ > g e t M e s s a g e ( ) ; }

Slide 40

Slide 40 text

CONSOLE COMMANDS

Slide 41

Slide 41 text

The key to success is not perfection, but making peace with the term good enough, and then moving on.