重构Eloquent Collection以获得更好的API访问权限

时间:2018-06-01 11:39:47

标签: php laravel eloquent

我正在开发基于Elequent ORM的REST API。 在请求单个对象时,我的查询返回类似的内容:

$data = $this->select('objects.*')->where('id', '=', $id)->get();

收藏品:

[
    {
        "id": 3414,
        "type": 3,
        "title": "Title",
        "shorttext": "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.",
        "spacetext": "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.",
        "description": "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua."

    }
]

所以我想将API返回的结构更改为:

[
    {
        "id": 3414,
        "type": 3,
        "text" {
            "title": "Title",
            "shorttext": "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.",
            "spacetext": "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.",
            "description": "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua."
        }

    }
]

通过这种方式,结构对于访问用户来说更加透明。当然,当通过GET请求单个对象以及对象列表时,这当然也可以工作。

我尝试通过mapToGroups()使用雄辩的地图集合,但我无处可去。

在使用Eloquent之前我使用的是Medoo。在那里我只需输入这样的模式数组,一切都完成了:

$this->schema = [
        'id', 
        'type',
        'text' => [
            'title',
            'shorttext',
            'spacetext',
            'description'
        ],
        'prices' => [
            'baseprice',
            '...

有没有一种很好的方法可以用雄辩的方式实现这一目标?

3 个答案:

答案 0 :(得分:2)

这取决于您使用的是什么版本的Laravel。对于Laravel的旧版本(5.4及以下版本),有一个名为Fractal的简单包,可以帮助您实现所需的目标。

  

Fractal为复杂提供了一个表示和转换层   数据输出,在RESTful API中找到的,并且工作得很好   与JSON。

以下是该代码的示例:

<div>
   <app-personaldetails></app-personaldetails>
   <app-contactdetails></app-contactdetails>
</div>

在较新版本(5.5+)中,您可以使用Eloquent Resources概念。

  

资源类表示单个模型   需要转换为JSON结构。例如,这是一个   简单的资源类:

<?php namespace App\Transformer;

use Acme\Model\Book;
use League\Fractal\TransformerAbstract;

class BookTransformer extends TransformerAbstract
{
    /**
     * List of resources possible to include
     *
     * @var array
     */
    protected $availableIncludes = [
        'author'
    ];

    /**
     * Turn this item object into a generic array
     *
     * @return array
     */
    public function transform(Book $book)
    {
        return [
            'id'    => (int) $book->id,
            'title' => $book->title,
            'year'    => (int) $book->yr,
            'links'   => [
                [
                    'rel' => 'self',
                    'uri' => '/books/'.$book->id,
                ]
            ],
        ];
    }

    /**
     * Include Author
     *
     * @return \League\Fractal\Resource\Item
     */
    public function includeAuthor(Book $book)
    {
        $author = $book->author;

        return $this->item($author, new AuthorTransformer);
    }
}

答案 1 :(得分:0)

试试这个:

$remove = ["title", "shorttext", "spacetext", "description"];
$data->map(function($a) use($remove){
    foreach ($remove as $value) {
        $a["text"][$value] = $a[$value];
        unset($a[$value]);
    }
    return $a;
});

答案 2 :(得分:0)

我认为您应该在attribute中添加额外model来处理此问题。所以你的model应该是这样的:

e.g。

use Illuminate\Database\Eloquent\Model;

class Objects extends Model {

    protected $appends = ['text']; 

    public function getTextAttribute(){
        return array("shorttext" => $this->shorttext, "spacetext" => $this->spacetext, "description" => $this->description);
    }
}

它会给你想要的结果。

但是你会发现所有三列也在JSON或Array的旁边。因此,如果不需要使用$hidden

,则需要将其设置为隐藏

e.g。

protected $hidden = ['shorttext', 'spacetext', 'description' ];  // add this line in your model if you want to hide these columns in response json or array.

请记住,如果您只是找到或获得模型,您仍然可以访问这些属性。它只会被设置为hidden when converted to JSON or Array或在回复时返回。 如果您想要显示它们,那么只需使用setVisible()方法。

e.g。

//Inside controller
$records = Objects->where('somekey', 'somevalue')->get() ; 
$records->setVisible(['shorttext', 'spacetext', 'description']);