0

Basically let's say I have a model named 'Window'. I know laravel provides created event for new instances of the model, the problem is I don't always first create new database records so that the method is called, but I sometimes need to create an instance of the facade first. What I mean:

$window = App\Window::create(); //this creates a new record in the 
//database and the 'created' event is being called in laravel, 
//so I can assign some properties. Everything is ok
$window = new App\Window;//but this only creates an instance of the facade 
//which is not being saved until `$window->save();` is called.

The ting is that in my code so far I've avoided directly creating new empty records in the database, so I've used the second method. But now I'd like to handle that creation of new App\Window in order to assign custom default properties for each window programatically. Is there a way to achieve it?

D. Petrov
  • 1,147
  • 15
  • 27

2 Answers2

2

This should work. It will only apply defaults if they aren't already passed in. I also set the default values up as constants so if you need to modify them later, they are easy to find.

const COLUMN_DEFAULT = 'some default';

const SOME_OTHER_COLUMN_DEFAULT = 'some other default';

public function __construct(array $attributes = [])
{
    if (! array_key_exists('your_column', $attributes)) {
        $attributes['your_column'] = static::COLUMN_DEFAULT;
    }

    if (! array_key_exists('some_other_column_you_want_to_default', $attributes)) {
        $attributes['some_other_column_you_want_to_default'] = static::SOME_OTHER_COLUMN_DEFAULT;
    }

    parent::__construct($attributes);
}
user1669496
  • 32,176
  • 9
  • 73
  • 65
  • Oh, god, thanks! I just got lost in the whole documentation... I guess I should get better at searching. – D. Petrov May 24 '17 at 17:17
  • Actually this is a bad idea because I think if you use `Window::create()`, it's going to ignore your attributes and go to your defaults. I'll come up with a better solution after some quick testing. – user1669496 May 24 '17 at 17:18
  • Oh, that'd be an unwanted behaviour... Basically the priority should be as follows: if only an unsaved instance is being created, assign some defaults, then if they have been changed before saving it, keep them changed... And the creation method should also not get ignored. Thanks in advance for your help ^^ – D. Petrov May 24 '17 at 17:20
  • I just updated the answer. I don't think this type of thing would be in the docs. There's nothing really "Laravel" about this solution, it's just basic OO programming. – user1669496 May 24 '17 at 17:25
  • That seems amazing, but a little thing is that I'm using a lot of relations, so it wouldn't be convenient to work with column keys. But I also can't pass those relations as arguments to the `create` method, so I guess it's not gonna be a problem. – D. Petrov May 24 '17 at 17:28
  • You could also just set the defaults up in your schema and allow MySQL to handle it. That's probably an even better solution anyway so you don't have extra code to manage. – user1669496 May 24 '17 at 17:30
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/145054/discussion-between-d-petrov-and-user3158900). – D. Petrov May 24 '17 at 17:38
  • MySQL defaults are not an option, because those defaults depend on the current user and are going to be changed during the lifetime of the app. – D. Petrov May 24 '17 at 17:40
  • Huge problem: each time I call some of the associated belongsTo or hasMany relationships of the model, they get reset as in the default __construct function (yes, I've made some default relations). Is there a way to avoid overwriting the relations? Because if I check before setting them in the contstructor, they're always null, although they're being set... – D. Petrov May 24 '17 at 20:35
0

You can do it

new Window($request->all());
// Or
new Window($request->only(['foo', 'bar']));
// Or immediately create the instance
Window::create($request->all());

But you should first add the needed attributes to the $fillable property in Window model

class Window extends Model {
    protected $fillable = ['foo', 'bar'];
}
Aboudeh87
  • 716
  • 5
  • 16