59

If I try declaring a property, like this:

public $quantity = 9;

...it doesn't work, because it is not considered an "attribute", but merely a property of the model class. Not only this, but also I am blocking access to the actually real and existent "quantity" attribute.

What should I do, then?

J. Bruni
  • 20,322
  • 12
  • 75
  • 92

6 Answers6

93

An update to this...

@j-bruni submitted a proposal and Laravel 4.0.x is now supporting using the following:

protected $attributes = array(
  'subject' => 'A Post'
);

Which will automatically set your attribute subject to A Post when you construct. You do not need to use the custom constructor he has mentioned in his answer.

However, if you do end up using the constructor like he has (which I needed to do in order to use Carbon::now()) be careful that $this->setRawAttributes() will override whatever you have set using the $attributes array above. For example:

protected $attributes = array(
  'subject' => 'A Post'
);

public function __construct(array $attributes = array())
{
    $this->setRawAttributes(array(
      'end_date' => Carbon::now()->addDays(10)
    ), true);
    parent::__construct($attributes);
}

// Values after calling `new ModelName`

$model->subject; // null
$model->end_date; // Carbon date object

// To fix, be sure to `array_merge` previous values
public function __construct(array $attributes = array())
{
    $this->setRawAttributes(array_merge($this->attributes, array(
      'end_date' => Carbon::now()->addDays(10)
    )), true);
    parent::__construct($attributes);
}

See the Github thread for more info.

Prashant Pokhriyal
  • 3,727
  • 4
  • 28
  • 40
cmfolio
  • 3,413
  • 1
  • 16
  • 13
  • Do you know how to make the value randomly generated rather than being the same every time the models gets instantiated? (this might be worth a separate question but I thought to comment first) – Petar Vasilev Oct 29 '15 at 12:57
  • 2
    @PetarVasilev You can use the `__construct` override way above and call a function that generates your random value when assigning it. – cmfolio Nov 05 '15 at 17:42
  • I did that but when the user was created no data was saved in the database apart from my random value – Petar Vasilev Nov 11 '15 at 12:47
  • @PetarVasilev Sounds like it might be a mass assignment issue, but probably best to open a new topic for it. – cmfolio Nov 12 '15 at 18:01
  • @cmfolio I made a separate question for it, here it is: http://stackoverflow.com/questions/33651063/default-random-value-in-laravel-models/33651321?noredirect=1#comment55077022_33651321 – Petar Vasilev Nov 12 '15 at 20:22
  • Be sure to call `$this->syncOriginal()` in `__construct` after setting `$this->attributes`; – Jacob May 17 '18 at 14:30
58

This is what I'm doing now:

protected $defaults = array(
   'quantity' => 9,
);

public function __construct(array $attributes = array())
{
    $this->setRawAttributes($this->defaults, true);
    parent::__construct($attributes);
}

I will suggest this as a PR so we don't need to declare this constructor at every Model, and can easily apply by simply declaring the $defaults array in our models...


UPDATE:

As pointed by cmfolio, the actual ANSWER is quite simple:

Just override the $attributes property! Like this:

protected $attributes = array(
   'quantity' => 9,
);

The issue was discussed here.

Prashant Pokhriyal
  • 3,727
  • 4
  • 28
  • 40
J. Bruni
  • 20,322
  • 12
  • 75
  • 92
  • J.Bruni, mind sharing the PR url? so we can keep track of it also :) – Loonb Jan 21 '14 at 10:30
  • @TianLoon, I've updated the answer. The original PR is here: https://github.com/laravel/framework/pull/2264 - I closed it myself after learning more about `$attributes` and acknowledging it was not necessary. See @cmfolio answer for details (he is using my proposed solution, because he needs to instantiate an object for one default). – J. Bruni Jan 21 '14 at 16:37
  • @J.Bruni hello, I was try by overrid the $attributes like your answer. when `dd()` the default attributes value show correctly. but the mutators attribute not work for this way. :/ i do this in laravel 5 – antoniputra Jun 04 '15 at 21:31
  • I was trying this, but initial value is vanished when using `A::where(...)->first()`. Only works when using `new A()`. x.x – nelson6e65 Oct 11 '22 at 04:37
8

I know this is really old, but I just had this issue and was able to resolve this using this site.

Add this code to your model

protected static function boot()
{
   parent::boot();

   static::creating(function ($model) {
        $model->user_id = auth()->id();
    });
}

Update/Disclaimer

This code works, but it will override the regular Eloquent Model creating Event

pbgneff
  • 111
  • 1
  • 4
1

Set the attribute value in the constructor:

public function __construct()
{
    $this->attributes['locale'] = App::currentLocale();
}
Tony
  • 9,672
  • 3
  • 47
  • 75
0

I use this for Laravel 8 (static and to dynamically change attributes)

<?php

namespace App\Models\Api;

use Illuminate\Database\Eloquent\Model;

class Message extends Model
{
    /**
     * Indicates if the model should be timestamped.
     *
     * @var bool
     */
    public $timestamps = false;


    protected static function defAttr($messages, $attribute){

        if(isset($messages[$attribute])){
            return $messages[$attribute];
        }

        $attributes = [ 
            "password" => "123",
            "created_at" => gmdate("Y-m-d H:i:s"),
        ];

        return $attributes[$attribute];
    }
    

    /**
     * The "booted" method of the model.
     *
     * @return void
     */
    protected static function booted()
    {
        static::creating(function ($messages) {
            $messages->password = self::defAttr($messages, "password");
            $messages->created_at = self::defAttr($messages, "created_at");
        });
    }

}
0

Laravel 7, 8, 9, 10, and Beyond

If you wish to set a default value when retrieving a property value from a model,

Add the following to your model:

protected static function booted()
{
    static::retrieved(function ($self) {
        $self->your_column ??= 'default_value';
    });
}

if you want to set value for creation just change retrieved to creating

Mwthreex
  • 913
  • 1
  • 11
  • 24