Search code examples
phplaraveleloquentlaravel-query-builder

Laravel define a default key with value on Model


In my Laravel 8 project I have a model called Campaign, my front-end though is build in Vue JS so needs to have some keys on a Campaign for contextual purposes, such as opening and closing a dropdown menu when looping over the elements, a database column isn't nessecery for this.

I'd like to add some default key/value pairs to my Campaign model, for example: dropdown_is_open and should have a default value of false.

I came across the default attributes for a model and tried adding this but cannot see my new key on the object, what am I missing?

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;

class Campaign extends Model
{
    use HasFactory, SoftDeletes;

    /**
     * Indicates if the model's ID is auto-incrementing.
     *
     * @var bool
     */
    public $incrementing = false;

    /**
    * The table associated with the model.
    *
    * @var string
    */
    protected $table = 'campaigns';

    /**
     * The attributes that are mass assignable.
     *
     * @var array<int, string>
     */
    protected $fillable = [
        'campaign',
        'template'
    ];

    /**
     * The model's default values for attributes.
     *
     * @var array
     */
    protected $attributes = [
        'dropdown_is_open' => false
    ];
}

Index function in controller:

/**
 * Display a listing of the resource.
 *
 * @return \Illuminate\Http\Response
 */
public function index()
{
    $campaigns = Campaign::where('user_id', Auth::id())
                         ->orderBy('created_at', 'desc')
                         ->get();

    if (!$campaigns) {
        return response()->json([
            'message' => "You have no campaigns"
        ], 404);
    }

    return response()->json([
        'campaigns' => $campaigns
    ], 200);
}

I expect to see:

{
  campaign: 'my campaign',
  template: '',
  dropdown_is_open: false <-- my key
}

Previously I was doing a foreach in my index function and adding the contextual keys on each item, but this would only show for the index function and I'd have to add it everywhere.


Solution

  • I hope something like below helps.

    Change it from my_custom_field to dropdown_is_open key (and from getMyCustomFieldAttribute to getDropdownIsOpenAttribute method-name).

    Custom attribute (or Accessor)

    <?php
    
    namespace App\Models;
    
    use Illuminate\Database\Eloquent\Model;
    
    class User extends Model {
        protected $appends = ['my_custom_field'];
    
        public function getMyCustomFieldAttribute()
        {
            return false;
        }
    }
    

    The $appends in above is required only, to ensure that my_custom_field is preset/cached, and even sent as JSON-Response.