Php Elount模型上的自定义字段名

Php Elount模型上的自定义字段名,php,laravel,laravel-5,eloquent,Php,Laravel,Laravel 5,Eloquent,我有一个表posts,这个表有一些列,比如pst\u id,pst\u title,pst\u content,pst\u category\u id等等。我想在json输出中用一些更好的名称表示这些字段,实际上我正在尝试从列名中删除前缀pst 我测试了多种方法。起初,我试图在DB层上为这些列创建一个别名,例如Post::select(['pst\u id as id'])->get()。这种想法通常很糟糕,因为它使整个软件中的列名不一致(每个开发人员可能都有命名字段的约定)。所以我坚持要找到一

我有一个表
posts
,这个表有一些列,比如
pst\u id
pst\u title
pst\u content
pst\u category\u id
等等。我想在json输出中用一些更好的名称表示这些字段,实际上我正在尝试从列名中删除前缀
pst

我测试了多种方法。起初,我试图在DB层上为这些列创建一个别名,例如
Post::select(['pst\u id as id'])->get()
。这种想法通常很糟糕,因为它使整个软件中的列名不一致(每个开发人员可能都有命名字段的约定)。所以我坚持要找到一种方法来命名模型层上的列

下一个解决方案是使用
访问器
变异器
。虽然它涵盖了前一种方法的问题,但要为每个模型实现20种方法确实很困难!20x100~2000种方法!!!:/

我测试的最后一个解决方案是关于使用的
mappable
特性。这真的很好,我可以将所有旧字段放到
$hidden
属性中,并将新字段添加到
$appends
中,以便在输出时显示。但是这个解决方案也有一个问题。如果我将所有新字段添加到
$appends
,当我使用
select
语句选择某些列时,未选择的列将在输出时显示为
null
值:|。嗯,我尝试在一个基本模型上重写
mappedselect
parseMappings
方法,以便动态地将新名称添加到
$appends
,但我并不满意。事实上,它在使用上变得非常棘手,我不确定团队是否能够接受它并轻松地使用它

这就是问题所在:“有没有办法为eloquent重命名输出列的名称?”。GoLang有一个非常好的特性,称为结构标记。可以为结构定义一些标记,例如:

type Post struct {
  Pst_id            int       `json:"id"`
  Pst_title         string    `json:"title"`
  Pst_content       string    `json:"content"`
}
{
  "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?",
}
当您使用
json.Marshal
Post
结构生成json时,基于标记,它将为您提供如下json:

type Post struct {
  Pst_id            int       `json:"id"`
  Pst_title         string    `json:"title"`
  Pst_content       string    `json:"content"`
}
{
  "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世界中没有类似的东西,但是有没有任何方法可以使用后面的思想在Go中实现类似于标记结构的东西

欢迎任何意见和想法

我可能会用联盟的

基本上创建一个映射类并将其应用于集合

$posts = Post::all();
$manager = new Manager();
$manager->setSerializer(new CursorSerializer());
$resource = new Collection($posts, new PostTransformer());
$formattedCollection = $manager->createData($resource);
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);
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,
        ];
    }
}

这些文档非常好,实现起来非常简单。

第一步是覆盖这些模型上的几个方法。第一个方法是,当您访问模型的属性时,将调用该方法,以便您可以访问它。您希望能够在不使用
pst\uu
前缀的情况下访问该属性,因此可以执行以下操作:

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

    return parent::getAttribute($key);
}
然后,为了确保在强制转换为json时键没有前缀,您将覆盖输出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;
}

要实现这些特性,您可以使用实现这些方法的抽象类扩展
模型
类,并让您的类扩展该基类,或者使用这些方法创建特性,并让您的类实现该特性。

第一步是覆盖这些模型上的两个方法。第一个方法是,当您访问模型的属性时,将调用该方法,以便您可以访问它。您希望能够在不使用
pst\uu
前缀的情况下访问该属性,因此可以执行以下操作:

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

    return parent::getAttribute($key);
}
然后,为了确保在强制转换为json时键没有前缀,您将覆盖输出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;
}

要实现这些,您可以使用实现这些方法的抽象类扩展
模型
类,让您的类扩展基类,或者使用这些方法创建特性,让您的类实现该特性。

我喜欢您的方法!事实上,我是laravel的新手,我不知道将对象转换成数组的机制。我认为通过覆盖这些方法和其他一些方法(比如与
select
method相关的方法),我可以实现我的目标!谢谢我喜欢你的方法!事实上,我是laravel的新手,我不知道将对象转换成数组的机制。我认为通过覆盖这些方法和其他一些方法(比如与
select
method相关的方法),我可以实现我的目标!谢谢