简体   繁体   English

如何动态构建此查询 - Laravel/Lumen

[英]How to dynamically build this query - Laravel/Lumen

I have the following input from the user:我有来自用户的以下输入:

array (
  'id_coretable' => 1,
  'Internal_key' => 'UPDATED1',
  'extensiontable_itc' => 
  array (
    'description_itc' => 'UPDATED1',
  ),
  'extensiontable_sysops' => 
  array (
    'description_sysops' => 'UPDATED1',
  ),
)  

and its contents shall update the following model:其内容将更新以下模型:

array (
  'id_coretable' => 1,
  'Internal_key' => 'TESTKEY_1',
  'extensiontable_itc' => 
  array (
    'description_itc' => 'EXTENSION_ITC_1',
  ),
  'extensiontable_sysops' => 
  array (
    'description_sysops' => 'EXTENSION_SYSOPS_1',
  ),
)  

This model was created with this code:此模型是使用以下代码创建的:

$joinAsArray = coretable::with($permittedTables)->find(1);

Where $permittedTables is an array of tablenames which determine the tables to be joined with coretable.其中$permittedTables是一个表名数组,它确定要与 coretable 连接的表。

Now, I've spent multiple hours on pondering how to properly loop over a model, and it simply isnt possible without serializing the model to a plain array or the like.现在,我花了几个小时思考如何正确地循环模型,如果不将模型序列化为普通数组或类似的东西,这是不可能的。 This doesnt really help though, since I want to UPDATE the model here, and if I just convert it to an array, then I lose this connection to the DB/Model.但这并没有真正的帮助,因为我想在这里更新模型,如果我只是将它转换为数组,那么我就会失去与 DB/Model 的连接。

So I'm now using a different approach.所以我现在使用不同的方法。 I'm looping the userinput, which will ALWAYS have the same structure and indexes as the model.我正在循环用户输入,它总是与模型具有相同的结构和索引。 And then I'm using the keys from the very well loopable userinputarray and a copy of the old model in form of an array, to determine the attributes of the model which shall be updated with the respective input data.然后我使用来自非常好循环的 userinputarray 的键和数组形式的旧模型的副本,以确定模型的属性,该属性应使用相应的输入数据进行更新。 This is what my code currently looks like:这是我的代码目前的样子:

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

Now, this code works pretty neatly for the outer array.现在,这段代码非常适合用于外部数组。 I can indeed update the "Internal_key" field this way.我确实可以通过这种方式更新“Internal_key”字段。 However, once we hit the point where the joined table is represented in form of the "nested array", things go south.然而,一旦我们达到了以“嵌套数组”的形式表示连接表的点,事情就会向南。 I get the following error message:我收到以下错误消息:

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)

I can kind of see where this comes from.我可以看出这是从哪里来的。 Its trying to find a column extensiontable_itc on coretable which obviously isnt there since it is its own relation, only connected to the coretable via FK.它试图在 coretable 上找到一个列extensiontable_itc ,它显然不存在,因为它是它自己的关系,仅通过 FK 连接到 coretable。

The first thing that comes to my mind to deal with this problem is calling another model by dynamically inserting its name via the $key.我想到处理这个问题的第一件事是通过 $key 动态插入其名称来调用另一个模型。 Then I would have to loop over the nested arrays keys and values, basically doing the same thing as I did with the outer array.然后我将不得不遍历嵌套数组的键和值,基本上做与我对外部数组所做的相同的事情。

This probably will consume a comparatively horrible amount of ressources, but this software is for internal purposes only and our DB-server probably will be able to handle this load.这可能会消耗相当多的资源,但该软件仅供内部使用,我们的数据库服务器可能能够处理这种负载。 Its also quite hacky, I think^^它也很hacky,我认为^^

So, can anyone else give me another, more elegant, less ressource hungry and less hacky solution than mine?那么,有没有人可以给我另一个比我的更优雅、更少资源、更少黑客的解决方案?

