{"action":"created","issue":{"url":"https://api.github.com/repos/laravel/ideas/issues/1275","repository_url":"https://api.github.com/repos/laravel/ideas","labels_url":"https://api.github.com/repos/laravel/ideas/issues/1275/labels{/name}","comments_url":"https://api.github.com/repos/laravel/ideas/issues/1275/comments","events_url":"https://api.github.com/repos/laravel/ideas/issues/1275/events","html_url":"https://github.com/laravel/ideas/issues/1275","id":349315524,"node_id":"MDU6SXNzdWUzNDkzMTU1MjQ=","number":1275,"title":"[proposal] allow indirect modification of overloaded JSON model attributes","user":{"login":"judahnator","id":8620392,"node_id":"MDQ6VXNlcjg2MjAzOTI=","avatar_url":"https://avatars2.githubusercontent.com/u/8620392?v=4","gravatar_id":"","url":"https://api.github.com/users/judahnator","html_url":"https://github.com/judahnator","followers_url":"https://api.github.com/users/judahnator/followers","following_url":"https://api.github.com/users/judahnator/following{/other_user}","gists_url":"https://api.github.com/users/judahnator/gists{/gist_id}","starred_url":"https://api.github.com/users/judahnator/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/judahnator/subscriptions","organizations_url":"https://api.github.com/users/judahnator/orgs","repos_url":"https://api.github.com/users/judahnator/repos","events_url":"https://api.github.com/users/judahnator/events{/privacy}","received_events_url":"https://api.github.com/users/judahnator/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":1,"created_at":"2018-08-09T22:36:51Z","updated_at":"2018-08-10T19:38:36Z","closed_at":null,"author_association":"NONE","body":"I have been working on a side project where I have multiple JSON columns on a given model. You can see an example of that functionality in [the Laravel docs](https://laravel.com/docs/5.6/eloquent-mutators#array-and-json-casting).\r\n\r\nAs I am sure you folks know, you cannot really manipulate the overloaded JSON object. You have to copy the data, manipulate it, then replace it. Like this:\r\n```php\r\nclass myModel extends Model\r\n{\r\n  protected $casts = ['json_field' => 'array'];\r\n}\r\n$json_data = $myModel->json_field;\r\n$json_data->foo->bar = 'baz';\r\n$myModel->json_field = $json_data;\r\n```\r\n\r\nIt would be much easier to do this:\r\n```php\r\n$myModel->json_field->foo->bar = 'baz';\r\n```\r\nUnfortunately that gives an error about indirect modification of overloaded properties.\r\n\r\nIn another library I wrote I worked around this issue in a bit of a hacky way, but it would be a killer feature to implement natively into Laravel core.\r\n\r\n[Here](https://gitlab.com/judahnator/json-manipulator) is the library I wrote for reference. If you are curious about its workings you can give it a peek, but the short version is that it holds a refrence to the original json string and whenever data is manipulated it updates the original string it was holding onto. What I propose is to to implement something similar to the way I integrated that library into [this other library](https://gitlab.com/judahnator/laravel-metadata/blob/master/src/HasMetadata.php#L27).\r\n\r\nI do not believe a change like this would be a breaking change, as the element remains as a literal string in the model attributes array. I might be a bit biased though. My code is perfect according to me and all that.\r\n\r\nIs this a feature the Laravel community would be interested in? Not in integrating my specific library, thats just for an example, but in adding the ability to manipulate JSON columns as object directly, instead of indirectly.\r\n\r\nIf there is interest for this feature, what would be the next steps? Does anyone have feedback, how should we attack this problem, etc. I want to do things \"the Laravel way.\""},"comment":{"url":"https://api.github.com/repos/laravel/ideas/issues/comments/412184691","html_url":"https://github.com/laravel/ideas/issues/1275#issuecomment-412184691","issue_url":"https://api.github.com/repos/laravel/ideas/issues/1275","id":412184691,"node_id":"MDEyOklzc3VlQ29tbWVudDQxMjE4NDY5MQ==","user":{"login":"judahnator","id":8620392,"node_id":"MDQ6VXNlcjg2MjAzOTI=","avatar_url":"https://avatars2.githubusercontent.com/u/8620392?v=4","gravatar_id":"","url":"https://api.github.com/users/judahnator","html_url":"https://github.com/judahnator","followers_url":"https://api.github.com/users/judahnator/followers","following_url":"https://api.github.com/users/judahnator/following{/other_user}","gists_url":"https://api.github.com/users/judahnator/gists{/gist_id}","starred_url":"https://api.github.com/users/judahnator/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/judahnator/subscriptions","organizations_url":"https://api.github.com/users/judahnator/orgs","repos_url":"https://api.github.com/users/judahnator/repos","events_url":"https://api.github.com/users/judahnator/events{/privacy}","received_events_url":"https://api.github.com/users/judahnator/received_events","type":"User","site_admin":false},"created_at":"2018-08-10T19:38:36Z","updated_at":"2018-08-10T19:38:36Z","author_association":"NONE","body":"Sure, [here is an example](https://gitlab.com/judahnator/laravel-metadata/blob/master/src/HasMetadata.php#L22-28) I am using in one of the projects I mentioned. It depends on this json manipulation library to do its work.\r\n\r\nAdding on my example above, you could do something like this and it would work.\r\n\r\n```php\r\n<?php\r\n\r\nuse Illuminate\\Database\\Eloquent\\Model;\r\nuse function judahnator\\JsonManipulator\\load_json;\r\n\r\nclass MyModel extends Model\r\n{\r\n\r\n  protected $fillable = ['json_field'];\r\n  public $timestamps = false;\r\n\r\n  public function getJsonFieldAttribute()\r\n  {\r\n    return load_json($this->attributes['json_field']);\r\n  }\r\n\r\n}\r\n\r\n// Create model\r\n$newModel = MyModel::create(['json_field' => '{\"foo\":{\"bar\":\"baz\"}}']);\r\n\r\n// Sanity check, make sure the json value is actually there\r\necho $newModel->json_field; // {\"foo\":{\"bar\":\"baz\"}}\r\n\r\n// Update a nested value\r\n$newModel->json_field->foo->bar = \"new value\";\r\necho $newModel->json_field; // {\"foo\":{\"bar\":\"new value\"}}\r\n\r\n// Save, to make sure persisting the data works\r\n$newModel->save();\r\n\r\n// We can see the data has persisted\r\necho MyModel::find($newModel->id)->json_field; // {\"foo\":{\"bar\":\"new value\"}}\r\n```\r\n\r\nYou can see its as easy as adding a quick accessor. Literally a one-liner, if you don't count the several dozen lines of code working behind the scenes.\r\n\r\nIt feels like something that should be taken care of by a cast rather than an accessor though."}}
{"actor":{"display_login":"judahnator"}}