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

Symfony2 REST Edition

Symfony2 REST Edition

See also http://www.rvl.io/gimler/symfony-rest-edition original slides with working text copy and links

Gordon Franke

April 18, 2013
Tweet

More Decks by Gordon Franke

Other Decks in Technology

Transcript

  1. WHY SYMFONY2? Stable Well documented Big Community Over Many PHP

    Evolutions came from Symfony World THERE IS A BUNDLE FOR THAT 1969 Bundles
  2. SETUP CHECK OUT THE DEMO p h p c o

    m p o s e r . p h a r c r e a t e - p r o j e c t \ " g i m l e r / s y m f o n y - r e s t - e d i t i o n : 2 . 2 . x - d e v " p a t h / t o / i n s t a l l Demo REST Notes Demo Controller API Documentation
  3. GENERATE BUNDLE ADD CONTROLLER REWRITE ROUTING p h p a

    p p / c o n s o l e g e n e r a t e : b u n d l e - - n a m e s p a c e = A c m e / T a s k B u n d l e \ - - f o r m a t = y m l - - d i r = s r c - - n o - i n t e r a c t i o n # s r c / A c m e / T a s k B u n d l e / C o n t r o l l e r / T a s k C o n t r o l l e r . p h p < ? p h p n a m e s p a c e A c m e \ T a s k B u n d l e \ C o n t r o l l e r u s e F O S \ R e s t B u n d l e \ C o n t r o l l e r \ F O S R e s t C o n t r o l l e r ; c l a s s T a s k C o n t r o l l e r e x t e n d s F O S R e s t C o n t r o l l e r { } # s r c / A c m e / T a s k B u n d l e / R e s o u r c e s / c o n f i g / r o u t i n g . y m l a c m e _ t a s k _ t a s k : r e s o u r c e : " @ A c m e D e m o B u n d l e / C o n t r o l l e r / T a s k C o n t r o l l e r " t y p e : r e s t
  4. A TASK Plain Old Php Object # s r c

    / A c m e / T a s k B u n d l e / M o d e l / T a s k . p h p < ? p h p n a m e s p a c e A c m e \ T a s k B u n d l e \ M o d e l ; c l a s s T a s k { p u b l i c $ t i t l e ; p u b l i c $ d e s c r i p t i o n ; p u b l i c $ s e c r e t ; }
  5. STOP WRITE A TEST Basic Controller Test # s r

    c / A c m e / T a s k B u n d l e / T e s t s / C o n t r o l l e r / T a s k C o n t r o l l e r T e s t . p h p < ? p h p n a m e s p a c e A c m e \ T a s k B u n d l e \ T e s t s \ C o n t r o l l e r ; u s e S y m f o n y \ B u n d l e \ F r a m e w o r k B u n d l e \ T e s t \ W e b T e s t C a s e ; c l a s s T a s k C o n t r o l l e r T e s t e x t e n d s W e b T e s t C a s e { p r o t e c t e d f u n c t i o n a s s e r t J s o n H e a d e r ( $ r e s p o n s e ) { $ t h i s - > a s s e r t T r u e ( $ r e s p o n s e - > h e a d e r s - > c o n t a i n s ( ' C o n t e n t - T y p e ' , ' a p p l i c a t i o n / j s o n ' ) , $ r e s p o n s e - > h e a d e r s ) ; } }
  6. TEST FOR GET TASKS # s r c / A

    c m e / T a s k B u n d l e / T e s t s / C o n t r o l l e r / T a s k C o n t r o l l e r T e s t . p h p . . . p u b l i c f u n c t i o n t e s t G e t N o t e s ( ) { $ c l i e n t = s t a t i c : : c r e a t e C l i e n t ( ) ; $ c l i e n t - > r e q u e s t ( ' G E T ' , ' / t a s k s . j s o n ' ) ; $ r e s p o n s e = $ c l i e n t - > g e t R e s p o n s e ( ) ; $ t h i s - > a s s e r t J s o n H e a d e r ( $ r e s p o n s e ) ; $ t h i s - > a s s e r t E q u a l s ( 2 0 0 , $ r e s p o n s e - > g e t S t a t u s C o d e ( ) , $ r e s p o n s e - > g e t C o n t e n t ( ) ) ; $ t h i s - > a s s e r t E q u a l s ( ' [ { " t i t l e " : " P u t " , " d e s c r i p t i o n " : " a d d p u t a c t i o n " } ] ' , $ r e s p o n s e - > g e t C o n t e n t ( ) ) ; }
  7. IMPLEMENTATION # s r c / A c m e

    / T a s k B u n d l e / C o n t r o l l e r / T a s k C o n t r o l l e r . p h p . . . u s e F O S \ R e s t B u n d l e \ C o n t r o l l e r \ A n n o t a t i o n s ; u s e A c m e \ T a s k B u n d l e \ M o d e l \ T a s k ; . . . / * * * @ A n n o t a t i o n s \ V i e w ( ) * / p u b l i c f u n c t i o n g e t T a s k s A c t i o n ( ) { $ t a s k = n e w T a s k ( ) ; $ t a s k - > t i t l e = ' P u t ' ; $ t a s k - > d e s c r i p t i o n = ' a d d p u t a c t i o n ' ; $ t a s k - > s e c r e t = ' t o p s e c r e t ' ; r e t u r n a r r a y ( $ t a s k ) ; }
  8. CHECK THE RESULT FAIL! JSON XML [ { " t

    i t l e " : " P u t " , " d e s c r i p t i o n " : " a d d p u t a c t i o n " , " s e c r e t " : " t o p s e c r e t " } ] < ? x m l v e r s i o n = " 1 . 0 " e n c o d i n g = " U T F - 8 " ? > < r e s u l t > < e n t r y > < t i t l e > < ! [ C D A T A [ P u t ] ] > < / t i t l e > < d e s c r i p t i o n > < ! [ C D A T A [ a d d p u t a c t i o n ] ] > < / d e s c r i p t i o n > < s e c r e t > < ! [ C D A T A [ t o p s e c r e t ] ] > < / s e c r e t > < / e n t r y > < / r e s u l t >
  9. MODEL SECURITY! RECHECK THE RESULT # s r c /

    A c m e / T a s k B u n d l e / R e s o u r c e s / c o n f i g / s e r i a l i z e r / M o d e l . T a s k . y m l A c m e \ T a s k B u n d l e \ M o d e l \ T a s k : e x c l u s i o n _ p o l i c y : A L L x m l _ r o o t _ n a m e : t a s k p r o p e r t i e s : t i t l e : e x p o s e : t r u e t y p e : s t r i n g d e s c r i p t i o n : e x p o s e : t r u e t y p e : s t r i n g JSON XML [ { " t i t l e " : " P u t " , " d e s c r i p t i o n " : " a d d p u t a c t i o n " } ] < ? x m l v e r s i o n = " 1 . 0 " e n c o d i n g = " U T F - 8 " ? > < r e s u l t > < e n t r y > < t i t l e > < ! [ C D A T A [ P u t ] ] > < / t i t l e > < d e s c r i p t i o n > < ! [ C D A T A [ a d d p u t a c t i o n ] ] > < / d e s c r i p t i o n > < / e n t r y > < / r e s u l t >
  10. WHAT ABOUT ? DOCUMENTATION # s r c / A

    c m e / T a s k B u n d l e / C o n t r o l l e r / T a s k C o n t r o l l e r . p h p . . . u s e N e l m i o \ A p i D o c B u n d l e \ A n n o t a t i o n \ A p i D o c ; . . . / * * * @ A p i D o c ( * r e s o u r c e = t r u e , * d e s c r i p t i o n = " l i s t o f t a s k s " * s t a t u s C o d e = { * 2 0 0 = " R e t u r n e d w h e n s u c c e s s f u l " * } * ) * /
  11. GET TASK ACTION Move dummy data to constructor # s

    r c / A c m e / T a s k B u n d l e / C o n t r o l l e r / T a s k C o n t r o l l e r . p h p . . . p r o t e c t e d $ t a s k s = a r r a y ( ) ; . . . p u b l i c f u n c t i o n _ _ c o n s t r u c t ( ) { $ t a s k = n e w T a s k ( ) ; $ t a s k - > t i t l e = ' P u t ' ; $ t a s k - > d e s c r i p t i o n = ' a d d p u t a c t i o n ' ; $ t a s k - > s e c r e t = ' t o p s e c r e t ' ; $ t h i s - > t a s k s = a r r a y ( $ t a s k ) ; }
  12. FIRST WRITE A TEST # s r c / A

    c m e / T a s k B u n d l e / T e s t s / C o n t r o l l e r / T a s k C o n t r o l l e r T e s t . p h p . . . p u b l i c f u n c t i o n t e s t G e t N o t e ( ) { $ c l i e n t = s t a t i c : : c r e a t e C l i e n t ( ) ; $ c l i e n t - > r e q u e s t ( ' G E T ' , ' / t a s k s / 0 . j s o n ' ) ; $ r e s p o n s e = $ c l i e n t - > g e t R e s p o n s e ( ) ; $ t h i s - > a s s e r t J s o n H e a d e r ( $ r e s p o n s e ) ; $ t h i s - > a s s e r t E q u a l s ( 2 0 0 , $ r e s p o n s e - > g e t S t a t u s C o d e ( ) , $ r e s p o n s e - > g e t C o n t e n t ( ) ) ; $ t h i s - > a s s e r t E q u a l s ( ' { " t i t l e " : " P u t " , " d e s c r i p t i o n " : " a d d p u t a c t i o n " } ' , $ r e s p o n s e - > g e t C o n t e n t ( ) ) ; }
  13. IMPLEMENTATION # s r c / A c m e

    / T a s k B u n d l e / C o n t r o l l e r / T a s k C o n t r o l l e r . p h p . . . / * * * @ A p i D o c ( * r e s o u r c e = t r u e , * d e s c r i p t i o n = " g e t t a s k b y i d " * ) * * @ A n n o t a t i o n s \ V i e w ( ) * / p u b l i c f u n c t i o n g e t T a s k A c t i o n ( $ i d ) { r e t u r n $ t h i s - > t a s k s [ $ i d ] ; }
  14. CHECK THE RESULT JSON XML [ { " t i

    t l e " : " P u t " , " d e s c r i p t i o n " : " a d d p u t a c t i o n " } ] < ? x m l v e r s i o n = " 1 . 0 " e n c o d i n g = " U T F - 8 " ? > < t a s k > < t i t l e > < ! [ C D A T A [ P u t ] ] > < / t i t l e > < d e s c r i p t i o n > < ! [ C D A T A [ a d d p u t a c t i o n ] ] > < / d e s c r i p t i o n > < s e c r e t > < ! [ C D A T A [ t o p s e c r e t ] ] > < / s e c r e t > < / t a s k >
  15. SERIALIZER GROUPS display description only on getNoteAction # s r

    c / A c m e / T a s k B u n d l e / R e s o u r c e s / c o n f i g / s e r i a l i z e r / M o d e l . T a s k . y m l A c m e \ T a s k B u n d l e \ M o d e l \ T a s k : . . . p r o p e r t i e s : t i t l e : . . . g r o u p s : [ l i s t , s h o w ] d e s c r i p t i o n : . . . g r o u p s : [ s h o w ] # s r c / A c m e / T a s k B u n d l e / C o n t r o l l e r / T a s k C o n t r o l l e r . p h p . . . / * * * @ A n n o t a t i o n s \ V i e w ( s e r i a l i z e r G r o u p s = { " s h o w " } ) * /
  16. FILTER RESULTS add more examples to the constructor use the

    param fetcher # s r c / A c m e / T a s k B u n d l e / C o n t r o l l e r / T a s k C o n t r o l l e r . p h p / * * * @ A n n o t a t i o n s \ Q u e r y P a r a m ( n a m e = " l a s t I d " , r e q u i r e m e n t s = " \ d + " , * n u l l a b l e = t r u e , d e s c r i p t i o n = " L a s t i d f r o m p r e v i o u s c a l l . " ) * @ A n n o t a t i o n s \ Q u e r y P a r a m ( n a m e = " l i m i t " , r e q u i r e m e n t s = " \ d + " , * d e f a u l t = " 5 " , d e s c r i p t i o n = " H o w m a n y r e c o r d s . " ) * / p u b l i c f u n c t i o n g e t T a s k s A c t i o n ( P a r a m F e t c h e r I n t e r f a c e $ p a r a m F e t c h e r ) { $ s t a r t = 0 ; i f ( n u l l ! = = $ l a s t I d = $ p a r a m F e t c h e r - > g e t ( ' l a s t I d ' ) ) { $ s t a r t = $ l a s t I d ; } $ l i m i t = $ p a r a m F e t c h e r - > g e t ( ' l i m i t ' ) ; r e t u r n a r r a y _ s l i c e ( $ t h i s - > t a s k s , + + $ s t a r t , $ l i m i t , t r u e ) ; }
  17. API SECURITY Basic auth with htaccess (see ) Advanced Symfony2

    Security Config # a p p / c o n f i g / s e c u r i t y . y m l . . . s e c u r i t y : p r o v i d e r s : i n _ m e m o r y : m e m o r y : u s e r s : u s e r : { p a s s w o r d : u s e r p a s s , r o l e s : [ ' R O L E _ U S E R ' ] } . . . f i r e w a l l s : a p i : p a t t e r n : ^ / a p i s e c u r i t y : t r u e h t t p _ b a s i c : r e a l m : " A P I S e c u r e d A r e a " FOSOAuthServerBundle
  18. HATEOAS WHAT? add id attribute to model use existing FSCHateoasBundle

    # s r c / A c m e / T a s k B u n d l e / R e s o u r c e s / c o n f i g / h a t e o a s / M o d e l . T a s k . y m l A c m e \ T a s k B u n d l e \ M o d e l \ T a s k : r e l a t i o n s : s e l f : r e l : s e l f h r e f : r o u t e : g e t _ t a s k p a r a m e t e r s : { " i d " : " . i d " } t a s k s : r e l : t a s k s h r e f : r o u t e : g e t _ t a s k s
  19. CHECK THE RESULT JSON XML [ { " t i

    t l e " : " P u t " , " l i n k s " : { " s e l f " : { " h r e f " : " h t t p : / / w o r k s p a c e . l o c a l / s y m f o n y - r e s t - e d i t i o n / w e b / a p p _ d e v . p h p / t a s k s / 0 " } , " t a s k s " : { " h r e f " : " h t t p : / / w o r k s p a c e . l o c a l / s y m f o n y - r e s t - e d i t i o n / w e b / a p p _ d e v . p h p / t a s k s " } } } ] < ? x m l v e r s i o n = " 1 . 0 " e n c o d i n g = " U T F - 8 " ? > < t a s k > < t i t l e > < ! [ C D A T A [ P u t ] ] > < / t i t l e > < l i n k r e l = " s e l f " h r e f = " h t t p : / / l o c a l h o s t / a p p _ d e v . p h p / t a s k s / 0 " > < l i n k r e l = " t a s k s " h r e f = " h t t p : / / l o c a l h o s t / a p p _ d e v . p h p / t a s k s " > < / t a s k >
  20. LINKS Knp Bundles REST Edition Demo Symfony2 Security Config FOSOAuthBundle

    FSCHateoasBundle http://knpbundles.com/ https://github.com/gimler/symfony-rest-edition http://localhost/app_dev.php http://symfony.com/doc/2.0/reference/configuration/security.htm https://github.com/FriendsOfSymfony/FOSOAuthServerBundle/ https://github.com/TheFootballSocialClub/FSCHateoasBundle