рдкреЗрд╢реЗрд╡рд░ рдкрд╛рдареНрдпрдХреНрд░рдо "рдлреНрд░реЗрдорд╡рд░реНрдХ рд▓рд╛рд░рд╡реЗрд▓" рдХреЗ рдЫрд╛рддреНрд░реЛрдВ рдХреЗ рд▓рд┐рдП рд▓реЗрдЦ рдХрд╛ рдЕрдиреБрд╡рд╛рдж рддреИрдпрд╛рд░ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ред

рдкрд░рд┐рдЪрдп
рдпрд╣ рд▓реЗрдЦ PHP рднрд╛рд╖рд╛ рдФрд░ рд▓рд╛рд░реНрд╡реЗрд▓ рдврд╛рдВрдЪреЗ рдореЗрдВ рдШрдЯрдирд╛ CQRS- рд╕рд┐рд╕реНрдЯрдо рдмрдирд╛рдиреЗ рдХреА рдореВрд▓ рдмрд╛рддреЗрдВ рдХреЗ рд▓рд┐рдП рд╕рдорд░реНрдкрд┐рдд рд╣реИред рдпрд╣ рдорд╛рдирд╛ рдЬрд╛рддрд╛ рд╣реИ рдХрд┐ рдЖрдк рдХрдорд╛рдВрдб рдмрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд╡рд┐рдХрд╛рд╕ рдпреЛрдЬрдирд╛ рд╕реЗ рдкрд░рд┐рдЪрд┐рдд рд╣реИрдВ рдФрд░ рдЗрд╕рдореЗрдВ рдШрдЯрдирд╛рдУрдВ рдХрд╛ рдПрдХ рд╡рд┐рдЪрд╛рд░ рд╣реИ (рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ, рд╢реНрд░реЛрддрд╛рдУрдВ рдХреА рдПрдХ рд╕рд░рдгреА рдХреЗ рд▓рд┐рдП рдШрдЯрдирд╛рдУрдВ рдХрд╛ рдкреНрд░рдХрд╛рд╢рди)ред рдЗрд╕ рдЬреНрдЮрд╛рди рдХреЛ рддрд╛рдЬрд╝рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдк рд▓реИрд░рд╛рдХреИрдЯреНрд╕ рд╕реЗрд╡рд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдпрд╣ рдорд╛рдирд╛ рдЬрд╛рддрд╛ рд╣реИ рдХрд┐ рдЖрдкрдХреЛ CQRS рд╕рд┐рджреНрдзрд╛рдВрдд рдХреА рдПрдХ рдирд┐рд╢реНрдЪрд┐рдд рд╕рдордЭ рд╣реИред рдпрджрд┐ рдирд╣реАрдВ, рддреЛ рдореИрдВ рдЕрддреНрдпрдзрд┐рдХ рджреЛ рд╡реНрдпрд╛рдЦреНрдпрд╛рди рд╕реБрдирдиреЗ рдХреА рд╕рд▓рд╛рд╣ рджреЗрддрд╛ рд╣реВрдВ:
рдЗрд╡реЗрдВрдЯ рдЬрдирд░реЗрд╢рди рдФрд░
рдЧреНрд░реЗрдЧ рдпрдВрдЧ рдХреЗ CQRS рдФрд░ рдЗрд╡реЗрдВрдЯ рдЬрдирд░реЗрд╢рди рдкрд░ рдореИрдерд┐рдпрд╛рд╕ рд╡реЗрд░реЗрдЬ рд╡рд░реНрдХрд╢реЙрдк ред
рдЕрдкрдиреА рдкрд░рд┐рдпреЛрдЬрдирд╛рдУрдВ рдореЗрдВ рдпрд╣рд╛рдВ рджрд┐рдП рдЧрдП рдХреЛрдб рдХрд╛ рдЙрдкрдпреЛрдЧ рди рдХрд░реЗрдВ! рдпрд╣ CQRS рдХреЗ рдкреАрдЫреЗ рдХреЗ рд╡рд┐рдЪрд╛рд░реЛрдВ рдХреЛ рд╕рдордЭрдиреЗ рдХрд╛ рдПрдХ рд╕реАрдЦрдиреЗ рдХрд╛ рдордВрдЪ рд╣реИред рдЗрд╕ рдХреЛрдб рдХреЛ рд╡рд┐рд╢реНрд╡рд╕рдиреАрдп рдирд╣реАрдВ рдХрд╣рд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рдЗрд╕рдХрд╛ рдЦрд░рд╛рдм рдкрд░реАрдХреНрд╖рдг рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рдФрд░ рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдореИрдВ рд╢рд╛рдпрдж рд╣реА рдХрднреА рдкреНрд░реЛрдЧреНрд░рд╛рдо рдЗрдВрдЯрд░рдлреЗрд╕ рдХрд░рддрд╛ рд╣реВрдВ, рдЗрд╕рд▓рд┐рдП рдХреЛрдб рдХреЗ рдЕрд▓рдЧ-рдЕрд▓рдЧ рд╣рд┐рд╕реНрд╕реЛрдВ рдХреЛ рдмрджрд▓рдирд╛ рдмрд╣реБрдд рдореБрд╢реНрдХрд┐рд▓ рд╣реЛрдЧрд╛ред CQRS рдкреИрдХреЗрдЬ рдХрд╛ рдПрдХ рдмреЗрд╣рддрд░ рдЙрджрд╛рд╣рд░рдг рдЖрдк рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ,
рдмреНрд░реЙрдбрд╡реЗ рд╣реИ, рдЬреЛ Qandidate Lab рджреНрд╡рд╛рд░рд╛ рд╡рд┐рдХрд╕рд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ ред рдпрд╣ рд╕рд╛рдл, рд╢рд┐рдерд┐рд▓ рдпреБрдЧреНрдорд┐рдд рдХреЛрдб рд╣реИ, рд╣рд╛рд▓рд╛рдВрдХрд┐, рдХреБрдЫ рд╕рд╛рд░ рдпрд╣ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рд╕реНрдкрд╖реНрдЯ рдирд╣реАрдВ рдХрд░рддреЗ рд╣реИрдВ рдпрджрд┐ рдЖрдкрдиреЗ рдХрднреА рдЗрд╡реЗрдВрдЯ рд╕рд┐рд╕реНрдЯрдо рдХрд╛ рд╕рд╛рдордирд╛ рдирд╣реАрдВ рдХрд┐рдпрд╛ рд╣реИред
рдФрд░ рдЖрдЦрд┐рд░реА - рдореЗрд░рд╛ рдХреЛрдб рдШрдЯрдирд╛рдУрдВ рдФрд░ рд▓рд╛рд░рд╡реЗрд▓ рдХрдорд╛рдВрдб рдмрд╕ рд╕реЗ рдЬреБрдбрд╝рд╛ рд╣реБрдЖ рд╣реИред рдореИрдВ рдпрд╣ рджреЗрдЦрдирд╛ рдЪрд╛рд╣рддрд╛ рдерд╛ рдХрд┐ рд▓рд╛рд░рд╡реЗрд▓ рдореЗрдВ рдХреЛрдб рдХреИрд╕реЗ рджрд┐рдЦреЗрдЧрд╛ (рдореИрдВ рдЖрдорддреМрд░ рдкрд░ рдЫреЛрдЯреА рдПрдЬреЗрдВрд╕рд┐рдпреЛрдВ рдХреА рдкрд░рд┐рдпреЛрдЬрдирд╛рдУрдВ рдХреЗ рд▓рд┐рдП рдЗрд╕ рдврд╛рдВрдЪреЗ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реВрдВ), рд╣рд╛рд▓рд╛рдВрдХрд┐, рдкреАрдЫреЗ рдореБрдбрд╝рдХрд░ рджреЗрдЦрддрд╛ рд╣реВрдВ, рддреЛ рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдореБрдЭреЗ рдЕрдкрдирд╛ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдмрдирд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред рдореБрдЭреЗ рдЙрдореНрдореАрдж рд╣реИ рдХрд┐ рдореЗрд░рд╛ рдХреЛрдб рдЙрди рд▓реЛрдЧреЛрдВ рдХреЗ рд▓рд┐рдП рднреА рд╕реНрдкрд╖реНрдЯ рд╣реЛрдЧрд╛ рдЬреЛ рдлреНрд░реЗрдорд╡рд░реНрдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд░рддреЗ рд╣реИрдВред
Github рдкрд░, рдХреЛрдб
https://github.com/scazz/cqrs-tutorial.git рдкрд░ рд╕реНрдерд┐рдд рд╣реИ, рдФрд░ рд╣рдорд╛рд░реЗ рдЧрд╛рдЗрдб рдореЗрдВ рд╣рдо рддрд░реНрдХ рдмрдврд╝рд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдЗрд╕рдХреЗ рдШрдЯрдХреЛрдВ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВрдЧреЗред
рд╣рдо рдПрдХ рд╕рд░реНрдл рд╕реНрдХреВрд▓ рдХреЗ рд▓рд┐рдП рдПрдХ рдкреНрд░рд╛рд░рдВрднрд┐рдХ рдкрдВрдЬреАрдХрд░рдг рдкреНрд░рдгрд╛рд▓реА рдмрдирд╛рдПрдВрдЧреЗред рдЗрд╕рдХреА рдорджрдж рд╕реЗ, рд╕реНрдХреВрд▓ рдЧреНрд░рд╛рд╣рдХ рдХрдХреНрд╖рд╛рдУрдВ рдХреЗ рд▓рд┐рдП рдкрдВрдЬреАрдХрд░рдг рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рд░рд┐рдХреЙрд░реНрдбрд┐рдВрдЧ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреЗ рд▓рд┐рдП, рд╣рдо рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдирд┐рдпрдо рдмрдирд╛рддреЗ рд╣реИрдВ:
- рдкреНрд░рддреНрдпреЗрдХ рдкрд╛рда рдореЗрдВ рдХрдо рд╕реЗ рдХрдо рдПрдХ рдЧреНрд░рд╛рд╣рдХ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП ...
- ... рд▓реЗрдХрд┐рди рддреАрди рд╕реЗ рдЬреНрдпрд╛рджрд╛ рдирд╣реАрдВред
рдЗрд╡реЗрдВрдЯ-рдЖрдзрд╛рд░рд┐рдд CQRS рд╕рд┐рд╕реНрдЯрдо рдХреА рд╕рдмрд╕реЗ рдкреНрд░рднрд╛рд╡рд╢рд╛рд▓реА рд╡рд┐рд╢реЗрд╖рддрд╛рдУрдВ рдореЗрдВ рд╕реЗ рдПрдХ рд╣реИ рд╕рд┐рд╕реНрдЯрдо рд╕реЗ рдЖрд╡рд╢реНрдпрдХ рдкреНрд░рддреНрдпреЗрдХ рдореАрдЯреНрд░рд┐рдХ рдХреЗ рд▓рд┐рдП рд╡рд┐рд╢рд┐рд╖реНрдЯ рд░реАрдбрд┐рдВрдЧ рдореЙрдбрд▓ рдХрд╛ рдирд┐рд░реНрдорд╛рдгред рдЖрдкрдХреЛ ElasticSearch рдореЗрдВ рд░реАрдбрд┐рдВрдЧ рдореЙрдбрд▓ рдХреЗ рдкреНрд░рдХреНрд╖реЗрдкрдг рдХреЗ рдЙрджрд╛рд╣рд░рдг рдорд┐рд▓реЗрдВрдЧреЗ, рдФрд░ рдЧреНрд░реЗрдЧ рдпрдВрдЧ рдиреЗ рдЬрдЯрд┐рд▓ рдШрдЯрдирд╛рдУрдВ рд╕реЗ рдирд┐рдкрдЯрдиреЗ рдХреЗ рд▓рд┐рдП рдЕрдкрдиреЗ рдЗрд╡реЗрдВрдЯ рд╕реНрдЯреЛрд░ рдореЗрдВ рдПрдХ рд╡рд┐рд╖рдп-рдЙрдиреНрдореБрдЦ рднрд╛рд╖рд╛ рдХреЛ рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ рд╣реИред рд╣рд╛рд▓рд╛рдБрдХрд┐, рд╕рд╛рджрдЧреА рдХреЗ рд▓рд┐рдП, рд╣рдорд╛рд░рд╛ рдкрдврд╝рд╛ рд╣реБрдЖ рдкреНрд░рдХреНрд╖реЗрдкрдг рдПрд▓реЛрдХреЗрдВрдЯ рдХреЗ рд╕рд╛рде рдЙрдкрдпреЛрдЧ рдХреЗ рд▓рд┐рдП рдПрдХ рдорд╛рдирдХ SQL рдбреЗрдЯрд╛рдмреЗрд╕ рд╣реЛрдЧрд╛ред рдирддреАрдЬрддрди, рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдХрдХреНрд╖рд╛рдУрдВ рдХреЗ рд▓рд┐рдП рдПрдХ рдЯреЗрдмрд▓ рдФрд░ рдЧреНрд░рд╛рд╣рдХреЛрдВ рдХреЗ рд▓рд┐рдП рдПрдХ рд╣реЛрдЧрд╛ред
рдЗрд╡реЗрдВрдЯ рдЬрдирд░реЗрд╢рди рдХреА рдЕрд╡рдзрд╛рд░рдгрд╛ рдЖрдкрдХреЛ рдШрдЯрдирд╛рдУрдВ рдХреЛ рдСрдлрд╝рд▓рд╛рдЗрди рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддреА рд╣реИред рд▓реЗрдХрд┐рди рдЗрд╕ рд▓реЗрдЦ рдореЗрдВ рдореИрдВ "рдкрд╛рд░рдВрдкрд░рд┐рдХ" рд╡рд┐рдХрд╛рд╕ рдореЙрдбрд▓ рдХреЛ рдЕрдзрд┐рдХрддрдо (рдлрд┐рд░ рд╕реЗ, рд╕рд░рд▓ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП) рдХрд╛ рдкрд╛рд▓рди рдХрд░реВрдВрдЧрд╛, рдФрд░ рд╣рдорд╛рд░реЗ рдкрдврд╝рдиреЗ рдХреЗ рдЕрдиреБрдорд╛рдиреЛрдВ рдХреЛ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рд╕рдордп рдореЗрдВ рдЕрдкрдбреЗрдЯ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛, рдШрдЯрдирд╛рдУрдВ рдХреЗ рднрдВрдбрд╛рд░ рдореЗрдВ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд┐рдП рдЬрд╛рдиреЗ рдХреЗ рддреБрд░рдВрдд рдмрд╛рджред
рдкреНрд░реЛрдЬреЗрдХреНрдЯ рд╕реЗрдЯрдЕрдк рдФрд░ рдкрд╣рд▓рд╛ рдкрд░реАрдХреНрд╖рдг
git clone https://github.com/scazz/cqrs-tutorial
рдПрдХ рдирдпрд╛ Laravel 5 рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдмрдирд╛рдПрдВ
$> laravel new cqrs-tutorial
рдФрд░ рд╢реБрд░реБрдЖрдд рдХреЗ рд▓рд┐рдП, рд╣рдореЗрдВ рдПрдХ рдкрд░реАрдХреНрд╖рдг рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рд╣рдо рдПрдХреАрдХрд░рдг рдкрд░реАрдХреНрд╖рдг рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗ, рдЬреЛ рдпрд╣ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░реЗрдЧрд╛ рдХрд┐ рдХрдХреНрд╖рд╛рдУрдВ рдХреЗ рд▓рд┐рдП рдЧреНрд░рд╛рд╣рдХ рдХрд╛ рдкрдВрдЬреАрдХрд░рдг рдЗрд╕ рддрдереНрдп рдХреА рдУрд░ рдЬрд╛рддрд╛ рд╣реИ рдХрд┐ рд╕рдмрдХ рд╣рдорд╛рд░реЗ рдПрд▓реЛрдХреЗрдВрдЯ рдореЙрдбрд▓ рдореЗрдВ рдмрдирд╛рдпрд╛ рдЧрдпрд╛ рд╣реИред
рд▓рд┐рд╕реНрдЯрд┐рдВрдЧ рдкрд░реАрдХреНрд╖рдг / CQRSTest.php:
use Illuminate\Foundation\Bus\DispatchesCommands; class CQRSTest extends TestCase { use DispatchesCommands;
/** * , BookLesson * @return void */ public function testFiringEventUpdatesReadModel() { $testLessonId = '123e4567-e89b-12d3-a456-426655440000'; $clientName = "George"; $lessonId = new LessonId($testLessonId); $command = new BookLesson($lessonId, $clientName); $this->dispatch($command); $this->assertNotNull(Lesson::find($testLessonId)); $this->assertEquals( Lesson::find($testLessonId)->clientName, $clientName ); } }
рд╣рдо рдПрдХ рдЖрдИрдбреА рдХреЗ рд▓рд┐рдП рдирдИ рдЧрддрд┐рд╡рд┐рдзрд┐ рдХрд╛ рдкреНрд░рдЪрд╛рд░ рдХрд░рддреЗ рд╣реИрдВ, рдПрдХ рдирдИ рдЧрддрд┐рд╡рд┐рдзрд┐ рдХреЗ рд▓рд┐рдП рд╕рд╛рдЗрди рдЕрдк рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдЯреАрдо рдмрдирд╛рддреЗ рд╣реИрдВ, рдФрд░ рд▓рд╛рд░рд╡реЗрд▓ рдХреЛ рдЗрд╕реЗ рднреЗрдЬрдиреЗ рдХреЗ рд▓рд┐рдП рдХрд╣рддреЗ рд╣реИрдВред рдкрд╛рда рддрд╛рд▓рд┐рдХрд╛ рдореЗрдВ, рд╣рдореЗрдВ рдПрдХ рдирдпрд╛ рд░рд┐рдХреЙрд░реНрдб рдмрдирд╛рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рдЬрд┐рд╕реЗ рд╣рдо рдПрд▓реЛрдХреЗрдВрдЯ рдореЙрдбрд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдкрдврд╝ рд╕рдХрддреЗ рд╣реИрдВред рд╣рдореЗрдВ рдПрдХ рдбреЗрдЯрд╛рдмреЗрд╕ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдЕрдкрдиреА .env рдлрд╝рд╛рдЗрд▓ рдХреЛ рдареАрдХ рд╕реЗ рднрд░реЗрдВред
рд╣рдорд╛рд░реЗ рдИрд╡реЗрдВрдЯ рд╕реНрдЯреЛрд░ рдореЗрдВ рджрд░реНрдЬ рдкреНрд░рддреНрдпреЗрдХ рдШрдЯрдирд╛ рдПрдЧреНрд░реАрдЧреЗрдЯ рдХреА рдЬрдбрд╝ рд╕реЗ рдЬреБрдбрд╝реА рд╣реЛрддреА рд╣реИ, рдЬрд┐рд╕реЗ рд╣рдо рдмрд╕ рдЗрдХрд╛рдИ (рдЗрдХрд╛рдИ) рдХрд╣реЗрдВрдЧреЗ - рд╢реИрдХреНрд╖рд┐рдХ рдЙрджреНрджреЗрд╢реНрдпреЛрдВ рдХреЗ рд▓рд┐рдП рдПрдХ рдЕрдореВрд░реНрддрддрд╛ рдХреЗрд╡рд▓ рднреНрд░рдо рдкреИрджрд╛ рдХрд░рддреА рд╣реИред рдЖрдИрдбреА рдПрдХ рд╕рд╛рд░реНрд╡рднреМрдорд┐рдХ рд╡рд┐рд╢рд┐рд╖реНрдЯ рдкрд╣рдЪрд╛рдирдХрд░реНрддрд╛ (UUID) рд╣реИред рдпрджрд┐ рдИрд╡реЗрдВрдЯ рдкрд╛рда рдпрд╛ рдХреНрд▓рд╛рдЗрдВрдЯ рдкрд░ рд▓рд╛рдЧреВ рд╣реЛрддрд╛ рд╣реИ рддреЛ рдИрд╡реЗрдВрдЯ рд╕реНрдЯреЛрд░ рдзреНрдпрд╛рди рдирд╣реАрдВ рд░рдЦрддрд╛ рд╣реИред рд╡рд╣ рдХреЗрд╡рд▓ рдпрд╣ рдЬрд╛рдирддрд╛ рд╣реИ рдХрд┐ рдпрд╣ рдПрдХ рдЖрдИрдбреА рд╕реЗ рдЬреБрдбрд╝рд╛ рд╣реИред
рдкрд░реАрдХреНрд╖рдг рдХреЗ рджреМрд░рд╛рди рдкрд╣рдЪрд╛рдиреА рдЧрдИ рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЗ рдЖрдзрд╛рд░ рдкрд░, рд╣рдо рд▓рд╛рдкрддрд╛ рдХрдХреНрд╖рд╛рдПрдВ рдмрдирд╛ рд╕рдХрддреЗ рд╣реИрдВред рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рд╣рдо рд▓реЗрд╕рдиреЙрдЗрдб рдХреНрд▓рд╛рд╕ рдмрдирд╛рдПрдВрдЧреЗ, рдлрд┐рд░ рдмреБрдХрд▓реИрд╕рди рдХрдорд╛рдВрдб (рд╣реИрдВрдбрд▓рд░ рд╡рд┐рдзрд┐ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЕрднреА рддрдХ рдЪрд┐рдВрддрд╛ рди рдХрд░реЗрдВ, рдмрд╕ рдкрд░реАрдХреНрд╖рдг рдЪрд▓рд╛рдирд╛ рдЬрд╛рд░реА рд░рдЦреЗрдВ)ред рд▓реЗрд╕рди рдХреНрд▓рд╛рд╕, рд▓реЗрд╕рд╕рди рдиреЗрдорд╕реНрдкреЗрд╕ рдХреЗ рдмрд╛рд╣рд░ рдПрдХ рд░реАрдбрд┐рдВрдЧ рдореЙрдбрд▓ рд╣реИред рдПрдХ рд╡рд┐рд╢реЗрд╖ рд░реАрдбрд┐рдВрдЧ рдореЙрдбрд▓ - рд╡рд┐рд╖рдп рдХреНрд╖реЗрддреНрд░ рдХрд╛ рддрд░реНрдХ рдпрд╣рд╛рдВ рдХрднреА рд╕рдВрдЧреНрд░рд╣реАрдд рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред рдирд┐рд╖реНрдХрд░реНрд╖ рдореЗрдВ, рд╣рдореЗрдВ рдкрд╛рда рддрд╛рд▓рд┐рдХрд╛ рдХреЗ рд▓рд┐рдП рдПрдХ рдорд╛рдЗрдЧреНрд░реЗрд╢рди рдмрдирд╛рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрдЧреАред
рдХреЛрдб рдХреА рд╕реНрдкрд╖реНрдЯрддрд╛ рдмрдирд╛рдП рд░рдЦрдиреЗ рдХреЗ рд▓рд┐рдП, рдореИрдВ рд╕рддреНрдпрд╛рдкрди рд╕рддреНрдпрд╛рдкрди рдкреБрд╕реНрддрдХрд╛рд▓рдп рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реВрдВрдЧрд╛ред рдЗрд╕реЗ рдирд┐рдореНрди рдХрдорд╛рдВрдб рдХреЗ рд╕рд╛рде рдЬреЛрдбрд╝рд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ:
$> composer require beberlei/assert
рдЗрд╕ рдХрдорд╛рдВрдб рджреНрд╡рд╛рд░рд╛ рд╢реБрд░реВ рдХреА рдЬрд╛рдиреЗ рд╡рд╛рд▓реА рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВ:
- рдорд╛рдиреНрдпрддрд╛: рдЖрд╡рд╢реНрдпрдХ рдЖрджреЗрд╢ рд╡рд┐рдлрд▓ рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВ, рдФрд░ рдШрдЯрдирд╛рдПрдБ рдкрд╣рд▓реЗ рд╣реА рдШрдЯрд┐рдд рд╣реЛ рдЪреБрдХреА рд╣реИрдВ рдФрд░ рдЗрд╕рд▓рд┐рдП рд╡рд┐рдлрд▓ рдирд╣реАрдВ рд╣реЛрдиреА рдЪрд╛рд╣рд┐рдПред
- рдПрдХ рдирдпрд╛ рдкрд╛рда рдмрдирд╛рдПрдБ рдШрдЯрдирд╛ (рдПрдХ рдкрд╛рда рдХреЗ рд▓рд┐рдП рд╕рд╛рдЗрди рдЕрдк)ред
- рдЧрддрд┐рд╡рд┐рдзрд┐ рдХреА рд╕реНрдерд┐рддрд┐ рдЕрдкрдбреЗрдЯ рдХрд░реЗрдВред (рд░рд┐рдХреЙрд░реНрдб рдореЙрдбрд▓ рдХреЛ рдореЙрдбрд▓ рдХреА рд╕реНрдерд┐рддрд┐ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдкрддрд╛ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП рддрд╛рдХрд┐ рд╡рд╣ рд╕рддреНрдпрд╛рдкрди рдХрд░ рд╕рдХреЗред)
- рдЗрд╕ рдШрдЯрдирд╛ рдХреЛ рдЧрддрд┐рд╡рд┐рдзрд┐ рд░рд┐рдХреЙрд░реНрдб рдореЙрдбрд▓ рдореЗрдВ рд╕рдВрдЧреНрд░рд╣реАрдд рдЕрдирдЕрдорд╛рдЗрдВрдб рдЗрд╡реЗрдВрдЯ рдХреА рдзрд╛рд░рд╛ рдореЗрдВ рдЬреЛрдбрд╝реЗрдВред
- рд╕реНрдЯреЛрд░ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЕрдкреНрд░рдХрд╛рд╢рд┐рдд рдШрдЯрдирд╛рдУрдВ рдХреА рдзрд╛рд░рд╛ рдХреЛ рдмрдЪрд╛рдПрдВред
- рдкрд╛рда рддрд╛рд▓рд┐рдХрд╛ рдХреЛ рдЕрджреНрдпрддрди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╕рднреА рдкрдарди рдкреНрд░реЛрдЬреЗрдХреНрдЯрд░реЛрдВ рдХреЛ рд╕реВрдЪрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╡рд┐рд╢реНрд╡ рд╕реНрддрд░ рдкрд░ рд▓реЗрд╕рдиреЙрд╕реНрдХрдмреБрдХ рдХреА рдЧрдИ рдШрдЯрдирд╛ рдЙрдард╛рдПрдБред
рдкрд╣рд▓реЗ рдЖрдкрдХреЛ рдкрд╛рда рдХреЗ рд▓рд┐рдП рдПрдХ рд░рд┐рдХреЙрд░реНрдбрд┐рдВрдЧ рдореЙрдбрд▓ рдмрдирд╛рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рд╣рдо рд╕реНрдереИрддрд┐рдХ рдХрд╛рд░рдЦрд╛рдирд╛ рд╡рд┐рдзрд┐ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗ
Lesson::bookClientOntoNewLesson()
ред рдпрд╣ рдПрдХ рдирдпрд╛
LessonWasOpened
рдИрд╡реЗрдВрдЯ рдЙрддреНрдкрдиреНрди рдХрд░рддрд╛ рд╣реИ (рдкрд╛рда рдЦреБрд▓рд╛ рд╣реИ), рдЗрд╕ рдИрд╡реЗрдВрдЯ рдХреЛ рд╕реНрд╡рдпрдВ рдкрд░ рд▓рд╛рдЧреВ рдХрд░рддрд╛ рд╣реИ (рдмрд╕ рдЕрдкрдиреА рдЖрдИрдбреА рд╕реЗрдЯ рдХрд░рддрд╛ рд╣реИ), рдирдП рдИрд╡реЗрдВрдЯ рдХреЛ
DomainEventMessage
(рдИрд╡реЗрдВрдЯ рдкреНрд▓рд╕ рдХреБрдЫ рдореЗрдЯрд╛рдбреЗрдЯрд╛ рдХреЗ рд░реВрдк рдореЗрдВ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИ рдЬреЛ рд╣рдо рдЗрд╡реЗрдВрдЯ рд╕реНрдЯреЛрд░ рдореЗрдВ рд╕рд╣реЗрдЬрддреЗ рд╕рдордп рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ)ред
рдЗрд╡реЗрдВрдЯ рдореЗрдВ рдХреНрд▓рд╛рдЗрдВрдЯ рдЬреЛрдбрд╝рдиреЗ рдХреЗ рд▓рд┐рдП рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреЛ рджреЛрд╣рд░рд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред
ClientWasBookedOntoLesson
рдИрд╡реЗрдВрдЯ рд▓рд╛рдЧреВ рдХрд░рддреЗ
ClientWasBookedOntoLesson
(рдХреНрд▓рд╛рдЗрдВрдЯ рдХреЛ рдкрд╛рда рдореЗрдВ рдирд╛рдорд╛рдВрдХрд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛), рд░рд┐рдХреЙрд░реНрдбрд┐рдВрдЧ рдореЙрдбрд▓ рдХреНрд▓рд╛рдЗрдВрдЯ рдирд╛рдореЛрдВ рдХреЛ рдЯреНрд░реИрдХ рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдХреЗрд╡рд▓ рдкрдВрдЬреАрдХреГрдд рдЧреНрд░рд╛рд╣рдХреЛрдВ рдХреА рд╕рдВрдЦреНрдпрд╛ред рд░рд┐рдХреЙрд░реНрдб рдореЙрдбрд▓ рдХреЛ рд╕реНрдерд┐рд░рддрд╛ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЧреНрд░рд╛рд╣рдХ рдХреЗ рдирд╛рдо рдЬрд╛рдирдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИред
applyLessonWasOpened
рдФрд░
applyClientWasBookedOntoLesson
рд╡рд┐рдзрд┐рдпрд╛рдВ рдЕрднреА рдереЛрдбрд╝реА рдЕрдЬреАрдм рд▓рдЧ рд╕рдХрддреА рд╣реИрдВред рд╣рдо рдмрд╛рдж рдореЗрдВ рдЙрдирдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗ рдЬрдм рд╣рдореЗрдВ рд░рд┐рдХреЙрд░реНрдбрд┐рдВрдЧ рдореЙрдбрд▓ рдХреА рд╕реНрдерд┐рддрд┐ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдкреБрд░рд╛рдиреА рдШрдЯрдирд╛рдУрдВ рдХреЛ рдкреБрди: рдкреЗрд╢ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрдЧреАред рдпрд╣ рд╕рдордЭрд╛рдирд╛ рдЖрд╕рд╛рди рдирд╣реАрдВ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдореИрдВ рдПрдХ рдХреЛрдб рджреВрдВрдЧрд╛ рдЬреЛ рдЖрдкрдХреЛ рдЗрд╕ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреЛ рд╕рдордЭрдиреЗ рдореЗрдВ рдорджрдж рдХрд░реЗрдЧрд╛ред рдмрд╛рдж рдореЗрдВ рд╣рдо рдЙрд╕ рдХреЛрдб рдХреЛ рдирд┐рдХрд╛рд▓реЗрдВрдЧреЗ рдЬреЛ uncommittedEvents рдХреЛ рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд░рддрд╛ рд╣реИ рдФрд░ рдбреЛрдореЗрди рдИрд╡реЗрдВрдЯ рд╕рдВрджреЗрд╢ рдЙрддреНрдкрдиреНрди рдХрд░рддрд╛ рд╣реИред
app/School/Lesson/Lesson.php public function openLesson( LessonId $lessonId ) { /* , , */ $this->apply( new LessonWasOpened( $lessonId) ); } protected function applyLessonWasOpened( LessonWasOpened $event ) { $this->lessonId = $event->getLessonId(); $this->numberOfClients = 0; } public function bookClient( $clientName ) { if ($this->numberOfClients >= 3) { throw new TooManyClientsAddedToLesson(); } $this->apply( new ClientBookedOntoLesson( $this->lessonId, $clientName) ); } /** * тАФ * , * , , * . */ protected function applyClientBookedOntoLesson( ClientBookedOntoLesson $event ) { $this->numberOfClients++; }
рд╣рдо рдЕрдкрдиреЗ рд░рд┐рдХреЙрд░реНрдбрд┐рдВрдЧ рдореЙрдбрд▓ рд╕реЗ CQRS рдШрдЯрдХреЛрдВ рдХреЛ рдирд┐рдХрд╛рд▓ рд╕рдХрддреЗ рд╣реИрдВ - рдЕрд╕рдореНрдмрджреНрдз рдШрдЯрдирд╛рдУрдВ рдХреЗ рдкреНрд░рд╕рдВрд╕реНрдХрд░рдг рдореЗрдВ рд╢рд╛рдорд┐рд▓ рд╡рд░реНрдЧ рдХреЗ рдЯреБрдХрдбрд╝реЗред рд╣рдо рдИрд╡реЗрдВрдЯ-рдЬрдирд░реЗрдЯ рдХрд┐рдП рдЧрдП рдирд┐рдХрд╛рдп рдХреЗ рд▓рд┐рдП API рдХреЛ рдПрдХ рд╕реБрд░рдХреНрд╖рд┐рдд
applyEventName()
рдлрд╝рдВрдХреНрд╢рди рдХреЗ рд▓рд┐рдП рднреА рд╕реНрдкрд╖реНрдЯ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдЬреЛ рдИрд╡реЗрдВрдЯ рдХреЛ рд╕реНрд╡реАрдХрд╛рд░ рдХрд░рддрд╛ рд╣реИ, рдЬреЛ рд╕рдВрдмрдВрдзрд┐рдд
applyEventName()
рд╡рд┐рдзрд┐ рдХреЛ рдХреЙрд▓ рдХрд░рддрд╛ рд╣реИ, рдФрд░ рдПрдХ рдирдП
DomainEventMessage
рдИрд╡реЗрдВрдЯ рдХреЛ
DomainEventMessage
рдИрд╡реЗрдВрдЯ рдХреА рд╕реВрдЪреА рдореЗрдВ рдЬреЛрдбрд╝рддрд╛ рд╣реИред рдирд┐рдХрд╛рд▓рд╛ рдЧрдпрд╛ рд╡рд░реНрдЧ CQRS рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХрд╛ рдПрдХ рд╡рд┐рд╡рд░рдг рд╣реИ рдФрд░ рдЗрд╕рдореЗрдВ рдбреЛрдореЗрди рддрд░реНрдХ рд╢рд╛рдорд┐рд▓ рдирд╣реАрдВ рд╣реИ, рдЗрд╕рд▓рд┐рдП рд╣рдо рдПрдХ рдирдпрд╛ рдирд╛рдорд╕реНрдерд╛рди рдмрдирд╛ рд╕рдХрддреЗ рд╣реИрдВ: App \ CQRS:
рдХреЛрдб app/CQRS/EventSourcedEntity.php
рдкрд░ рдзреНрдпрд╛рди app/CQRS/EventSourcedEntity.php
рдХреЛрдб рдХреЛ рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдореЗрдВ DomainEventMessage
рдХреНрд▓рд╛рд╕ рдХреЛ рдЬреЛрдбрд╝рдирд╛ рд╣реЛрдЧрд╛, рдЬреЛ рдХрд┐ рдПрдХ рд╕рд╛рдзрд╛рд░рдг DTO рд╣реИ - рдЗрд╕реЗ app/CQRS/DomainEventMessage.php
рдореЗрдВ рдкрд╛рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИредрдЗрд╕ рдкреНрд░рдХрд╛рд░, рд╣рдореЗрдВ рдПрдХ рдкреНрд░рдгрд╛рд▓реА рдорд┐рд▓реА рдЬреЛ рдкреНрд░рддреНрдпреЗрдХ рд▓рд┐рдЦрдиреЗ рдХреЗ рдкреНрд░рдпрд╛рд╕ рдХреЗ рд▓рд┐рдП рдШрдЯрдирд╛рдУрдВ рдХреЛ рдЙрддреНрдкрдиреНрди рдХрд░рддреА рд╣реИ рдФрд░ рдЖрдХреНрд░рдордгрдХрд╛рд░рд┐рдпреЛрдВ рдХреЛ рд░реЛрдХрдиреЗ рдХреЗ рд▓рд┐рдП рдЖрд╡рд╢реНрдпрдХ рдкрд░рд┐рд╡рд░реНрддрдиреЛрдВ рдХреЛ рд░рд┐рдХреЙрд░реНрдб рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдШрдЯрдирд╛рдУрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреА рд╣реИред рдЕрдЧрд▓рд╛ рдХрджрдо рд╕реНрдЯреЛрд░ рдореЗрдВ рдЗрди рдШрдЯрдирд╛рдУрдВ рдХреЛ рдмрдЪрд╛рдиреЗ рдХреЗ рд▓рд┐рдП рд╣реИ (EventStore)ред рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рдЗрд╕ рдШрдЯрдирд╛ рдХреЗ рднрдВрдбрд╛рд░ рдХреЛ рдмрдирд╛рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рд╕рд░рд▓ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рдПрд▓реЛрдХреЗрдВрдЯ рдореЙрдбрд▓, рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдХреНрд╖реЗрддреНрд░реЛрдВ рдХреЗ рд╕рд╛рде рдПрдХ рд╕рд╛рдзрд╛рд░рдг рдПрд╕рдХреНрдпреВрдПрд▓ рдЯреЗрдмрд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗ: *
UUID
(рдпрд╣ рдЬрд╛рдирдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐ рдХрд┐рд╕ рдЗрдХрд╛рдИ рдХреЛ рдШрдЯрдирд╛ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдирд╛ рд╣реИ) *
event_payload
(рдШрдЯрдирд╛ рдХреЛ рдлрд┐рд░ рд╕реЗ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдЖрд╡рд╢реНрдпрдХ рд╕рдм рдХреБрдЫ рдпреБрдХреНрдд рдзрд╛рд░рд╛рд╡рд╛рд╣рд┐рдХ рд╕рдВрджреЗрд╢) -
event_payload
рдЯрд╛рдЗрдорд╕реНрдЯреИрдореНрдк рдЬрдм рдШрдЯрдирд╛ рдХреЛ рдЬрд╛рдирдиреЗ рдХреЗ рд▓рд┐рдПред рдпрд╣ рдХреНрдпрд╛ рд╣реБрдЖред рдпрджрд┐ рдЖрдк рдХреЛрдб рдХреА рд╕рд╛рд╡рдзрд╛рдиреАрдкреВрд░реНрд╡рдХ рд╕рдореАрдХреНрд╖рд╛ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рдЖрдк рджреЗрдЦреЗрдВрдЧреЗ рдХрд┐ рдореИрдВрдиреЗ рджреЛ рдЖрджреЗрд╢ рдмрдирд╛рдП - рд╣рдорд╛рд░реЗ рд╕реНрдЯреЛрд░реЗрдЬ рдЯреЗрдмрд▓ рдХреЛ рдмрдирд╛рдиреЗ рдФрд░ рдирд╖реНрдЯ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП:
- php рдХрд╛рд░реАрдЧрд░ eloquenteventstore: рдмрдирд╛рдПрдБ (App \ CQRS \ EloquentEventStore \ CreateEloquentEventStore)
- php рдХрд╛рд░реАрдЧрд░ eloquenteventstore: drop (App \ CQRS \ EloquentEventStore \ DropEloquentEventStore) (рдЙрдиреНрд╣реЗрдВ рдРрдк \ _ рдХрдВрд╕реЛрд▓ / рдХрд░реНрдиреЗрд▓ рдореЗрдВ рдЬреЛрдбрд╝рдирд╛ рди рднреВрд▓реЗрдВред рддрд╛рдХрд┐ рд╡реЗ рд▓реЛрдб рд╣реЛрдВ)ред
SQL рдХреЛ рдЗрд╡реЗрдВрдЯ рд╕реНрдЯреЛрд░ рдХреЗ рд░реВрдк рдореЗрдВ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд░рдиреЗ рдХреЗ рджреЛ рдмрд╣реБрдд рд╣реА рдЕрдЪреНрдЫреЗ рдХрд╛рд░рдг рд╣реИрдВ: рдпрд╣ рдПрдкреЗрдВрдб-рдУрдирд▓реА рдореЙрдбрд▓ (рдХреЗрд╡рд▓ рдбреЗрдЯрд╛ рдЬреЛрдбрд╝рдирд╛, рдИрд╡реЗрдВрдЯ рдЕрдкрд░рд┐рд╡рд░реНрддрдиреАрдп рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП) рдХреЛ рд▓рд╛рдЧреВ рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ, рдФрд░ рдпрд╣ рднреА рдХрд┐ SQL рдЯреЗрдореНрдкреЛрд░рд▓ рдбреЗрдЯрд╛рдмреЗрд╕ рдХреЗ рд▓рд┐рдП рдПрдХ рдЖрджрд░реНрд╢ рдХреНрд╡реЗрд░реА рд▓реИрдВрдЧреНрд╡реЗрдЬ рдирд╣реАрдВ рд╣реИред рд╣рдо рдмрд╛рдж рдХреЗ рдкреНрд░рдХрд╛рд╢рдиреЛрдВ рдореЗрдВ рдЗрд╡реЗрдВрдЯ рд╕реНрдЯреЛрд░ рдХреЗ рдкреНрд░рддрд┐рд╕реНрдерд╛рдкрди рдХреА рд╕реБрд╡рд┐рдзрд╛ рдХреЗ рд▓рд┐рдП рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХреЛ рдкреНрд░реЛрдЧреНрд░рд╛рдо рдХрд░рддреЗ рд╣реИрдВред
рдШрдЯрдирд╛рдУрдВ рдХреЛ рдмрдЪрд╛рдиреЗ рдХреЗ рд▓рд┐рдП, рднрдВрдбрд╛рд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВред рдЬрдм рднреА рд░рд┐рдХреЙрд░реНрдбрд┐рдВрдЧ рдореЙрдбрд▓ рдХреЗ рд▓рд┐рдП
save()
рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рд╣рдо рдИрд╡реЗрдВрдЯ рд╕реНрдЯреЛрд░ рдореЗрдВ рдЕрдирдХрдореНрдпреВрдЯрд┐рд╡ рд▓рд┐рд╕реНрдЯ рдХреЛ рд╕рд╣реЗрдЬрддреЗ рд╣реИрдВред рдШрдЯрдирд╛рдУрдВ рдХреЛ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдореЗрдВ рдЙрдирдХреЗ рдХреНрд░рдорд╛рдВрдХрди рдФрд░ рдбреАрд░рд╛рдЗрдЬрд╝реЗрд╢рди рдХреЗ рд▓рд┐рдП рдПрдХ рддрдВрддреНрд░ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдЗрд╕рдХреЗ рд▓рд┐рдП рдПрдХ Serializer рдмрдирд╛рдПрдВред рд╣рдореЗрдВ рдореЗрдЯрд╛рдбреЗрдЯрд╛ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рдЬреИрд╕реЗ рдХрд┐ рдПрдХ рдШрдЯрдирд╛ рд╡рд░реНрдЧ (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП,
App\School\Lesson\Events\LessonWasOpened
) рдФрд░ рдПрдХ рдЗрд╡реЗрдВрдЯ рдкреЗрд▓реЛрдб (рдХрд┐рд╕реА рдШрдЯрдирд╛ рдХреЛ рдлрд┐рд░ рд╕реЗ рд╕рдВрдЧрдард┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЖрд╡рд╢реНрдпрдХ рдбреЗрдЯрд╛)ред
рдпрд╣ рд╕рдм JSON рдкреНрд░рд╛рд░реВрдк рдореЗрдВ рдПрдиреНрдХреЛрдб рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛, рдФрд░ рдлрд┐рд░ рдЗрдХрд╛рдИ UUID рдФрд░ рдЯрд╛рдЗрдорд╕реНрдЯреИрдореНрдк рдХреЗ рд╕рд╛рде рд╣рдорд╛рд░реЗ рдбреЗрдЯрд╛рдмреЗрд╕ рдХреЛ рд▓рд┐рдЦрд╛ рдЬрд╛рдПрдЧрд╛ред рд╣рдо рдШрдЯрдирд╛рдУрдВ рдХреЛ рдХреИрдкреНрдЪрд░ рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж рдЕрдкрдиреЗ рд░реАрдбрд┐рдВрдЧ рдореЙрдбрд▓ рдХреЛ рдЕрдкрдбреЗрдЯ рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рдЗрд╕рд▓рд┐рдП рдмрдЪрдд рдХреЗ рдмрд╛рдж рд░рд┐рдкреЙрдЬрд┐рдЯрд░реА рд╣рд░ рдШрдЯрдирд╛ рдХреЛ рдЯреНрд░рд┐рдЧрд░ рдХрд░реЗрдЧреАред рд╕реАрд░рд┐рдпрд▓ рдХреНрд▓рд╛рд╕ рдХреЗ рд▓рд┐рдП рдЬрд┐рдореНрдореЗрджрд╛рд░ рд╣реЛрдЧрд╛, рдЬрдмрдХрд┐ рдЗрд╡реЗрдВрдЯ рдЙрд╕рдХреЗ рдкреЗрд▓реЛрдб рдХреЛ рд╕реАрд░рд┐рдпрд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЬрд┐рдореНрдореЗрджрд╛рд░ рд╣реЛрдЧрд╛ред рдПрдХ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдХреНрд░рдордмрджреНрдз рдШрдЯрдирд╛ рдХреБрдЫ рдЗрд╕ рддрд░рд╣ рджрд┐рдЦрд╛рдИ рджреЗрдЧреА:
{ class: "App\\School\\Lesson\\Events\\", event: $event->serialize() }
рдЪреВрдБрдХрд┐ рд╕рднреА рдШрдЯрдирд╛рдУрдВ рдХреЛ рдХреНрд░рдордмрджреНрдзрддрд╛ рдФрд░ рдбреАрд░рд┐рдПрд▓рд╛рдЗрдЬрд╝реЗрд╢рди рд╡рд┐рдзрд┐ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ, рдЗрд╕рд▓рд┐рдП рд╣рдо рдПрдХ
SerializableEvent
рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдмрдирд╛ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдЕрдкреЗрдХреНрд╖рд┐рдд рдореВрд▓реНрдп рдХреЗ рдкреНрд░рдХрд╛рд░ рдХрд╛ рдПрдХ рд╕рдВрдХреЗрдд рдЬреЛрдбрд╝ рд╕рдХрддреЗ рд╣реИрдВред рд╣рдорд╛рд░реЗ
LessonWasOpened
рдЕрдкрдбреЗрдЯ рдХрд░реЗрдВ:
app/School/Lesson/Events/LessonWasOpened.php class LessonWasOpened implements SerializableEvent { public function serialize() { return array( 'lessonId'=> (string) $this->getLessonId() ); } }
рдПрдХ
LessonRepository
рд░рд┐рдкреЛрдЬрд┐рдЯрд░реА рд░рд┐рдкреЛрдЬрд┐рдЯрд░реА рдмрдирд╛рдПрдВред рд╣рдо рдмрд╛рдж рдореЗрдВ рдХреЛрд░ CQRS рдШрдЯрдХреЛрдВ рдХреЛ рд░рд┐рдлреНрд▓реЗрдХреНрдЯрд░ рдФрд░ рдирд┐рдХрд╛рд▓ рд╕рдХрддреЗ рд╣реИрдВред
app/School/Lesson/LessonRepository.php
eventStoreRepository = new EloquentEventStoreRepository( new EventSerializer() ); } public function save(Lesson $lesson) { /** @var DomainEventMessage $domainEventMessage */ foreach( $lesson->getUncommittedDomainEvents() as $domainEventMessage ) { $this->eventStoreRepository->append( $domainEventMessage->getId(), $domainEventMessage->getEvent(), $domainEventMessage->getRecordedAt() ); Event::fire($domainEventMessage->getEvent()); } } }
рдпрджрд┐ рдЖрдк рдлрд┐рд░ рд╕реЗ рдПрдХреАрдХрд░рдг рдкрд░реАрдХреНрд╖рдг рдЪрд▓рд╛рддреЗ рд╣реИрдВ рдФрд░ рдлрд┐рд░
domain_events
SQL рддрд╛рд▓рд┐рдХрд╛ рдХреА рдЬрд╛рдБрдЪ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рдЖрдкрдХреЛ рдбреЗрдЯрд╛рдмреЗрд╕ рдореЗрдВ рджреЛ рдШрдЯрдирд╛рдУрдВ рдХреЛ рджреЗрдЦрдирд╛ рдЪрд╛рд╣рд┐рдПред
рдкрд░реАрдХреНрд╖рдг рдХреЛ рд╕рдлрд▓рддрд╛рдкреВрд░реНрд╡рдХ рдкрд╛рд╕ рдХрд░рдиреЗ рдореЗрдВ рд╣рдорд╛рд░рд╛ рдЕрдВрддрд┐рдо рдЪрд░рдг рдкреНрд░рд╕рд╛рд░рдг рдШрдЯрдирд╛рдУрдВ рдХреЛ рд╕реБрди рд░рд╣рд╛ рд╣реИ рдФрд░ рдкрд╛рда рдкрдврд╝рдиреЗ рдХреЗ рдореЙрдбрд▓ рдХреЗ рдкреНрд░рдХреНрд╖реЗрдкрдг рдХреЛ рдЕрджреНрдпрддрди рдХрд░рдирд╛ рд╣реИред рдкрд╛рда рдкреНрд░рд╕рд╛рд░рдг рдХреА рдШрдЯрдирд╛рдУрдВ рдХреЛ
LessonProjector
рджреНрд╡рд╛рд░рд╛ рдЗрдВрдЯрд░рд╕реЗрдкреНрдЯ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛, рдЬреЛ
LessonProjection
(рдкрд╛рда рддрд╛рд▓рд┐рдХрд╛ рдХреЗ
LessonProjection
рдореЙрдбрд▓) рдореЗрдВ рдЖрд╡рд╢реНрдпрдХ рдкрд░рд┐рд╡рд░реНрддрди рд▓рд╛рдЧреВ рдХрд░реЗрдЧрд╛:
app/School/Lesson/Projections/LessonProjector.php class LessonProjector { public function applyLessonWasOpened( LessonWasOpened $event ) { $lessonProjection = new LessonProjection(); $lessonProjection->id = $event->getLessonId(); $lessonProjection->save(); } public function subscribe(Dispatcher $events) { $fullClassName = self::class; $events->listen( LessonWasOpened::class, $fullClassName.'@applyLessonWasOpened'); } } app/School/Lesson/Projections/LessonProjection.php class LessonProjection extends Model { public $timestamps = false; protected $table = "lessons"; }
рдпрджрд┐ рдЖрдк рдкрд░реАрдХреНрд╖рдг рдЪрд▓рд╛рддреЗ рд╣реИрдВ, рддреЛ рдЖрдк рджреЗрдЦреЗрдВрдЧреЗ рдХрд┐ рдПрдХ SQL рддреНрд░реБрдЯрд┐ рд╣реБрдИ рд╣реИ:
Unknown column 'clientName' in 'field list'
рдЬреИрд╕реЗ рд╣реА рд╣рдо
clientName
рдХреЛ рдкрд╛рда рддрд╛рд▓рд┐рдХрд╛ рдореЗрдВ рдЬреЛрдбрд╝рдиреЗ рдХреЗ рд▓рд┐рдП рдорд╛рдЗрдЧреНрд░реЗрд╢рди рдмрдирд╛рддреЗ рд╣реИрдВ, рд╣рдо рд╕рдлрд▓рддрд╛рдкреВрд░реНрд╡рдХ рдкрд░реАрдХреНрд╖рдг рдкрд╛рд╕ рдХрд░ рд▓реЗрдВрдЧреЗред рд╣рдордиреЗ CQRS рдХреА рдмреБрдирд┐рдпрд╛рджреА рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рдХреЛ рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ рд╣реИ: рдЯреАрдореЗрдВ рдРрд╕реА рдШрдЯрдирд╛рдУрдВ рдХрд╛ рдирд┐рд░реНрдорд╛рдг рдХрд░рддреА рд╣реИрдВ рдЬрд┐рдирдХрд╛ рдЙрдкрдпреЛрдЧ рд░реАрдбрд┐рдВрдЧ рдореЙрдбрд▓ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред
рд▓рд┐рдВрдХ рдХреЗ рд╕рд╛рде рд░реАрдбрд┐рдВрдЧ рдореЙрдбрд▓ рдореЗрдВ рд╕реБрдзрд╛рд░
рд╣рдо рдПрдХ рдорд╣рддреНрд╡рдкреВрд░реНрдг рдореБрдХрд╛рдо рдкрд░ рдкрд╣реБрдВрдЪ рдЧрдП рд╣реИрдВ, рд▓реЗрдХрд┐рди рдпрд╣ рд╕рдм рдирд╣реАрдВ рд╣реИ! рдЕрдм рддрдХ, рд░реАрдбрд┐рдВрдЧ рдореЙрдбрд▓ рдХреЗрд╡рд▓ рдПрдХ рдХреНрд▓рд╛рдЗрдВрдЯ рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рддрд╛ рд╣реИ (рд╣рдордиреЗ рдЕрдкрдиреЗ рдбреЛрдореЗрди рдирд┐рдпрдореЛрдВ рдореЗрдВ рддреАрди рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд┐рдП рд╣реИрдВ)ред рд░реАрдбрд┐рдВрдЧ рдореЙрдбрд▓ рдореЗрдВ рд╣рдо рдЬреЛ рдмрджрд▓рд╛рд╡ рдХрд░рддреЗ рд╣реИрдВ, рд╡реЗ рдХрд╛рдлреА рд╕рд░рд▓ рд╣реИрдВ: рд╣рдо рд╕рд┐рд░реНрдл рдПрдХ рдХреНрд▓рд╛рдЗрдВрдЯ рдкреНрд░реЛрдЬреЗрдХреНрд╢рди рдореЙрдбрд▓ рдФрд░ рдПрдХ
ClientBookedOntoLesson
рдЬреЛ
ClientBookedOntoLesson
рдЗрд╡реЗрдВрдЯ рдХреЛ рдкрдХрдбрд╝рддрд╛ рд╣реИред рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рд╣рдо рдЕрдкрдиреЗ рдкрд░реАрдХреНрд╖рдг рдХреЛ рдЙрди рдкрд░рд┐рд╡рд░реНрддрдиреЛрдВ рдХреЛ рдкреНрд░рддрд┐рдмрд┐рдВрдмрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЕрджреНрдпрддрди рдХрд░рддреЗ рд╣реИрдВ рдЬрд┐рдиреНрд╣реЗрдВ рд╣рдо рдЕрдкрдиреЗ рдкрдврд╝рдиреЗ рдХреЗ рдореЙрдбрд▓ рдореЗрдВ рджреЗрдЦрдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ:
tests/CQRSTest.php public function testFiringEventUpdatesReadModel() { $lessonId = new LessonId( (string) \Rhumsaa\Uuid\Uuid::uuid1() ); $clientName = "George"; $command = new BookLesson($lessonId, $clientName); $this->dispatch($command); $lesson = Lesson::find( (string) $lessonId); $this->assertEquals( $lesson->id, (string) $lessonId ); $client = $lesson->clients()->first(); $this->assertEquals($client->name, $clientName); }
рдпрд╣ рдПрдХ рд╕реНрдкрд╖реНрдЯ рдкреНрд░рджрд░реНрд╢рди рд╣реИ рдХрд┐ рд░реАрдбрд┐рдВрдЧ рдореЙрдбрд▓ рдХреЛ рдмрджрд▓рдирд╛ рдХрд┐рддрдирд╛ рдЖрд╕рд╛рди рд╣реИред рд╕рдм рдХреБрдЫ, рдШрдЯрдирд╛ рдХреЗ рднрдВрдбрд╛рд░ рдХреЗ рдиреАрдЪреЗ, рдЕрдкрд░рд┐рд╡рд░реНрддрд┐рдд рд░рд╣рддрд╛ рд╣реИред рдПрдХ рдмреЛрдирд╕ рдХреЗ рд░реВрдк рдореЗрдВ, рдИрд╡реЗрдВрдЯ рд╕рд┐рд╕реНрдЯрдо рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╕рдордп, рд╣рдореЗрдВ рдмреБрдирд┐рдпрд╛рджреА рдкрд░реАрдХреНрд╖рдгреЛрдВ рдХреЗ рд▓рд┐рдП рдбреЗрдЯрд╛ рдорд┐рд▓рддрд╛ рд╣реИ - рд░реАрдбрд┐рдВрдЧ рдореЙрдбрд▓ рдХреЗ рдкреНрд░реЛрдЬреЗрдХреНрдЯрд░ рдХреЛ рдмрджрд▓рддреЗ рд╕рдордп, рд╣рдо рд╣рд░ рдЙрд╕ рдШрдЯрдирд╛ рдХреЛ рд╕реБрдирддреЗ рд╣реИрдВ рдЬреЛ рдХрднреА рд╣рдорд╛рд░реЗ рд╕рд┐рд╕реНрдЯрдо рдореЗрдВ рд╣реБрдИ рд╣реИред
рд╣рдо рдирдП рдкреНрд░реЛрдЬреЗрдХреНрдЯрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЗрди рдШрдЯрдирд╛рдУрдВ рдХреЛ рдкреБрди: рдкреЗрд╢ рдХрд░рддреЗ рд╣реИрдВ, рдЕрдкрд╡рд╛рджреЛрдВ рдХреА рдЬрд╛рдВрдЪ рдХрд░рддреЗ рд╣реИрдВ, рдФрд░ рдкрд┐рдЫрд▓реЗ рдЕрдиреБрдорд╛рдиреЛрдВ рдХреЗ рд╕рд╛рде рдкрд░рд┐рдгрд╛рдореЛрдВ рдХреА рддреБрд▓рдирд╛ рдХрд░рддреЗ рд╣реИрдВред рд╕рд┐рд╕реНрдЯрдо рдХреБрдЫ рд╕рдордп рдХреЗ рд▓рд┐рдП рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж, рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рд╣рдорд╛рд░реЗ рдкреНрд░реЛрдЬреЗрдХреНрдЯрд░реЛрдВ рдХреЗ рдкрд░реАрдХреНрд╖рдг рдХреЗ рд▓рд┐рдП рдШрдЯрдирд╛рдУрдВ рдХрд╛ рдПрдХ рдХрд╛рдлреА рдкреНрд░рддрд┐рдирд┐рдзрд┐ рдЪрдпрди рд╣реЛрдЧрд╛ред
рд╣рдорд╛рд░реЗ рд░рд┐рдХреЙрд░реНрдбрд┐рдВрдЧ рдореЙрдбрд▓ рдореЗрдВ рд╡рд░реНрддрдорд╛рди рд╕реНрдерд┐рддрд┐ рдХреЛ рд▓реЛрдб рдХрд░рдиреЗ рдХреА рдХреНрд╖рдорддрд╛ рдирд╣реАрдВ рд╣реИред рдпрджрд┐ рд╣рдо рдкрд╛рда рдореЗрдВ рджреВрд╕рд░рд╛ рдЧреНрд░рд╛рд╣рдХ рдЬреЛрдбрд╝рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рддреЛ рд╣рдо рдмрд╕ рдПрдХ рджреВрд╕рд░рд╛ ClientWasAddedToLesson рдИрд╡реЗрдВрдЯ рдмрдирд╛ рд╕рдХрддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рд╣рдо рдЗрдирд╡рд┐рдпрд░реНрд╕ рдХреЗ рдЦрд┐рд▓рд╛рдл рд╕реБрд░рдХреНрд╖рд╛ рдкреНрд░рджрд╛рди рдирд╣реАрдВ рдХрд░ рд╕рдХрддреЗред рдЕрдзрд┐рдХ рд╕реНрдкрд╖реНрдЯрддрд╛ рдХреЗ рд▓рд┐рдП, рдореИрдВ рдкреНрд░рддрд┐ рдкрд╛рда рджреЛ рдЧреНрд░рд╛рд╣рдХреЛрдВ рдХреА рд░рд┐рдХреЙрд░реНрдбрд┐рдВрдЧ рдХрд╛ рдЕрдиреБрдХрд░рдг рдХрд░рддреЗ рд╣реБрдП рдПрдХ рджреВрд╕рд░рд╛ рдкрд░реАрдХреНрд╖рдг рд▓рд┐рдЦрдиреЗ рдХрд╛ рдкреНрд░рд╕реНрддрд╛рд╡ рдХрд░рддрд╛ рд╣реВрдВред
tests/CQRSTest.php public function testLoadingWriteModel() { $lessonId = new LessonId( (string) \Rhumsaa\Uuid\Uuid::uuid1() ); $clientName_1 = "George"; $clientName_2 = "Fred"; $command = new BookLesson($lessonId, $clientName_1); $this->dispatch($command); $command = new BookClientOntoLesson($lessonId, $clientName_2); $this->dispatch($command); $lesson = Lesson::find( (string) $lessonId ); $this->assertClientCollectionContains($lesson->clients, $clientName_1); $this->assertClientCollectionContains($lesson->clients, $clientName_2); }
рд╣рдорд╛рд░реЗ рд░рд┐рдХреЙрд░реНрдбрд┐рдВрдЧ рдореЙрдбрд▓ рдХреЗ рд▓рд┐рдП, рд╣рдореЗрдВ рдПрдХ рдЗрдХрд╛рдИ рдХреЛ "рд▓реЛрдб" рдХрд░рдиреЗ рдХреА рдПрдХ рд╡рд┐рдзрд┐ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рдЬрд┐рд╕рдХреЗ рд▓рд┐рдП рдЗрд╡реЗрдВрдЯ рд╕реНрдЯреЛрд░ рдореЗрдВ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдЗрд╕рдХреЗ рд▓рд┐рдП рдЖрд╡реЗрджрди рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рд╣рдо рдЗрдХрд╛рдИ рдХреЗ рдпреВрдпреВрдЖрдИрдбреА рдХреЛ рд╕рдВрджрд░реНрднрд┐рдд рдХрд░рдиреЗ рд╡рд╛рд▓реА рдкреНрд░рддреНрдпреЗрдХ рдШрдЯрдирд╛ рдХреЛ рд╡рд╛рдкрд╕ рдЦреЗрд▓рдХрд░ рдЗрд╕реЗ рдкреНрд░рд╛рдкреНрдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рд╕рд╛рдорд╛рдиреНрдп рд╢рдмреНрджреЛрдВ рдореЗрдВ, рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдЗрд╕ рдкреНрд░рдХрд╛рд░ рд╣реИ:
- рд╣рдореЗрдВ рдИрд╡реЗрдВрдЯ рд╕реНрдЯреЛрд░ рд╕реЗ рд╕рднреА рдкреНрд░рд╛рд╕рдВрдЧрд┐рдХ рдИрд╡реЗрдВрдЯ рд╕рдВрджреЗрд╢ рдкреНрд░рд╛рдкреНрдд рд╣реЛрддреЗ рд╣реИрдВред
- рдкреНрд░рддреНрдпреЗрдХ рд╕рдВрджреЗрд╢ рдХреЗ рд▓рд┐рдП, рд╣рдо рдЗрд╕реА рдШрдЯрдирд╛ рдХреЛ рдлрд┐рд░ рд╕реЗ рдмрдирд╛рддреЗ рд╣реИрдВред
- рд╣рдо рдПрдХ рдирдпрд╛ рдЗрдХрд╛рдИ рд░рд┐рдХреЙрд░реНрдб рдореЙрдбрд▓ рдмрдирд╛рддреЗ рд╣реИрдВ рдФрд░ рдкреНрд░рддреНрдпреЗрдХ рдШрдЯрдирд╛ рдХреЛ рд╡рд╛рдкрд╕ рдЦреЗрд▓рддреЗ рд╣реИрдВред
рдлрд┐рд▓рд╣рд╛рд▓, рд╣рдорд╛рд░реЗ рдкрд░реАрдХреНрд╖рдг рдЕрдкрд╡рд╛рджреЛрдВ рдХреЛ рдлреЗрдВрдХрддреЗ рд╣реИрдВ, рдЗрд╕рд▓рд┐рдП рд╣рдо
BookLesson
рдХрдорд╛рдВрдб рдХреЛ рдЯреЗрдореНрдкрд▓реЗрдЯ рдХреЗ рд░реВрдк рдореЗрдВ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реБрдП, рдЖрд╡рд╢реНрдпрдХ
BookClientOntoLesson
(рдкрд╛рда рдХреЗ рд▓рд┐рдП рдПрдХ рдХреНрд▓рд╛рдЗрдВрдЯ рд░рдЬрд┐рд╕реНрдЯрд░ рдХрд░реЗрдВ)
BookLesson
рдХрд░реЗрдВрдЧреЗред рд╣реИрдВрдбрд▓рд░ рд╡рд┐рдзрд┐ рдЗрд╕ рддрд░рд╣ рджрд┐рдЦрд╛рдИ рджреЗрдЧреА:
app/School/Lesson/Commands/BookClientOntoLesson.php public function handle(LessonRepository $repository) { /** @var Lesson $lesson */ $lesson = $repository->load($this->lessonId); $lesson->bookClient($this->clientName); $repository->save($lesson); } : app/School/Lesson/LessonRepository.php public function load(LessonId $id) { $events = $this->eventStoreRepository->load($id); $lesson = new Lesson(); $lesson->initializeState($events); return $lesson; }
рд░рд┐рдкреЙрдЬрд┐рдЯрд░реА рд▓реЛрдб рдлрд╝рдВрдХреНрд╢рди рд░реАрдХреНрд░рд┐рдПрдЯреЗрдб рдЗрд╡реЗрдВрдЯ рдХреА рдПрдХ рд╕рд░рдгреА рджреЗрддрд╛ рд╣реИред рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╡рд╣ рдкрд╣рд▓реЗ рд░рд┐рдкреЙрдЬрд┐рдЯрд░реА рдореЗрдВ рдШрдЯрдирд╛рдУрдВ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд╕рдВрджреЗрд╢ рдкрд╛рддрд╛ рд╣реИ, рдФрд░ рдлрд┐рд░ рдкреНрд░рддреНрдпреЗрдХ рд╕рдВрджреЗрд╢ рдХреЛ рдПрдХ рдШрдЯрдирд╛ рдореЗрдВ рдмрджрд▓рдиреЗ рдХреЗ рд▓рд┐рдП рдЙрдиреНрд╣реЗрдВ
Serializer
рдореЗрдВ
Serializer
рд╣реИред
Serializer
рдШрдЯрдирд╛рдУрдВ рд╕реЗ рд╕рдВрджреЗрд╢ рдмрдирд╛рддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рд╣рдореЗрдВ рд╡реНрдпреБрддреНрдХреНрд░рдо рдкрд░рд┐рд╡рд░реНрддрди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП
deserialize()
рд╡рд┐рдзрд┐ рдХреЛ рдЬреЛрдбрд╝рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдпрд╛рдж рд░рдЦреЗрдВ рдХрд┐ рдШрдЯрдирд╛ рдХреЗ рдбреЗрдЯрд╛ (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдХреНрд▓рд╛рдЗрдВрдЯ рдХрд╛ рдирд╛рдо) рдХреЛ рдХреНрд░рдордмрджреНрдз рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдкреНрд░рддреНрдпреЗрдХ рдШрдЯрдирд╛ рдХреЗ рд▓рд┐рдП
Serializer
рдкрд╛рд░рд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред рд╣рдо рд╡реНрдпреБрддреНрдХреНрд░рдо рдкрд░рд┐рд╡рд░реНрддрди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдРрд╕рд╛ рд╣реА рдХрд░реЗрдВрдЧреЗ, рдЬрдмрдХрд┐ рд╣рдорд╛рд░реЗ
SerializableEvent
рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХреЛ
deserialize()
рд╡рд┐рдзрд┐ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЕрдкрдбреЗрдЯ рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред рдХреЛрдб рдХреЛ рджреЗрдЦрддреЗ рд╣реИрдВ рддрд╛рдХрд┐ рд╕рдм рдХреБрдЫ рдЬрдЧрд╣ рдореЗрдВ рдЧрд┐рд░ рдЬрд╛рдПред рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ
EventStoreRepository
рд▓реЛрдб
EventStoreRepository
:
app/CQRS/EloquentEventStore/EloquentEventStoreRepository.php public function load($uuid) { $eventMessages = EloquentEventStoreModel::where('uuid', $uuid)->get(); $events = []; foreach($eventMessages as $eventMessage) { /* event_payload, . */ $events[] = $this->eventSerializer->deserialize( json_decode($eventMessage->event_payload)); } return $events; }
eventSerializer
рдореЗрдВ рдЙрдЪрд┐рдд deserialization рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛:
app/CQRS/Serializer/EventSerializer.php public function serialize( SerializableEvent $event ) { return array( 'class' => get_class($event), 'payload' => $event->serialize() ); } public function deserialize( $serializedEvent ) { $eventClass = $serializedEvent->class; $eventPayload = $serializedEvent->payload; return $eventClass::deserialize($eventPayload); }
рдЕрдВрдд рдореЗрдВ, рд╣рдо
LessonWasOpened
рдореЗрдВ рд╕реНрдЯреИрдЯрд┐рдХ рдлреИрдХреНрдЯреНрд░реА рд╡рд┐рдзрд┐
deserialize()
рдХрд╛ рдЙрдкрдпреЛрдЧ
LessonWasOpened
(рд╣рдореЗрдВ рдкреНрд░рддреНрдпреЗрдХ рдИрд╡реЗрдВрдЯ рдореЗрдВ рдЗрд╕ рд╡рд┐рдзрд┐ рдХреЛ рдЬреЛрдбрд╝рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ)
app/School/Lesson/Events/LessonWasOpened.php public static function deserialize($data) { $lessonId = new LessonId($data->lessonId); return new self($lessonId); }
рдЕрдм рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдЙрди рд╕рднреА рдШрдЯрдирд╛рдУрдВ рдХреА рдПрдХ рд╕рд░рдгреА рд╣реИ, рдЬрд┐рдиреНрд╣реЗрдВ рд╣рдордиреЗ
app/CQRS/EventSouredEntity.php
рдореЗрдВ
initializeState
рд╡рд┐рдзрд┐ рдореЗрдВ рд░рд╛рдЬреНрдп рдХреЛ рд╢реБрд░реВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╣рдорд╛рд░реЗ рдПрдВрдЯрд┐рдЯреА рд░рд┐рдХреЙрд░реНрдб рдореЙрдбрд▓ рдХреЗ рд╕рд╛рдкреЗрдХреНрд╖ рдкреБрди: рдкреНрд░рд╕реНрддреБрдд рдХрд┐рдпрд╛ рд╣реИред
рдЕрдм рд╣рдорд╛рд░реА рдкрд░реАрдХреНрд╖рд╛ рдЪрд▓рд╛рдУред рдмрд┐рдВрдЧреЛ!
рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рдЗрд╕ рд╕рдордп рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рд╣рдорд╛рд░реЗ рдбреЛрдореЗрди рдирд┐рдпрдореЛрдВ рдХреЗ рдЕрдиреБрдкрд╛рд▓рди рдХреЛ рд╕рддреНрдпрд╛рдкрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдкрд░реАрдХреНрд╖рдг рдирд╣реАрдВ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдЗрд╕реЗ рд▓рд┐рдЦреЗрдВ:
tests/CQRSTest.php public function testMoreThan3ClientsCannotBeAddedToALesson() { $lessonId = new LessonId( (string) \Rhumsaa\Uuid\Uuid::uuid1() ); $this->dispatch( new BookLesson($lessonId, "bob") ); $this->dispatch( new BookClientOntoLesson($lessonId, "george") ); $this->dispatch( new BookClientOntoLesson($lessonId, "fred") ); $this->setExpectedException( TooManyClientsAddedToLesson::class ); $this->dispatch( new BookClientOntoLesson($lessonId, "emma") ); }
рдХреГрдкрдпрд╛ рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рд╣рдореЗрдВ рдХреЗрд╡рд▓
lessonId
рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ - рдпрд╣ рдкрд░реАрдХреНрд╖рдг рдкреНрд░рддреНрдпреЗрдХ рдХрдорд╛рдВрдб рдХреЗ рджреМрд░рд╛рди рдкрд╛рда рдХреА рд╕реНрдерд┐рддрд┐ рдХреЛ
lessonId
ред
рдлрд┐рд▓рд╣рд╛рд▓, рд╣рдо рдХреЗрд╡рд▓ рдореИрдиреНрдпреБрдЕрд▓ рд░реВрдк рд╕реЗ рдмрдирд╛рдП рдЧрдП
UUID
рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░рддреЗ рд╣реИрдВ, рдЬрдмрдХрд┐ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рд╣рдо рдЙрдиреНрд╣реЗрдВ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд░реВрдк рд╕реЗ рдЙрддреНрдкрдиреНрди рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВред рдореИрдВ
Ramsy\UUID
рдкреИрдХреЗрдЬ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдЬрд╛ рд░рд╣рд╛ рд╣реВрдВ, рдЗрд╕рд▓рд┐рдП
composer
рд╕рд╛рде рдЗрд╕реЗ рд╕реНрдерд╛рдкрд┐рдд рдХрд░реЗрдВ:
$> composer require ramsey/uuid
рдЕрдм рдирдП рдкреИрдХреЗрдЬ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╣рдорд╛рд░реЗ рдкрд░реАрдХреНрд╖рдг рдЕрдкрдбреЗрдЯ рдХрд░реЗрдВ:
tests/CQRSTest.php public function testEntityCreationWithUUIDGenerator() { $lessonId = new LessonId( (string) \Rhumsaa\Uuid\Uuid::uuid1() ); $this->dispatch( new BookLesson($lessonId, "bob") ); $this->assertInstanceOf( Lesson::class, Lesson::find( (string) $lessonId) ); }
рдЕрдм рдирдП рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдбреЗрд╡рд▓рдкрд░ рдХреЛрдб рдХреЛ рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ,
App\School\ReadModels
, рдЬрд┐рд╕рдореЗрдВ
App\School\ReadModels
рдореЙрдбрд▓ рдХрд╛ рдПрдХ рд╕реЗрдЯ рд╣реИ, рдФрд░ рдкрд╛рда рддрд╛рд▓рд┐рдХрд╛ рдореЗрдВ рдкрд░рд┐рд╡рд░реНрддрди рд▓рд┐рдЦрдиреЗ рдХреЗ рд▓рд┐рдП рдЗрди рдореЙрдбрд▓реЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВред рд╣рдо рдПрдХ рдРрд╕рд╛
app/CQRS/ReadModelImmutableModel.php
рдХреНрд▓рд╛рд╕ рдмрдирд╛рдХрд░ рдЗрд╕реЗ рд░реЛрдХ рд╕рдХрддреЗ рд╣реИрдВ, рдЬреЛ рдПрд▓реЛрдХреНрд╡реЗрдВрдЯ рдореЙрдбрд▓ рдХреНрд▓рд╛рд╕ рдХрд╛ рд╡рд┐рд╕реНрддрд╛рд░ рдХрд░рддрд╛ рд╣реИ рдФрд░
app/CQRS/ReadModelImmutableModel.php
рдореЗрдВ рд╕реЗрд╡ рдореЗрдердб рдХреЛ рдУрд╡рд░рд░рд╛рдЗрдб рдХрд░рддрд╛ рд╣реИред