2016-06-06 83 views
0

想象我有這樣幾個簡單的對象:如何覆蓋hasMany關係的結果?

<?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

亞歷山德羅的答案看起來是最好的;它指出了Laravel關於訪問器和增變器的文檔。但是,在頁面底部附近有一個更簡單的方法:attribute casting

在典型的Laravel時尚中,他們並沒有列出所有可以投射到的類型,但他們確實提到能夠將JSON格式的數據庫列轉換爲數組。通過the source有點戳,事實證明,你可以對一個對象做同樣的事情。所以我的答案,加入App\Post控制器,是這樣的:

/** 
* The attributes that should be casted to native types. 
* 
* @var array 
*/ 
protected $casts = ["jsondata"=>"object"]; 

這將自動進行解碼,使原始數據可用。作爲獎勵,它會在保存時自動執行JSON編碼!

+0

應該是更好還是不好。這取決於您是否還想保留編碼數據屬性。 Laravel爲您提供了許多方法來完成相同的事情,但並不總是最好的方法,但是對問題有好的或壞的方法 – Alessandro

3

它可以在不同的地方/方式完成,但是我建議在你的模型中使用這個屬性的append,如果你希望這個數據總是在任何地方解碼,並且每次你檢索Post模型,或者只是一個增變器。

看到https://laravel.com/docs/master/eloquent-mutators

在你的模型,你可以定義:

$後> name_of_property

注意從轉換:

protected $appends = [ 
    'name_of_property' 
]; 

// calculated/mutated field 
public function getNameOfPropertyAttribute() 
{ 
    return jsondecode($this->jsondata); 
} 

然後,您可以隨時訪問此屬性CamelCase轉換爲snake_case,並從getNameOfPropertyAttribute> name_of_property進行轉換。默認情況下,你需要尊重這個約定來使它自動工作。

您可以用相應的內容替換name_of_property和NameOfProperty。

乾杯

+0

感謝您的有用答案。它指出我更好的解決方案。 – miken32