PHP / Laravel - Получить JSON-ввод из запроса, динамически сопоставить по имени - PullRequest
0 голосов
/ 27 августа 2018

В настоящее время я получаю данные из внешнего приложения, используя Laravel в моем приложении.

Я создал простой webhook в моем файле контроллера, например:

public function webhook(Request $request)
{
        $document = new Document();

        $document->fill($request->all());

        //Insert (or update existing) data in our database.
        $document::updateOrCreate(
            ['booking_reference' => $document->booking_reference],
            $document->getAttributes()
        );

        return response()->json('OK');
}

Теперь моя проблема в том, что я должен вставить эти данные в таблицу. Чтобы сделать это, полученные объекты json должны соответствовать имени столбцов моей таблицы. Я могу установить имена json во внешнем приложении - однако , иногда внешнее приложение добавляет дочерние элементы к именам json.

Например, представьте, что это моя база данных:

id    |   booking_reference   | shipment_reference

И у моего JSON есть такие:

"booking_reference"  : "32000"
"shipment_reference" : "TREXOOO"

Тогда данные будут правильно вставлены в мою базу данных. Однако, как уже упоминалось, объекты JSON иногда могут выглядеть так:

"booking_reference_0"  : "32000"
"shipment_reference_5" : "TREX000"

В этом примере моя таблица не будет обновлена, поскольку имена JSON не совпадают с именами моей таблицы.

Как это сделать, чтобы я мог динамически вставлять данные в свою таблицу? Данные всегда будут иметь префикс имени таблицы, например booking_reference или booking_reference_{child}

Обновление:

Используя ответ Erubiel, я могу получить столбцы для динамического соответствия имени. Тем не менее, у меня есть базовая настройка отношения ownTo, но решение Erubiel удаляет объект $ document и добавляет только столбцы mapped .

$document->creator()->associate(auth()->user());

и в моей модели:

public function creator()
{
    return $this->belongsTo(User::class, 'user_id', 'id');
}

Но мой JSON-ответ не содержит user_id или creator info:

{"booking_reference":"CDK10000","pickup_location":"Afhentingsadresse 100 2650","drop_off_location":"Leveringsadresse 200 1000","comments":"HaHA","shipment_referenec":"SBRY100000"}

Если я получу $document перед циклом foreach:

{"user_id":1,"creator":{"id":1,"name":"Oliver","email":"oliver@example.com","created_at":"2018-08-27 10:58:10","updated_at":"2018-08-27 10:58:10"}}

Окончательное редактирование с решением

Используя ответ Erubiel, я немного изменил его, чтобы сохранить новые значения в моем существующем объекте JSON:

foreach ($request->all() as $key => $value) {
     $newKey = preg_replace("/(_?\d+)+$/", '', $key); //this generates the name of column that you need
     $document->$newKey = $value;
 }

Который работает как брелок - вывод:

{"user_id":1,"booking_reference":"CDK10000","pickup_location":"Afhentingsadresse 100 2650","drop_off_location":"Leveringsadresse 200 1000","comments":"HaHA","shipment_referenec":"SBRY100000","creator":{"id":1,"name":"Oliver","email":"oliver@example.com","created_at":"2018-08-27 10:58:10","updated_at":"2018-08-27 10:58:10"}}

Ответы [ 3 ]

0 голосов
/ 27 августа 2018

Это должно работать, как предложено в комментариях, препроцесс.

public function webhook(Request $request)
{

    $arrAux = array();
    foreach($request->all() as $key => $value){
        $newKey = preg_replace("/(_?\d+)+$/","",$key); //this generates the name of column that you need
        $arrAux[$newKey] = $value;
    }

    //Insert (or update existing) data in our database.
    Document::updateOrCreate(
        ['booking_reference' => $arrAux['booking_reference']],
        $arrAux
    );

    return response()->json('OK');
}
0 голосов
/ 27 августа 2018

Добавить защищенное $fillable свойство со списком доступных полей для массового присвоения вашей модели:

protected $fillable = ['booking_reference','shipment_reference'];

Затем отловить ошибку несоответствия полей в вашем контроллере

try {
    $document->update($request->input());
} catch (MassAssignmentException $e) {
    $data = $request->input();
    foreach ($data as &$field) {
       preg_match('~([a-zA-Z]+(_[a-zA-Z]+)+)~', $field, $match);
       $field = $match[1];
    }
    $document->update($data);
}
0 голосов
/ 27 августа 2018

Ваш подход к решению проблемы похож на анти-шаблон архитектуры / дизайна (вставка основана на необработанных данных json). Это не ответ на ваш вопрос, а только мое мнение.

Самое быстрое решение вашей проблемы - это класс, который примет $ jsonKey и переведет его / вернет $ dbKey.

Ваш текущий код:

$document->fill($request->all());

Новый подход:

$input = $this->translator->fromInput($request->all());
$document->fill($input);

Пример класса sanitize / translate:

class Translator {
    /**
     * @param array $input
     * @return array
     */
    public function fromInput(array $input): array
    {
        $translated = [];

        foreach ($input as $key => $value) {
            switch ($key){
                case 'a':
                case 'a_1':
                    $translated['a'] = $value;
                    break;
                case mb_strpos($key, 'b'):
                    $translated['b'] = $value;
                    break;
                default: $translated[$key] = $value;
            }
        }

        return $translated;
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...