web-dev-qa-db-fra.com

Masquer dynamiquement certaines colonnes lors du retour d'un objet Eloquent au format JSON?

Comment masquer dynamiquement certaines colonnes lors du retour d'un objet Eloquent en JSON? Par exemple. pour masquer la colonne "mot de passe":

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

Je sais que je peux définir des propriétés protégées dans le modèle ($ hidden ou $ visible), mais comment les définir dynamiquement? Je pourrais vouloir cacher ou afficher différentes colonnes dans différents contextes.

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

$model->setVisible(array $columns);
35
Jarek Tkaczyk

J'ai trouvé une solution complète au problème de l'utilisation de $ model-> setHidden (array $ columns);

Disons, par exemple, que vous souhaitez décider exactement dans le contrôleur quels champs retourner. La mise à jour uniquement du modèle caché vous oblige à parcourir chaque modèle avant de renvoyer un tableau de modèles par exemple. Le problème devient encore pire lorsque ces modèles ont des relations que vous aimeriez également changer. Vous devez faire une boucle sur chaque modèle, définir l'attribut caché, puis définir pour chacun les relations masquées. Quel bordel.

Ma solution consiste à créer un membre statique pour chaque modèle qui, lorsqu'il est présent, met à jour l'attribut visible/caché juste avant l'appel à "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();
    }

}

En prime, j'expose un moyen de masquer/visible par défaut du modèle que vous avez peut-être défini dans la classe de votre modèle.

N'oubliez pas d'ajouter le trait

class Client extends Eloquent {
     use DynamicHiddenVisible;
}

Enfin, dans le contrôleur, avant de retourner votre modèle, décidez des attributs visibles/cachés:

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();
}
14
NiRR

De Documentation Lavarel 5. :

Modification temporaire de la visibilité des attributs

Si vous souhaitez rendre certains attributs généralement masqués visibles sur une instance de modèle donnée, vous pouvez utiliser la méthode makeVisible. La méthode makeVisible renvoie l'instance de modèle pour un chaînage de méthode pratique:

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

De même, si vous souhaitez masquer certains attributs généralement visibles sur une instance de modèle donnée, vous pouvez utiliser la méthode makeHidden.

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

Je ne pense pas que c'est le travail de l'ORM de s'inquiéter de la logique de présentation, et c'est ce qu'est le JSON. Vous devrez toujours convertir des données en différents types, masquer des éléments et parfois créer une zone tampon pour renommer les éléments en toute sécurité.

Vous pouvez faire tout cela avec Fractal que j'ai construit exactement pour cette raison.

<?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);
    }
}

L'intégration (y compris) de trucs peut être un peu plus que ce dont vous avez besoin en ce moment, mais cela peut aussi être très pratique.

10
Phil Sturgeon

En plus de la réponse de @ deczo - je sens que le $hidden la variable n'est pas vraiment conçue pour être utilisée dynamiquement. Il s'agit davantage de protéger des données spécifiques contre tout affichage incorrect (tel que "mot de passe").

Si vous voulez des colonnes spécifiques - vous devriez probablement simplement utiliser une instruction select et obtenir simplement les colonnes spécifiques que vous voulez.

8
Laurence

Dans 5.4, vous pouvez masquer et afficher les attributs dynamiquement:

$model->makeVisible('attribute');

$model->makeHidden('attribute');

Documents Laravel

5
Luca C.

Pour Laravel 5.3 ou version supérieure,

Si vous souhaitez rendre plusieurs attributs temporaires masqués ou visibles à l'aide d'une seule instruction, vous pouvez utiliser les méthodes model->makeVisible() et model->makeHidden() en passant array of attributes.

Par exemple, pour masquer plusieurs attributs,

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

Et pour rendre visibles plusieurs attributs,

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

Créé un package pour cela qui utilise des stratégies de modèle.

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


Utilisez le Salomoni\AuthorizedAttributes trait

<?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'];
}

Créer et enregistrer une politique modèle . Ajoutez des méthodes pour les attributs cachés dans le cas de chameau préfixé avec 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();
    }
}
1
Jari Pekkala