{"action":"closed","issue":{"url":"https://api.github.com/repos/somos/framework/issues/31","labels_url":"https://api.github.com/repos/somos/framework/issues/31/labels{/name}","comments_url":"https://api.github.com/repos/somos/framework/issues/31/comments","events_url":"https://api.github.com/repos/somos/framework/issues/31/events","html_url":"https://github.com/somos/framework/issues/31","id":57722909,"number":31,"title":"Actions","user":{"login":"mvriel","id":193704,"avatar_url":"https://avatars.githubusercontent.com/u/193704?v=3","gravatar_id":"","url":"https://api.github.com/users/mvriel","html_url":"https://github.com/mvriel","followers_url":"https://api.github.com/users/mvriel/followers","following_url":"https://api.github.com/users/mvriel/following{/other_user}","gists_url":"https://api.github.com/users/mvriel/gists{/gist_id}","starred_url":"https://api.github.com/users/mvriel/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mvriel/subscriptions","organizations_url":"https://api.github.com/users/mvriel/orgs","repos_url":"https://api.github.com/users/mvriel/repos","events_url":"https://api.github.com/users/mvriel/events{/privacy}","received_events_url":"https://api.github.com/users/mvriel/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/somos/framework/labels/roadmap","name":"roadmap","color":"fbca04"}],"state":"closed","locked":false,"assignee":{"login":"mvriel","id":193704,"avatar_url":"https://avatars.githubusercontent.com/u/193704?v=3","gravatar_id":"","url":"https://api.github.com/users/mvriel","html_url":"https://github.com/mvriel","followers_url":"https://api.github.com/users/mvriel/followers","following_url":"https://api.github.com/users/mvriel/following{/other_user}","gists_url":"https://api.github.com/users/mvriel/gists{/gist_id}","starred_url":"https://api.github.com/users/mvriel/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mvriel/subscriptions","organizations_url":"https://api.github.com/users/mvriel/orgs","repos_url":"https://api.github.com/users/mvriel/repos","events_url":"https://api.github.com/users/mvriel/events{/privacy}","received_events_url":"https://api.github.com/users/mvriel/received_events","type":"User","site_admin":false},"milestone":{"url":"https://api.github.com/repos/somos/framework/milestones/6","labels_url":"https://api.github.com/repos/somos/framework/milestones/6/labels","id":979308,"number":6,"title":"Core activities","description":"","creator":{"login":"mvriel","id":193704,"avatar_url":"https://avatars.githubusercontent.com/u/193704?v=3","gravatar_id":"","url":"https://api.github.com/users/mvriel","html_url":"https://github.com/mvriel","followers_url":"https://api.github.com/users/mvriel/followers","following_url":"https://api.github.com/users/mvriel/following{/other_user}","gists_url":"https://api.github.com/users/mvriel/gists{/gist_id}","starred_url":"https://api.github.com/users/mvriel/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mvriel/subscriptions","organizations_url":"https://api.github.com/users/mvriel/orgs","repos_url":"https://api.github.com/users/mvriel/repos","events_url":"https://api.github.com/users/mvriel/events{/privacy}","received_events_url":"https://api.github.com/users/mvriel/received_events","type":"User","site_admin":false},"open_issues":5,"closed_issues":1,"state":"open","created_at":"2015-02-14T08:18:04Z","updated_at":"2015-02-15T14:23:06Z","due_on":null,"closed_at":null},"comments":1,"created_at":"2015-02-15T08:31:44Z","updated_at":"2015-02-15T14:23:06Z","closed_at":"2015-02-15T14:23:06Z","body":"A core part of Somos is the concept of Actions. An action is an implementation of the Action Controller pattern; each represents a single Request -> Response combination.\r\n\r\nUsing an action can developers instruct Somos to serve an HTTP request, respond to a Console command or anything else that requires a match, business logic and response. \r\n\r\nThe basic API for constructing an Action is as follows:\r\n\r\n    $action = Action::matches($matcher)->uses($actionCallback)->responds($responderCallback);\r\n\r\n## Matchers\r\n\r\nIn the example above the `$matcher` is an object that can be recognized by a Message and provides a pattern that allows that message to check if the attached business logic and response is to be handled. An example of this is the \\Somos\\Console\\Command object; it will function as a matcher since it requires a command name (such as 'my:command') and the Somos\\Console\\Run message will use actions with that matcher to know which console commands are available.\r\n\r\n## Business logic\r\n\r\nAn action can optionally bind a piece of business logic to itself using the `uses()` method. This business logic can be a callable (handy for use as micro-framework) or a string representing a class name (and optionally method) of a service that will be able to pull in additional services automatically using the auto-wiring functionality of PHP-DI. \r\n\r\nThis piece of business logic is what you usually place into a Controller class but is optional since some pages only give output and do not execute business logic.\r\n\r\nWhen a string is provided to the `uses()` method will try to retrieve an object of that class from the DI Container and if a method is provided invoke that; if no method part is provided than it is required that the class is callable using the `__invoke()` method.\r\n\r\nIf the business logic returns a value than this will be passed to the responders as the first argument, see responder below for more info.\r\n\r\n### Summary with supported arguments\r\n\r\n1. A closure, the Command that handles this action will pass any options as argument to the closure\r\n2. An object with the `__invoke()` method, will be handled identically to the closure\r\n3. A regular callable such as an array with class/object and method, will be handled identically to the closure\r\n4. A string with an FQCN, an object will be retrieved from the DI Container (and as such injections are resolved automatically) and the `__invoke()` will be called after this it will be handled identically to the closure\r\n5. An array with an FQCN and method  (`[MyClass::class, 'methodName']`); identical to number 4 with the exception that not the `__invoke()` method is called but the given method. May be used to have more old-school controller classes that contain multiple actions, or to have an action class with different behaviour for different mime formats. The normal behaviour of PHP is to call a static method on the given class but if the given methodName is a non-static member than the an object of the given className will be retrieved from the Container first and then the method will be called non-statically\r\n\r\n## Responder\r\n\r\nResponder objects function technically identical to the business logic actions detailed above with the following exceptions:\r\n\r\n- Responders are responsible for mapping the data returned by the business logic into a response appropriate for the Command; as such the first argument or a responder is the data returned by the business logic or null is nothing is returned.\r\n- Responders may have additional options: the second (optional) argument of the `responds` method is an array of data that is passed as-is as the second argument of the responder method.\r\n- Responders are responsible for creating a response object or output that is applicable for the type of command that will invoke the action. As such an HTTP command will expect a Responder that will create an HTTP response and set that on the server "}}