Laravel saving mass assignment with a morphMany re

2019-05-21 01:04发布

问题:

I'm looking at mass assignment in Laravel, and trying to mass assign data for both one model and it's related model.

My models:

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();
    }
}

My Input

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.

回答1:

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!