У меня есть следующий ввод от пользователя:
array (
'id_coretable' => 1,
'Internal_key' => 'UPDATED1',
'extensiontable_itc' =>
array (
'description_itc' => 'UPDATED1',
),
'extensiontable_sysops' =>
array (
'description_sysops' => 'UPDATED1',
),
)
и его содержимое должно обновить следующую модель:
array (
'id_coretable' => 1,
'Internal_key' => 'TESTKEY_1',
'extensiontable_itc' =>
array (
'description_itc' => 'EXTENSION_ITC_1',
),
'extensiontable_sysops' =>
array (
'description_sysops' => 'EXTENSION_SYSOPS_1',
),
)
Эта модель была создана с этим кодом:
$joinAsArray = coretable::with($permittedTables)->find(1);
Где $permittedTables
- это массив имен таблиц, которые определяют таблицы, которые нужно объединить с coretable.
Теперь я потратил несколько часов на размышления о том, как правильно l oop над модель, и это просто невозможно без сериализации модели в простой массив или тому подобное. Это действительно не помогает, так как я хочу обновить модель здесь, и если я просто преобразую ее в массив, я потеряю это соединение с БД / моделью.
Так что я сейчас использую другой подход. Я зацикливаю пользовательский ввод, который ВСЕГДА будет иметь ту же структуру и индексы, что и модель. А затем я использую ключи из очень хорошо зацикливаемого userinputarray и копию старой модели в виде массива, чтобы определить атрибуты модели, которые должны быть обновлены соответствующими входными данными. Вот как выглядит мой код:
foreach($input as $key => $value){
foreach($modelAsArray as $keyOld => $valueOld){
//$keyOld is ALWAYS the same key as the "new" one.
//$keyOld was only chosen to both distinguish from the outer loops $key and to
//maintain its relationship to $valueOld, which is indeed the old value! ;)
coretable::with($permittedTables)->where($key, $valueOld)->update([$key => $value]);
}
}
Теперь этот код работает довольно аккуратно для внешнего массива. Я действительно могу обновить поле «Internal_key» таким образом. Однако, как только мы дойдем до точки, где объединенная таблица будет представлена в виде «вложенного массива», вещи go на юг. Я получаю следующее сообщение об ошибке:
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'extensiontable_itc' in 'where clause' (SQL: update `coretable` set `extensiontable_itc` = {"description_itc":"UPDATED1"}, `coretable`.`updated_at` = 2020-02-06 16:07:06 where `extensiontable_itc` = UPDATED1)
Я вижу, как это происходит. Он пытается найти столбец extensiontable_itc
на coretable, которого, очевидно, там нет, так как это его собственное отношение, связанное только с coretable через FK.
Первое, что приходит мне в голову, чтобы разобраться с этой проблемой, это вызвать другую модель, динамически вставляя ее имя с помощью клавиши $. Тогда мне нужно будет l oop над ключами и значениями вложенных массивов, в основном делая то же самое, что я делал с внешним массивом.
Это, вероятно, потребует сравнительно ужасное количество ресурсов, но это программное обеспечение только для внутренних целей, и наш DB-сервер, вероятно, сможет справиться с этой нагрузкой. Я думаю, это тоже довольно хакерски ^^
Итак, кто-нибудь еще может дать мне другое, более элегантное, менее требовательное к ресурсам и менее хакерское решение, чем мое?
РЕДАКТИРОВАТЬ: В соответствии с запросом в комментариях, вот мои миграции:
Coretable
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateCoretable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('coretable', function (Blueprint $table) {
$table->bigIncrements('id_coretable');
$table->string('Internal_key')->nullable(false)->unique();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('coretable');
}
}
extensiontable_it c
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateExtensiontableItc extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('extensiontable_itc', function (Blueprint $table) {
$table->bigIncrements('id_extensiontable_itc');
$table->bigInteger('coretable_id')->unsigned()->unique()->nullable(false);
$table->foreign('coretable_id', 'fk_extensiontable_itc_coretable')->references('id_coretable')->on('coretable');
$table->string('description_itc')->nullable(false);
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('extensiontable_itc');
}
}
extensiontable_sysops
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class ExtensiontableSysops extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('extensiontable_sysops', function (Blueprint $table) {
$table->bigIncrements('id_extensiontable_sysops');
$table->bigInteger('coretable_id')->unsigned()->nullable(false)->unique();
$table->foreign('coretable_id', 'fk_extensiontable_sysops_coretable')->references('id_coretable')->on('coretable');
$table->string('description_sysops')->nullable(false);
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('extensiontable_sysops');
}
}