想象一下,我有几个像这样的简单对象:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
public function posts()
{
return $this->hasMany("App\Post");
}
}
class Post extends Model
{
public function user()
{
return $this->belongsTo("App\User");
}
}
我们会说\App\Post
对象有一个名为jsondata
的数据库列,其中包含JSON编码的数据。当我想在解码该列的视图中显示用户的帖子时,我需要在控制器中执行此操作:
$posts = Auth::user()->posts()->get();
foreach ($posts as $post) {
$post->jsondata = json_decode($post->jsondata);
}
return view("user.show", ["posts"=>$posts]);
有没有办法避免我的控制器中的foreach
循环并在较低级别进行JSON解码?
我确信我可以在App\User::posts()
中执行此操作,但这对我需要显示解码数据的其他地方没有帮助。我尝试定义App\Post::get()
来覆盖父方法,但它不起作用,因为hasMany()
似乎根本不返回模型的实例。
答案 0 :(得分:3)
它可以在不同的地方/方式完成,但如果您希望此数据始终在每个地方解码并且每次检索Post模型或仅仅是mutator时,我建议在模型中使用此属性的附加。
请参阅https://laravel.com/docs/master/eloquent-mutators
在您的模型中,您可以定义:
protected $appends = [
'name_of_property'
];
// calculated / mutated field
public function getNameOfPropertyAttribute()
{
return jsondecode($this->jsondata);
}
然后,您可以随时访问此属性:
$后&GT; name_of_property
请注意从CamelCase到snake_case的转换以及从getNameOfPropertyAttribute转换为&gt; name_of_property。默认情况下,您需要遵守此约定以使其自动运行。
您可以将name_of_property和NameOfProperty替换为您想要的内容。
干杯
答案 1 :(得分:0)
在典型的Laravel方式中,他们实际上并未列出您可以投射的所有类型,但他们确实提到能够将JSON格式的数据库列转换为数组。稍微戳了一下the source,事实证明你可以对一个对象做同样的事情。所以我的答案,添加到App\Post
控制器,是:
/**
* The attributes that should be casted to native types.
*
* @var array
*/
protected $casts = ["jsondata"=>"object"];
这会自动进行解码并使原始数据可用。作为奖励,它在保存时会自动执行JSON编码!