In this talk I’m going to explain how Event Sourcing can help you solve this problem and what other benefits you can get from it.
We will walk over of the concepts and possible implementations of event sourcing.
Keep track of revocations account_id app_id datetime 75623 8 2015-01-01T00:00:00+0000 75623 8 2015-01-27T18:54:18+0000 Are you going to do this for all actions on accounts?
You normally might do it like this < ? p h p / / C o m p a n y . p h p p u b l i c f u n c t i o n _ _ c o n s t r u c t ( $ i d , $ n a m e ) { $ t h i s - > i d = $ i d ; $ t h i s - > n a m e = $ n a m e ; }
< ? p h p / / C o m p a n y . p h p p u b l i c s t a t i c f u n c t i o n r e g i s t e r ( $ i d , $ n a m e ) { $ c o m p a n y = n e w C o m p a n y ( ) ; $ c o m p a n y - > a p p l y ( n e w C o m p a n y R e g i s t e r e d E v e n t ( $ i d , $ n a m e ) ) ; r e t u r n $ c o m p a n y ; }
Record the events < p h p / / A g g r e g a t e R o o t . p h p p u b l i c f u n c t i o n a p p l y ( $ e v e n t ) { $ t h i s - > h a n d l e ( $ e v e n t ) ; $ t h i s - > u n c o m m i t e d E v e n t s [ ] = $ e v e n t ; } p r i v a t e f u n c t i o n h a n d l e ( $ e v e n t ) { $ c l a s s P a r t s = e x p l o d e ( ' \ \ ' , $ e v e n t ) ; $ m e t h o d = ' a p p l y ' . e n d ( $ c l a s s P a r t s ) ; $ t h i s - > $ m e t h o d ( $ e v e n t ) ; }
/ / C o m p a n y . p h p p u b l i c f u n c t i o n a p p l y C o m p a n y R e g i s t e r e d E v e n t ( C o m p a n y R e g i s t e r e d E v e n t $ e v e n t ) { $ t h i s - > c o m p a n y I d = $ e v e n t - > g e t C o m p a n y I d ( ) ; $ t h i s - > c o m p a n y N a m e = $ e v e n t - > g e t C o m p a n y N a m e ( ) ; }
< p h p / / C o m p a n y R e p o s i t o r y . p h p f u n c t i o n l o a d ( $ a g g r e g a t e I d ) { $ e v e n t s = $ t h i s - > e v e n t S t o r e - > l o a d ( $ a g g r e g a t e I d ) ; $ a g g r e g a t e = n e w $ t h i s - > a g g r e g a t e C l a s s ( ) ; $ a g g r e g a t e - > i n i t i a l i z e S t a t e ( $ e v e n t s ) ; r e t u r n $ a g g r e g a t e ; }
< ? p h p / / C o m p a n y . p h p p u b l i c f u n c t i o n i n i t i a l i z e S t a t e ( a r r a y $ e v e n t s ) { f o r e a c h ( $ e v e n t s a s $ e v e n t ) { $ t h i s - > h a n d l e ( $ e v e n t ) ; } }
Should contain everything It should only depend on previous events f i n a l c l a s s C o m p a n y R e g i s t e r e d E v e n t { p r i v a t e $ c o m p a n y I d ; p r i v a t e $ c o m p a n y N a m e ; / / c o n s t r u c t o r + g e t t e r s }
CompanyRegistered / / C o m p a n y f u n c t i o n a p p l y C o m p a n y R e g i s t e r e d E v e n t ( C o m p a n y R e g i s t e r e d E v e n t $ e v e n t ) { $ t h i s - > c o m p a n y I d = $ e v e n t - > g e t C o m p a n y I d ( ) ; }
AccountConnected / / C o m p a n y f u n c t i o n a p p l y A c c o u n t C o n n e c t e d E v e n t ( A c c o u n t C o n n e c t e d E v e n t $ e v e n t ) { $ i d = $ e v e n t - > g e t A c c o u n t I d ( ) ; $ t h i s - > a c c o u n t s [ $ i d ] = $ i d ; }
AppEnabled / / C o m p a n y f u n c t i o n a p p l y A p p E n a b l e d E v e n t ( A p p E n a b l e d E v e n t $ e v e n t ) { $ s u b s c r i p t i o n = n e w S u b s c r i p t i o n ( $ e v e n t - > g e t C o m p a n y I d ( ) , $ e v e n t - > g e t A p p I d ( ) ) ; $ t h i s - > s u b s c r i p t i o n s [ $ e v e n t - > g e t A p p I d ( ) ] = $ s u b s c r i p t i o n ; }
AccessGrantedToApp / / C o m p a n y p r o t e c t e d f u n c t i o n g e t C h i l d E n t i t i e s ( ) { r e t u r n $ t h i s - > s u b s c r i p t i o n s ; } / / S u b s c r i p t i o n f u n c t i o n a p p l y A c c e s s G r a n t e d T o A p p E v e n t ( A c c e s s G r a n t e d T o A p p E v e n t $ e v e n t ) { i f ( $ t h i s - > a p p I d ! = = $ e v e n t - > g e t A p p I d ( ) ) { r e t u r n ; } $ a c c o u n t I d = $ e v e n t - > g e t A c c o u n t I d ( ) ; $ t h i s - > g r a n t e d A c c o u n t s [ $ a c c o u n t I d ] = $ a c c o u n t I d ; }
CompanyRegistration c l a s s C o m p a n y R e g i s t r a t i o n i m p l e m e n t s R e a d M o d e l { p u b l i c f u n c t i o n _ _ c o n s t r u c t ( $ c o m p a n y I d , $ c o m p a n y N a m e , D a t e T i m e $ r e g i s t e r e d O n ) { / / . . } }
Company Registration Projector c l a s s C o m p a n y R e g i s t r a t i o n P r o j e c t o r i m p l e m e n t s E v e n t L i s t e n e r { p u b l i c f u n c t i o n a p p l y C o m p a n y R e g i s t e r e d E v e n t ( C o m p a n y R e g i s t e r e d E v e n t $ e v e n t , D o m a i n M e s s a g e $ d o m a i n M e s s a g e ) { $ c o m p a n y = n e w C o m p a n y R e g i s t r a t i o n ( $ e v e n t - > g e t C o m p a n y I d ( ) , $ e v e n t - > g e t C o m p a n y N a m e ( ) , $ d o m a i n M e s s a g e - > g e t R e c o r d e d O n ( ) ) ; $ t h i s - > r e p o s i t o r y - > s a v e ( $ c o m p a n y ) ; } }
The ability to create multiple read models List of company registrations Graph of all connections between companies and accounts Creating reports about the amount of revocations
From Controller to CommandBus c l a s s C o m p a n y C o n t r o l l e r { f u n c t i o n r e g i s t e r A c t i o n ( R e q u e s t $ r e q u e s t ) { $ t h i s - > c o m m a n d B u s - > d i s p a t c h ( n e w R e g i s t e r C o m p a n y C o m m a n d ( U u i d : : u u i d 4 ( ) , $ r e q u e s t - > r e q u e s t - > g e t ( ' c o m p a n y N a m e ' ) ) ) ; } }
From CommandHandler to Aggregate c l a s s C o m p a n y C o m m a n d H a n d l e r { f u n c t i o n h a n d l e R e g i s t e r C o m p a n y C o m m a n d ( R e g i s t e r C o m p a n y C o m m a n d $ c o m m a n d ) { $ c o m p a n y = C o m p a n y : : r e g i s t e r ( $ c o m m a n d - > g e t C o m p a n y I d ( ) , $ c o m m a n d - > g e t C o m p a n y N a m e ( ) ) ; $ t h i s - > a g g r e g a t e R e p o s t i t o r y - > s a v e ( $ c o m p a n y ) ; } }
From Aggregate to Event p u b l i c s t a t i c f u n c t i o n r e g i s t e r ( $ c o m p a n y I d , $ n a m e ) { $ c o m p a n y = n e w C o m p a n y ( ) ; $ c o m p a n y - > a p p l y ( n e w C o m p a n y R e g i s t e r e d E v e n t ( $ c o m p a n y I d , $ n a m e ) ) ; r e t u r n $ c o m p a n y ; } p u b l i c f u n c t i o n a p p l y C o m p a n y R e g i s t e r e d E v e n t ( C o m p a n y R e g i s t e r e d E v e n t $ e v e n t ) { $ t h i s - > c o m p a n y I d = $ e v e n t - > g e t C o m p a n y I d ( ) ; }
From Repository to EventStore / / C o m p a n y R e g i s t r y . p h p f u n c t i o n s a v e ( $ a g g r e g a t e ) { $ e v e n t s = $ a g g r e g a t e - > g e t U n c o m m i t t e d E v e n t s ( ) ; $ t h i s - > e v e n t S t o r e - > a p p e n d ( $ a g g r e g a t e - > g e t A g g r e g a t e I d ( ) , $ e v e n t s ) ; $ t h i s - > e v e n t B u s - > p u b l i s h ( $ e v e n t s ) ; }
From event to read model c l a s s C o m p a n y R e g i s t r a t i o n P r o j e c t o r { p u b l i c f u n c t i o n a p p l y C o m p a n y R e g i s t e r e d E v e n t ( C o m p a n y R e g i s t e r e d E v e n t $ e v e n t , D o m a i n M e s s a g e $ d o m a i n M e s s a g e ) { $ c o m p a n y = n e w C o m p a n y R e g i s t r a t i o n ( $ e v e n t - > g e t C o m p a n y I d ( ) , $ e v e n t - > g e t C o m p a n y N a m e ( ) , $ d o m a i n M e s s a g e - > g e t R e c o r d e d O n ( ) ) ; $ t h i s - > r e p o s i t o r y - > s a v e ( $ c o m p a n y ) ; } }
Test your Command Handler $ t h i s - > s c e n a r i o - > g i v e n ( [ n e w C o m p a n y R e g i s t e r e d E v e n t ( 1 2 3 ) ] ) - > w h e n ( n e w E n a b l e A p p F o r C o m p a n y C o m m a n d ( 4 2 , 1 2 3 ) ) - > t h e n ( [ n e w A p p E n a b l e d E v e n t ( 4 2 , 1 2 3 ) ] ) ;
Or your aggregate $ t h i s - > s c e n a r i o - > g i v e n ( [ n e w C o m p a n y R e g i s t e r e d E v e n t ( 1 2 3 ) ] ) - > w h e n ( f u n c t i o n ( $ c o m p a n y ) { $ c o m p a n y - > e n a b l e A p p ( 4 2 ) ; } ) - > t h e n ( [ n e w A p p E n a b l e d E v e n t ( 4 2 , 1 2 3 ) ] ) ;
Don't forget your read models $ t h i s - > s c e n a r i o - > g i v e n ( [ ] ) - > w h e n ( n e w C o m p a n y R e g i s t e r e d E v e n t ( 1 2 3 , ' A c m e I n c ' ) ) - > t h e n ( [ n e w C o m p a n y R e g i s t r a t i o n ( 1 2 3 , ' A c m e I n c ' ) ] ) ;