PHP / Laravel — Предварительное сохранение в базе данных (ошибка Grammar ::parameterize()))

#php #laravel

#php #laravel

Вопрос:

У меня есть массив, который выглядит следующим образом:

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

Я пытаюсь сохранить приведенный выше массив в моей таблице базы данных под названием email_rules :

Моя таблица базы данных

Ниже приведен мой код.

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

Теперь $stream->addRules() функция отвечает за сохранение данных в базе данных.

Stream.php :

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


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

Теперь вышеописанное не работает. Я получаю ошибку ниже:

 Argument 1 passed to IlluminateDatabaseGrammar::parameterize() must be of the type array, int given, 
  

Что я делаю не так?

Ответ №1:

Если вы сбрасываете $attributes, вы можете получить int (bool) в качестве pass или fail или даже json, в зависимости от того, что происходит, после проверки. Это может быть просто вопросом изменения синтаксиса с

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

Для

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

Я полагаю, ваша проблема в том, что вы пытаетесь сохранить массив как единственное значение. Т.е. эти атрибуты необходимо повторить, чтобы вместо этого создать новый набор правил для каждого из них. Обычно я ожидаю увидеть массив, готовый к созданию отдельных объектов. В этом случае, хотя похоже, что он структурирован для создания отдельных полей (field, operator, value), поэтому перебор их может также не привести к желаемому результату — он предоставляет несколько полей для конструкции create, а не полный набор параметров объекта для нового правила (). Я думаю, Laravel намекает, что вы, возможно, захотите изменить структуру вашего запроса / возврата, чтобы соответствовать формату модели.

Комментарии:

1. Дамп создается после проверки. Изменение его на $this->validate.. не работает

2. Ах! Теперь я понимаю. Кажется, я вижу проблему. Я отредактирую свой ответ.

Ответ №2:

Я думаю, что это может быть структура массива. Можете ли вы изменить массив на?:

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

Редактировать:
В контроллере добавьте цикл, подобный этому:

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

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

Комментарии:

1. Массив используется по умолчанию в Laravels request() .

2. @oliverbj извините за мой плохой английский. возможно, есть лучший способ, чем вложенный foreach, но вы можете попробовать, как в редактировании моего ответа

3. @Pablo — с твоим английским все в порядке. И ваш ответ хорош. Я думаю, что мы оба указываем на одну и ту же ошибку.

Ответ №3:

Проблема заключалась в том, что Laravels create или createMany ожидали массив с ключом => пара значений, где ключ соответствует столбцам базы данных.

Эта статья Адама Ватана мне очень помогла.

Это то, что я в итоге сделал:

   $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);