J'aimerais pouvoir ajouter un attribut/une propriété personnalisée à un modèle Laravel/Eloquent lors de son chargement, comme cela pourrait être réalisé avec la méthode RedBean's$model->open()
.
Par exemple, pour le moment, dans mon contrôleur, j'ai:
public function index()
{
$sessions = EventSession::all();
foreach ($sessions as $i => $session) {
$sessions[$i]->available = $session->getAvailability();
}
return $sessions;
}
Ce serait bien de pouvoir omettre la boucle et d'avoir l'attribut «disponible» déjà défini et rempli.
J'ai essayé d'utiliser certains des événements de modèle décrits dans la documentation pour associer cette propriété au chargement de l'objet, mais sans succès jusqu'à présent.
Remarques:
$sessions
est renvoyé en tant qu'objet JSON en tant qu'élément d'une API. Par conséquent, appeler quelque chose comme $session->available()
dans un modèle n'est pas une option.Le problème est dû au fait que la méthode toArray()
de la Model
ignore tous les accesseurs qui ne sont pas directement liés à une colonne de la table sous-jacente.
Comme Taylor Otwell a mentionné ici , "C’est intentionnel et pour des raisons de performance." Cependant, il existe un moyen simple d'y parvenir:
class EventSession extends Eloquent {
protected $table = 'sessions';
protected $appends = array('availability');
public function getAvailabilityAttribute()
{
return $this->calculateAvailability();
}
}
Tous les attributs répertoriés dans la propriété $ appends seront automatiquement inclus dans le tableau ou la forme JSON du modèle, à condition que vous ayez ajouté l'accesseur approprié.
Ancienne réponse (pour les versions de Laravel <4.08):
La meilleure solution que j'ai trouvée consiste à remplacer la méthode toArray()
et à définir explicitement l'attribut:
class Book extends Eloquent {
protected $table = 'books';
public function toArray()
{
$array = parent::toArray();
$array['upper'] = $this->upper;
return $array;
}
public function getUpperAttribute()
{
return strtoupper($this->title);
}
}
ou, si vous avez beaucoup d’accesseurs personnalisés, parcourez-les tous et appliquez-les:
class Book extends Eloquent {
protected $table = 'books';
public function toArray()
{
$array = parent::toArray();
foreach ($this->getMutatedAttributes() as $key)
{
if ( ! array_key_exists($key, $array)) {
$array[$key] = $this->{$key};
}
}
return $array;
}
public function getUpperAttribute()
{
return strtoupper($this->title);
}
}
Le dernière chose sur la page de la documentation de Laravel Eloquent } est:
protected $appends = array('is_admin');
Cela peut être utilisé automatiquement pour ajouter de nouveaux accesseurs au modèle sans aucun travail supplémentaire tel que la modification de méthodes telles que ::toArray()
.
Créez simplement l'accesseur getFooBarAttribute(...)
et ajoutez le tableau foo_bar
au tableau $appends
.
Si vous renommez votre méthode getAvailability()
en getAvailableAttribute()
, votre méthode devient un accessor et vous pourrez le lire à l'aide de ->available
directement sur votre modèle.
Docs: https://laravel.com/docs/5.4/eloquent-mutators#accessors-and-mutators
EDIT: comme votre attribut est "virtuel", il n’est pas inclus par défaut dans la représentation JSON de votre objet.
Mais j'ai trouvé ceci: Les accesseurs de modèles personnalisés ne sont pas traités quand -> toJson () appelé?
Afin de forcer le renvoi de votre attribut dans le tableau, ajoutez-le en tant que clé au tableau $ attributs.
class User extends Eloquent {
protected $attributes = array(
'ZipCode' => '',
);
public function getZipCodeAttribute()
{
return ....
}
}
Je ne l'ai pas testé, mais cela devrait être assez simple pour vous d'essayer dans votre configuration actuelle.
J'avais quelque chose de similaire: J'ai une image d'attribut dans mon modèle, elle contient l'emplacement du fichier dans le dossier de stockage . L'image doit être retournée codée en base64
//Add extra attribute
protected $attributes = ['pictureData'];
//Make it available in the json response
protected $appends = ['pictureData'];
//implement the attribute
public function getPictureDataAttribute()
{
$file = Storage::get($this->picture);
$type = Storage::mimeType($this->picture);
return "data:" . $type . ";base64," . base64_encode($file);
}
vous pouvez utiliser la fonction setAttribute
dans Model pour ajouter un attribut personnalisé
Supposons que vous avez 2 colonnes nommées first_name et last_name dans votre table d'utilisateurs et que vous voulez récupérer le nom complet. vous pouvez réaliser avec le code suivant:
class User extends Eloquent {
public function getFullNameAttribute()
{
return $this->first_name.' '.$this->last_name;
}
}
maintenant vous pouvez obtenir le nom complet en tant que:
$user = User::find(1);
$user->full_name;
dans mon cas, créer une colonne vide et paramétrer son accesseur a bien fonctionné . mon accesseur en remplissant l'âge de l'utilisateur à partir de la colonne dob. La fonction toArray () a également fonctionné.
public function getAgeAttribute()
{
return Carbon::createFromFormat('Y-m-d', $this->attributes['dateofbirth'])->age;
}
Dans mon modèle d’abonnement, j’ai besoin de savoir si l’abonnement est en pause ou non. public function getIsPausedAttribute() {
$isPaused = false;
if (!$this->is_active) {
$isPaused = true;
}
}
ensuite, dans le modèle de vue, je peux utiliser $subscription->is_paused
pour obtenir le résultat.
getIsPausedAttribute
est le format pour définir un attribut personnalisé,
et utilise is_paused
pour obtenir ou utiliser l'attribut dans votre vue.