PHP / Laravel - Foreach存储到数据库中(\ Grammar :: parameterize()错误)

I have an array, which looks like this:

array:3 [▼
  "field" => array:2 [▼
    0 => "fromName"
    1 => "from"
  ]
  "operator" => array:2 [▼
    0 => "="
    1 => "="
  ]
  "value" => array:2 [▼
    0 => "Oliver"
    1 => "oliver@mywebsite.com"
  ]
]

I am trying to save the above array, into my database table called email_rules:

My database table

Below is my code.

StreamEmailRulesController.php:

public function store(Stream $stream)
{
    //Validate the request.
    //Validate the request.
    $attributes = request()->validate([
        'field' => 'required|array|min:1',
        'field.*' => [
            'required', 'string',
            Rule::in(['fromName', 'from']),
        ],
        'operator' => 'required|array|min:1',
        'operator.*' => [
            'required', 'string',
            Rule::in(['=', '!=', 'matches']),
        ],
        'value' => 'required|array|min:1',
        'value.*' => 'required|string|min:3|max:255',
    ]);

    //Add the document to the database.
    $stream->addRules($attributes);

    //Return back.
    return redirect()->back();
}

Now the $stream->addRules() function is responsible for saving the data to the database.

Stream.php:

/**
* A stream can have many rules.
*/
public function rules()
{
    return $this->hasMany(EmailRule::class);
}


/**
 * Add Email Rules(s) to the stream
 *
 * @return Illuminate\Database\Eloquent\Model
 */
public function addRules(array $attributes)
{
    return $this->rules()->create($attributes);
}

Now, above does not work. I get below error:

Argument 1 passed to Illuminate\Database\Grammar::parameterize() must be of the type array, int given, 

What am I doing wrong?

The problem was that Laravels create or createMany expect an array with key => pair values, where the key corresponds to the database columns.

This article from Adam Wathan helped me out a lot.

This is what I ended up doing:

  $requestData = collect(request()->only('field', 'operator', 'value'));
  $rules = $requestData->transpose()->map(function ($ruleData) {
         return new EmailRule([
             'field' => $ruleData[0],
             'operator' => $ruleData[1],
             'value' => $ruleData[2],
         ]);
  })->toArray();

  //Add the rules to the database.
  $stream->addRules($rules);

If you dump $attributes you may be getting an int (bool) as a pass or fail or even json, depending on what's going in, from the validation. This might just be a matter of changing syntax from

 $attributes = request()->validate([...

to

$attributes= $this->validate(request(), [...

I believe your issue is that you're trying to save an array as a singular value. IE those attributes need to be iterated over to create a new set of rules for each one, instead. Normally, I'd expect to see the array ready to create individual objects. In this case, though it looks like it is structured to create individual fields (field, operator, value), so looping through those may not do what you wish either -- it provides multiple fields to the create construct, rather than a full set of object params for a new rule(). I think Laravel is hinting that you may wish to change your request/return structure to match the model format.

I think it could be the array structure. Can you modify the array to?:

[
   [
   "field" => "fromName",
   "operator" => "=",
   "value" => "Oliver"
   ],
   [
   "field" => "from",
   "operator" => "=",
   "value" => "oliver@mywebsite.com"
   ],
]

EDIT: In the Controller add a loop like this:

...
foreach ($attributes as $key => $value) {
    foreach ($value as $k => $v) {
        $data [$k][$key] = $v;
    }
}

//Add the document to the database.
$stream->addRules($data);