2017-04-20 60 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); 

该文档非常好,它是非常直接的实施它。