{"action":"created","issue":{"url":"https://api.github.com/repos/laravel/framework/issues/18502","repository_url":"https://api.github.com/repos/laravel/framework","labels_url":"https://api.github.com/repos/laravel/framework/issues/18502/labels{/name}","comments_url":"https://api.github.com/repos/laravel/framework/issues/18502/comments","events_url":"https://api.github.com/repos/laravel/framework/issues/18502/events","html_url":"https://github.com/laravel/framework/pull/18502","id":217079588,"number":18502,"title":"[5.5] [WIP] Transformable Responses","user":{"login":"Aferz","id":8954655,"avatar_url":"https://avatars3.githubusercontent.com/u/8954655?v=3","gravatar_id":"","url":"https://api.github.com/users/Aferz","html_url":"https://github.com/Aferz","followers_url":"https://api.github.com/users/Aferz/followers","following_url":"https://api.github.com/users/Aferz/following{/other_user}","gists_url":"https://api.github.com/users/Aferz/gists{/gist_id}","starred_url":"https://api.github.com/users/Aferz/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Aferz/subscriptions","organizations_url":"https://api.github.com/users/Aferz/orgs","repos_url":"https://api.github.com/users/Aferz/repos","events_url":"https://api.github.com/users/Aferz/events{/privacy}","received_events_url":"https://api.github.com/users/Aferz/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":1,"created_at":"2017-03-26T18:49:05Z","updated_at":"2017-03-26T21:40:34Z","closed_at":null,"pull_request":{"url":"https://api.github.com/repos/laravel/framework/pulls/18502","html_url":"https://github.com/laravel/framework/pull/18502","diff_url":"https://github.com/laravel/framework/pull/18502.diff","patch_url":"https://github.com/laravel/framework/pull/18502.patch"},"body":"### Why ?\r\n\r\nThe purpose of this pull request is to give Laravel better flexibility when responding to API requests.\r\n\r\nI have created a new `TransformableResponse` class that allows to define a ruleset for transform the response that will be passed to the client.\r\n\r\nAs you all could observe, my inspiration was given by `FormRequest` class. If we can define Requests individually, why don't extend this behaviour to responses?\r\n\r\nI suggest to store our response classes inside `app/Http/Responses` folder.\r\n\r\n### Quick Example\r\n\r\n`GetUsersResponse` class:\r\n\r\n```php\r\n<?php\r\n\r\nnamespace App\\Http\\Responses;\r\n\r\nuse Illuminate\\Http\\TransformableResponse;\r\n\r\nclass GetUsersResponse extends TransformableResponse\r\n{\r\n    /**\r\n     * Define the rules that will apply to this transformer\r\n     * response.\r\n     *\r\n     * @return array\r\n     */\r\n    public function rules()\r\n    {\r\n        return [\r\n            'id' => true,\r\n            'posts' => true,\r\n            'posts.*.title' => false,\r\n            'posts.*.comments.*.title' => false\r\n        ];\r\n    }\r\n}\r\n```\r\n\r\nAs you can see we can define which data will be shown and which won't. `dot notation` and `array notation` can be used as you used in your own `Form Requests`.\r\n\r\nNext, let's define a `UsersController`:\r\n\r\n```php\r\n<?php\r\n\r\nnamespace App\\Http\\Controllers;\r\n\r\nuse App\\Http\\Responses\\GetUsersResponse;\r\n\r\nclass UsersController extends Controller\r\n{\r\n    public function get()\r\n    {\r\n        // Of course, here we'll use User::all(). For demo purposes, we will use this array\r\n        $users = [\r\n            'id' => 1,\r\n            'name' => 'Name #1',\r\n            'surname' => 'Surname #1',\r\n            'posts' => [\r\n                [\r\n                    'id' => 1,\r\n                    'title' => 'Post #1',\r\n                    'comments' => [\r\n                        [\r\n                            'id' => 1,\r\n                            'title' => 'Comment #1-1'\r\n                        ]\r\n                    ]\r\n                ],\r\n                [\r\n                    'id' => 2,\r\n                    'title' => 'Post #2',\r\n                    'comments' => [\r\n                        [\r\n                            'id' => 1,\r\n                            'title' => 'Comment #2-1'\r\n                        ]\r\n                    ]\r\n                ]\r\n            ]\r\n        ];\r\n        \r\n        return new GetUsersResponse($users);\r\n    }\r\n}\r\n```\r\n\r\nThe result of this response:\r\n\r\n```json\r\n{  \r\n   \"id\":1,\r\n   \"name\":\"Name #1\",\r\n   \"posts\":[  \r\n      {  \r\n         \"title\":\"Post #1\",\r\n         \"comments\":[  \r\n            {  \r\n               \"title\":\"Comment #1-1\"\r\n            }\r\n         ]\r\n      },\r\n      {  \r\n         \"title\":\"Post #2\",\r\n         \"comments\":[  \r\n            {  \r\n               \"title\":\"Comment #2-1\"\r\n            }\r\n         ]\r\n      }\r\n   ]\r\n}\r\n```\r\n\r\n\r\n### How does this work ?\r\n\r\nEasy. As you can see in the rules section you define which attributes should be visible and which attributes should be hidden.\r\n\r\nAttributes that will be shown, will evaluate first. If none attribute is checked for display, all will be shown by default.\r\n\r\nNext, attributes that are checked for hiding will hide the data passed from the previous process.\r\n\r\nAttributes marked as false will prevail those marked as visible.\r\n\r\nSimple.\r\n\r\n\r\n### Why is a WIP ?\r\n\r\nBecause there are few thing to do I will make if Laravel community thinks this is something useful or necessary.\r\n\r\nTODO:\r\n* Make it work with Paginators\r\n* Tests\r\n* Feedback, of course.\r\n\r\nLet me know what you all think.\r\n\r\nThanks !"},"comment":{"url":"https://api.github.com/repos/laravel/framework/issues/comments/289318555","html_url":"https://github.com/laravel/framework/pull/18502#issuecomment-289318555","issue_url":"https://api.github.com/repos/laravel/framework/issues/18502","id":289318555,"user":{"login":"Aferz","id":8954655,"avatar_url":"https://avatars3.githubusercontent.com/u/8954655?v=3","gravatar_id":"","url":"https://api.github.com/users/Aferz","html_url":"https://github.com/Aferz","followers_url":"https://api.github.com/users/Aferz/followers","following_url":"https://api.github.com/users/Aferz/following{/other_user}","gists_url":"https://api.github.com/users/Aferz/gists{/gist_id}","starred_url":"https://api.github.com/users/Aferz/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Aferz/subscriptions","organizations_url":"https://api.github.com/users/Aferz/orgs","repos_url":"https://api.github.com/users/Aferz/repos","events_url":"https://api.github.com/users/Aferz/events{/privacy}","received_events_url":"https://api.github.com/users/Aferz/received_events","type":"User","site_admin":false},"created_at":"2017-03-26T21:40:34Z","updated_at":"2017-03-26T21:40:34Z","body":"Yeah, before make this PR o reviewed Fractal, but IMO I think that It doesn't really fit with a nice Laravel approach. For me It was too verbose.\r\n\r\nI thought that filter through data needed to be easier, that's why I used validation rules style w\\ custom atomic clases to represent a specific response for a request instead of injecting multiple classes.\r\n\r\nThanks for your feedback!!"}}
{"actor":{"display_login":"Aferz"}}