EDIT: As per request in the comments, here are my migrations:编辑:根据评论中的要求,这是我的迁移:

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_itc扩展表_itc

<?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 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');
    }
}

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) SQLSTATE [42S22]:未发现柱:1054未知列'extensiontable_itc'在'where子句'(SQL:更新coretableextensiontable_itc = { “description_itc”: “UPDATED1”}, coretableupdated_at = 2020年2月6日16时07分:06 其中extensiontable_itc = UPDATED1)

You can't update relation data via with('relation')->update() .您不能通过with('relation')->update()更新关系数据。

I will make an example to implement this, based on your migration files.我将根据您的迁移文件制作一个示例来实现这一点。


Core

namespace App;

use App\ExtensiontableItc;
use App\ExtensiontableSysops;
use Illuminate\Database\Eloquent\Model;

class Core extends Model
{
    protected $table      = 'coretable';
    protected $primaryKey = 'id_coretable';
    protected $fillable   = [
        'id_coretable',
        'Internal_key',
    ];

    public function extensiontable_itc()
    {
        return $this->hasOne(ExtensiontableItc::class, 'coretable_id', 'id_coretable');
    }

    public function extensiontable_sysops()
    {
        return $this->hasOne(ExtensiontableSysops::class, 'coretable_id', 'id_coretable');
    }
}

ExtensiontableItc扩展表

namespace App;

use Illuminate\Database\Eloquent\Model;

class ExtensiontableItc extends Model
{
    protected $table      = 'extensiontable_itc';
    protected $primaryKey = 'id_extensiontable_itc';
    protected $fillable   = [
        'coretable_id',
        'description_itc',
    ];
}

ExtensiontableSysops扩展表管理员

namespace App;

use Illuminate\Database\Eloquent\Model;

class ExtensiontableSysops extends Model
{
    protected $table      = 'extensiontable_sysops';
    protected $primaryKey = 'id_extensiontable_sysops';
    protected $fillable   = [
        'coretable_id',
        'description_sysops',
    ];
}

Usage用法

$permittedTables = ['extensiontable_itc', 'extensiontable_sysops'];
$core            = Core::with($permittedTables)->find(1);

You will get (based on your example)你会得到(根据你的例子)

array:6 [
  "id_coretable" => 1
  "Internal_key" => "TESTKEY_1"
  "created_at" => "2020-02-07 18:05:50"
  "updated_at" => "2020-02-07 18:05:50"
  "extensiontable_itc" => array:5 [
    "id_extensiontable_itc" => 1
    "coretable_id" => 1
    "description_itc" => "UPDATED1"
    "created_at" => "2020-02-07 18:17:08"
    "updated_at" => "2020-02-07 11:32:44"
  ]
  "extensiontable_sysops" => array:5 [
    "id_extensiontable_sysops" => 1
    "coretable_id" => 1
    "description_sysops" => "UPDATED1"
    "created_at" => "2020-02-07 18:17:21"
    "updated_at" => "2020-02-07 11:32:44"
  ]
]

To update your relation, you need to call extensiontable_itc and extensiontable_sysops eager load via Core model.要更新您的关系,您需要通过Core模型调用extensiontable_itcextensiontable_sysops预先加载。


$input = [
    'id_coretable'          => 1,
    'Internal_key'          => 'TESTKEY_1',
    'extensiontable_itc'    => [
        'description_itc' => 'EXTENSION_ITC_1',
    ],
    'extensiontable_sysops' => [
        'description_sysops' => 'EXTENSION_SYSOPS_1',
    ],
];

$permittedTables = ['extensiontable_itc', 'extensiontable_sysops'];
$core            = Core::with($permittedTables)->find(1);

// Update extensiontable_itc
$core->extensiontable_itc->update($input['extensiontable_itc']);

// Update extensiontable_sysops
$core->extensiontable_sysops->update($input['extensiontable_sysops']);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM