{"action":"created","issue":{"url":"https://api.github.com/repos/neos/Neos.Cqrs/issues/94","repository_url":"https://api.github.com/repos/neos/Neos.Cqrs","labels_url":"https://api.github.com/repos/neos/Neos.Cqrs/issues/94/labels{/name}","comments_url":"https://api.github.com/repos/neos/Neos.Cqrs/issues/94/comments","events_url":"https://api.github.com/repos/neos/Neos.Cqrs/issues/94/events","html_url":"https://github.com/neos/Neos.Cqrs/issues/94","id":187738736,"number":94,"title":"Event upcasting","user":{"login":"bwaidelich","id":307571,"avatar_url":"https://avatars.githubusercontent.com/u/307571?v=3","gravatar_id":"","url":"https://api.github.com/users/bwaidelich","html_url":"https://github.com/bwaidelich","followers_url":"https://api.github.com/users/bwaidelich/followers","following_url":"https://api.github.com/users/bwaidelich/following{/other_user}","gists_url":"https://api.github.com/users/bwaidelich/gists{/gist_id}","starred_url":"https://api.github.com/users/bwaidelich/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/bwaidelich/subscriptions","organizations_url":"https://api.github.com/users/bwaidelich/orgs","repos_url":"https://api.github.com/users/bwaidelich/repos","events_url":"https://api.github.com/users/bwaidelich/events{/privacy}","received_events_url":"https://api.github.com/users/bwaidelich/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":1,"created_at":"2016-11-07T15:19:34Z","updated_at":"2016-11-09T09:33:14Z","closed_at":null,"body":"It should be possible to \"hook into\" the event handling process (during publishing & replay) in order to change the event class.\r\n\r\n### Example\r\n\r\nImagine you have an event `CustomerWasRenamed()` that expects the `$fullName` as constructor argument.\r\nNow you want to split that into `$givenName` and `$familyName` but there are already existing events in the store with the old format.\r\n\r\n#### Solution 1 (custom TypeConverter)\r\n\r\nYou could implement a custom `CustomerWasRenamedTypeConverter` that accepts an array and supports both variants\r\n\r\n#### Solution 2 (Accept both variants in the event implementation)\r\n\r\nWith the rename example that would be a bit hacky and could look sth like:\r\n```php\r\nfinal class CustomerWasRenamed implements EventInterface\r\n{\r\n    public function __construct(string $fullName = null, string $givenName = null, string $familyName = null)\r\n    {\r\n        if ($fullName !== null) {\r\n            list($this->givenName, $this->familyName) = explode(' ', $fullName);\r\n        }\r\n    }\r\n}\r\n```\r\nBut this is perfectly fine if you just add new parameters (which is probably the more common scenario)\r\n\r\n#### Solution 3 (Create a new Event)\r\n\r\nObviously one can just create a new Event, i.e. `CustomerWasRenamedV2` and deprecate the old one\r\n(again that doesn't really make sense for the given example, but usually the need for an upcast often comes from a different usecase that justifies a new event)\r\n\r\n#### Solution 4 (Framework support)\r\n\r\nWe have a central authority for mapping event types in the form `some.bounded.context:eventname` to the event implementation.\r\nWe could provide some simple mechanism to let 3rd party code hook into it in order to use a different implementation based on the payload"},"comment":{"url":"https://api.github.com/repos/neos/Neos.Cqrs/issues/comments/259370305","html_url":"https://github.com/neos/Neos.Cqrs/issues/94#issuecomment-259370305","issue_url":"https://api.github.com/repos/neos/Neos.Cqrs/issues/94","id":259370305,"user":{"login":"robertlemke","id":95582,"avatar_url":"https://avatars.githubusercontent.com/u/95582?v=3","gravatar_id":"","url":"https://api.github.com/users/robertlemke","html_url":"https://github.com/robertlemke","followers_url":"https://api.github.com/users/robertlemke/followers","following_url":"https://api.github.com/users/robertlemke/following{/other_user}","gists_url":"https://api.github.com/users/robertlemke/gists{/gist_id}","starred_url":"https://api.github.com/users/robertlemke/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/robertlemke/subscriptions","organizations_url":"https://api.github.com/users/robertlemke/orgs","repos_url":"https://api.github.com/users/robertlemke/repos","events_url":"https://api.github.com/users/robertlemke/events{/privacy}","received_events_url":"https://api.github.com/users/robertlemke/received_events","type":"User","site_admin":false},"created_at":"2016-11-09T09:33:14Z","updated_at":"2016-11-09T09:33:14Z","body":"I think the solution which is easiest to understand and to implement is no. 2. I guess no. 1  and no. 3 will always be (additional) options. I'm not sure about how 4 would look like in practice. "}}
{"actor":{"display_login":"robertlemke"}}