2017-04-20 58 views
0

自定義字段名稱我有一個表posts這個表有像pst_idpst_titlepst_contentpst_category_id和這樣的一些列。我想用json輸出中的一些更好的名稱來表示這些字段,實際上我試圖從列名稱中刪除前綴pst_上雄辯型號

我測試了多種方式。起初,我試圖爲DB層上的這些列創建別名,例如Post::select(['pst_id as id'])->get()。這個想法通常很糟糕,因爲它使得軟件的列名不一致(每個開發人員可能有一個命名字段的約定)。所以我堅持要爲模型層上的列命名。

下一個解決方案是使用AccessorsMutators。儘管它涵蓋了以前的問題,但是對於每個模型實現20個方法真的很難! 20x100〜2000的方法! :/

我測試的最後一個解決方案是關於使用https://github.com/jarektkaczyk/eloquencemappable功能。這真的很不錯,我可以把所有舊字段放到$hidden屬性中,然後在$appends中添加新字段以顯示輸出。但是這個解決方案也有問題。如果我將所有新字段添加到$appends,則當我使用select語句選擇某些列時,未選擇的列將在輸出中顯示,其值爲null |。那麼,我試圖在基礎模型上重寫mappedselectparseMappings方法來動態地將新名稱添加到$appends,但它不符合我的要求。事實上,它的使用變得非常棘手,我不確定團隊可以接受並輕鬆使用它。

所以這就是問題所在:「有沒有一種方法可以重新命名輸出中的列的名稱以提供口才?」。 GoLang有一個非常好的特性叫做Struct Tags。你可以定義一些標籤爲您的結構,例如像這樣:

type Post struct { 
    Pst_id   int  `json:"id"` 
    Pst_title   string `json:"title"` 
    Pst_content  string `json:"content"` 
} 

而當你產生一個JSON的Post結構json.Marshal,根據標籤,它給你這樣一個JSON:

{ 
    "id": 23, 
    "title": "Custom Field Tags for Eloquent", 
    "content": "I tried a lot of things, but they are hard. I'm a programmer so I'm lazy! What can I do?", 
} 

我認爲我們在php世界沒有這樣的東西,但是有什麼辦法可以使用doctrine's annotation背後的想法來實現類似Go中的標籤結構嗎?

歡迎任何意見和想法!

回答

1

第一步是重寫這些模型上的幾個方法。第一種方法是getAttribute(),當您訪問模型的屬性時可調用該屬性,以便您可以訪問它。你會希望能夠在無pst_前綴訪問屬性,這樣你會做:

public function getAttribute($key) 
{ 
    if(array_key_exists($prefixedKey = 'pst_'.$key, $this->attributes)) { 
     return $this->attributes[$prefixedKey]; 
    } 

    return parent::getAttribute($key); 
} 

然後確保鑄造JSON你會重寫attributesToArray()方法也就是當鍵沒有前綴當輸出json時會被調用,並且還會尊重您的$hidden$visible$casts$dates陣列。這將是這樣的:

public function attributesToArray() 
{ 
    $attributes = parent::attributesToArray(); 

    $mutated = []; 
    foreach ($attributes as $key => $value) { 
     $mutated[preg_replace('/^pst_/', '', $key)] = $value; 
    } 

    return $mutated; 
} 

要實現這些,你可以實現這些方法的抽象類擴展Model類和你的類擴展基類或者創建擁有這些方法的性狀,有你的類實現那個特質。

+0

我喜歡你的方法!事實上,我是laravel的新手,我並沒有意識到在對話中將對象轉換爲數組的機制。我認爲重寫這些方法和其他一些方法(如與'select'方法有關的方法),我可以達到我的目標!謝謝! – meysam

1

我可能會使用聯盟的Fractal Transformer

您基本上創建一個映射類並將其應用於集合。

Transformer類是這樣的

<?php 

namespace App; 

use App\Post; 
use League\Fractal; 
use League\Fractal\TransformerAbstract; 

class PostTransformer extends TransformerAbstract{ 

    public function transform(Post $post) 
    { 
     return [ 
      'id'  => (int) $post->pst_id, 
      'title' => $post->pst_name, 
      'content' => $post->pst_uuid, 
     ]; 
    } 
} 

然後在您的控制器或任何你變換的集合,其中。

$posts = Post::all(); 
$manager = new Manager(); 
$manager->setSerializer(new CursorSerializer()); 
$resource = new Collection($posts, new PostTransformer()); 
$formattedCollection = $manager->createData($resource); 

該文檔非常好,它是非常直接的實施它。