将Eloquent对象作为JSON返回时动态隐藏某些列?

时间:2014-07-15 12:47:32

标签: laravel laravel-4 eloquent

在将Eloquent对象作为JSON返回时,如何动态隐藏某些列?例如。隐藏“密码”列:

$users = User::all();
return Response::json($users);

我知道我可以在模型中设置受保护的属性( $ hidden $ visible ),但如何动态设置?我可能想在不同的上下文中隐藏或显示不同的列。

9 个答案:

答案 0 :(得分:34)

$model->getHidden();
$model->setHidden(array $columns);

$model->setVisible(array $columns);

答案 1 :(得分:14)

我使用$ model-> setHidden(array $ columns)找到了解决问题的完整解决方案;

让我们说,例如,您想要在控制器中确切地确定要返回哪些字段。在返回模型数组之前,仅更新模型的隐藏会强制您遍历每个模型。当这些模型具有您想要改变的关系时,问题变得更加严重。您必须遍历每个模型,设置隐藏属性,然后为每个模型设置隐藏的关系。真是一团糟。

我的解决方案涉及为每个模型创建一个静态成员,当它出现时,在调用" toArray"之前更新可见/隐藏属性:

<?php

trait DynamicHiddenVisible {

    public static $_hidden = null;
    public static $_visible = null;

    public static function setStaticHidden(array $value) {
        self::$_hidden = $value;
        return self::$_hidden;
    }

    public static function getStaticHidden() {
        return self::$_hidden;
    }

    public static function setStaticVisible(array $value) {
        self::$_visible = $value;
        return self::$_visible;
    }

    public static function getStaticVisible() {
        return self::$_visible;
    }

    public static function getDefaultHidden() {
        return with(new static)->getHidden();
    }

    public static function geDefaultVisible() {
        return with(new static)->getVisible();
    }

    public function toArray()    {
        if (self::getStaticVisible())
            $this->visible = self::getStaticVisible();
        else if (self::getStaticHidden())
            $this->hidden = self::getStaticHidden();
        return parent::toArray();
    }

}

作为额外的奖励,我公开了一种方法,可以在模型的类中设置模型的默认隐藏/可见。

不要忘记添加特质

class Client extends Eloquent {
     use DynamicHiddenVisible;
}

最后,在控制器中,在返回模型之前,决定可见/隐藏属性:

public function getIndex($clientId) {
    // in this specific call, I would like to hide the "special_type" field of my Client model
    $hiddenFields = Client::getDefaultHidden();
    array_push($hiddenFields, "special_type");
    Client::setStaticHidden($hiddenFields);

    return Client::find($clientId)->toJson();
}

答案 2 :(得分:12)

来自Lavarel 5.3 Documentation

暂时修改属性可见性

如果您想在给定的模型实例上显示一些通常隐藏的属性,可以使用makeVisible方法。 makeVisible方法返回模型实例以方便方法链接:

return $user->makeVisible('attribute')->toArray();

同样,如果您想在给定的模型实例上隐藏一些典型的可见属性,您可以使用makeHidden方法。

return $user->makeHidden('attribute')->toArray();

答案 3 :(得分:10)

我不相信ORM的工作是担心表示逻辑,这就是JSON的作用。你需要将数据转换为各种类型以及隐藏内容,有时还需要创建一个缓冲区来安全地重命名。

您可以使用我为此构建的Fractal完成所有这些操作。

<?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\ItemResource
     */
    public function includeAuthor(Book $book)
    {
        $author = $book->author;

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

嵌入(包括)内容可能比你现在需要的多一点,但它也可以非常方便。

答案 4 :(得分:8)

除了@ deczo的回答 - 我觉得$hidden变量并非真正设计为动态使用。更多的是保护特定数据不被错误显示(例如“密码”)。

如果你想要特定的列 - 你应该只是使用一个select语句,只需获得你想要的特定列。

答案 5 :(得分:4)

在5.4中,您可以隐藏和显示属性:

$model->makeVisible('attribute');

$model->makeHidden('attribute');

Laravel docs

答案 6 :(得分:1)

对于Laravel 5.3或更高版本

如果您想使用单个语句临时隐藏或显示多个属性,则可以使用model->makeVisible()model->makeHidden()方法传递array of attributes

例如,隐藏多个属性

$user->makeHidden(["attribute1", "attribute2", "attribute3"]);

制作可见的多个属性

$user->makeVisible(["otherAttribute1", "otherAttribute2", "otherAttribute3"]);

答案 7 :(得分:1)

为此制作了一个使用模型策略的软件包。

https://github.com/salomoni/authorized-attributes

使用Salomoni\AuthorizedAttributes特征

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;
use Salomoni\AuthorizedAttributes;

class Post extends Model
{
    use AuthorizedAttributes;

    /**
     * The attributes that should be hidden for serialization.
     *
     * @var array
     */
    protected $hidden = ['author_comments'];
}

Create and register a model policy。在驼峰式案例中添加前缀为see的隐藏属性的方法。

namespace App\Policies;

use App\User;

class PostPolicy
{
    /**
     * Determine if a post author_comments-atrribute can be seen by the user.
     *
     * @param  \App\User  $user
     * @return bool
     */
    public function seeAuthorComments(User $user)
    {
        return $user->isAuthor();
    }
}

答案 8 :(得分:0)

在模型中:

protected $hidden = [
    'your_field_1',
    'your_field_2',
];