Reputation: 712
I'm looking at mass assignment in Laravel, and trying to mass assign data for both one model and it's related model.
class News extends Eloquent {
protected $table = 'news';
protected $fillable = array(
'title', 'slug', 'author', 'img', 'content',
);
public function content() {
return $this->morphMany('Content', 'morphable')->orderBy('section');
}
}
class Content extends Eloquent {
protected $table = 'contents';
protected $fillable = array(
'rawText', 'section',
);
public function morphable() {
return $this->morphMany();
}
}
I have Input:all()
looking like this, coming from the form:
array(6) {
["_token"]=>
string(40) "irrelevant"
["title"]=>
string(11) "Happy Title"
["author"]=>
string(9) "Mr. Happy"
["slug"]=>
string(11) "happy-title"
["img"]=>
string(9) "happy.png"
["content"]=>
array(1) {
[0]=>
array(2) {
["section"]=>
string(4) "body"
["rawText"]=>
string(27) "# I'm happy! ## So happy"
}}}
What do I do now to actually save the data as two new database rows? (one in news, one in contents)
I thought it would now be as simple as:
$news = News::create(Input::all());
$news->push();
But I'm clearly missing something.
I get the error: preg_replace(): Parameter mismatch, pattern is a string while replacement is an array
Does mass assignment not work at all with related models?
Or does it work fine, but not with morphMany relations?
Have I misunderstood $model->push()
, or $model::create
?
Thanks in advance.
Upvotes: 2
Views: 3226
Reputation: 712
As often with SO questions, writing and formatting gave me some time to think..
$input = Input::all();
$contents = Input::get('content');
unset($input['content']);
$news = News::create($input);
foreach ($contents as $c) {
$content = Content::create($c);
$news->content()->save($content);
}
$news->save();
Works! But feels kinda hackish. Is there a more.. "Eloquent" way of mass assigning related models?
Edit: This probably is the generally correct course of action then - mass assignment won't handle relations, but at least I can mass assign each model individually.
I just need to juggle the input a bit, which I'll probably have to do anyway once validation gets added to the equation.
Edit2: Having lots of success moving the related model logic into that model, and keeping it simple, e.g:
$input = Input::all();
unset($input['content']);
$news = News::create($input);
$news = Content::updateAll($news, true);
$news->save();
for creating, and:
$input = Input::all();
unset($input['content']);
$news = News::find($id)->fill($input);
$news = Content::updateAll($news, false);
$news->save();
for updating.
The updateAll()
method, for anyone interested:
public static function updateAll($model, $create = false) {
$contents = Input::get('content');
foreach ($contents as $k => $c) {
// Save against parent model
if ($create) {
$content = Content::create($c);
} else {
$content = Content::find($k)->fill($c);
}
$model->content()->save($content);
}
return $model;
}
Now I feel like I'm using full power!
Upvotes: 1