优化用于插入,更新或删除关系的代码

时间:2016-06-06 18:38:13

标签: php mysql laravel model eloquent

我根据提供的输入和现有数据编写逻辑来插入,更新或删除表格行。

  • 如果没有输入,并且该行存在,则应删除该行。
  • 如果有输入,但该行不存在,则应该创建。
  • 最后,如果有输入并且该行存在,则应该更新该行。

此项目是attributes表的测试代码,其中包含namevaluemedia_id(引用已赋予属性的媒体片段) )。 namemedia_id是唯一的(一个媒体不能有两个具有相同名称的属性)。对项目而言,使用插入,更新和删除非常重要,而不是在空的情况下将它们留空。

我的问题是,是否有更简单的方法来执行这种逻辑。我可以将它用于一个输入,但是当有两个(namedescription)并且我可能稍后添加更多时,它似乎是一个巨大的代码片段使用。有更有效的方法吗?

我的数据库迁移:

Schema::create('attributes', function (Blueprint $table) {
    $table->increments('id')->unsigned();
    $table->integer('media_id')->unsigned();
    $table->string('name');
    $table->text('value')->nullable();
    $table->timestamps();
    $table->unique(['media_id', 'name']);
    $table->foreign('media_id')->references('id')->on('media')->onDelete('cascade');
});

我的观点:

<form action="{{ Request::path() }}" method="post">
    <input type="hidden" name="_token" value="{{ csrf_token() }}">
    <label style="display:block" for="name">Name</label>
    <input type="text" name="name" id="name" value="{{ $attributes->get('name') ? $attributes->get('name')->value : '' }}">
    <label style="display:block" for="description">Description</label>
    <textarea name="description" id="description">{{ $attributes->get('description') ? $attributes->get('description')->value : '' }}</textarea>
    <button type="submit">Save</button>
</form>

我的临时控制器:

Route::post('/', function(Request $request) {
    $media = Media::find(1);

    $attributes = $media->attributes->keyBy('name');

    if($request->input('name')) {
        if($attributes->get('name')) {
            $attributes->get('name')->value = $request->input('name');
            if(!$attributes->get('name')->save()) {
                return "error updating name";
            }
        } else {
            $attribute = new Attribute;
            $attribute->name = 'name';
            $attribute->value = $request->input('name');
            if(!$media->attributes()->save($attribute)) {
                return "error inserting name";
            }
        }
    } else {
        if($attributes->get('name')) {
            if(!$attributes->get('name')->delete()) {
                return "error deleting name";
            }
        }
    }
    if($request->input('description')) {
        if($attributes->get('description')) {
            $attributes->get('description')->value = $request->input('description');
            if(!$attributes->get('description')->save()) {
                return "error updating description";
            }
        } else {
            $attribute = new Attribute;
            $attribute->name = 'description';
            $attribute->value = $request->input('description');
            if(!$media->attributes()->save($attribute)) {
                return "error inserting description";
            }
        }
    } else {
        if($attributes->get('description')) {
            if(!$attributes->get('description')->delete()) {
                return "error deleting description";
            }
        }
    }
});
return redirect('/');

(还有一个GET控制器,它显示表格和数据库输出。我没有打扰包括它,因为我认为没有必要。)

我死的简单模型:

class Attribute extends Model
{
    public function media()
    {
        return $this->belongsTo('App\Media');
    }
}

1 个答案:

答案 0 :(得分:1)

好的,这就是我得到的:

路线档案:

use Illuminate\Http\Request;
use App\Models\Media;
use App\Models\Attribute;

Route::get('/', function(Request $request) {
    $media = Media::all();
    $media->attributes;
    return response()->json($media);
});
Route::get('/media/{id}', function($id, Request $request) {
    $media = Media::find($id);
    $media->attributes;
    return response()->json($media);
});
Route::post('/media/{id}', function($id, Request $request) {
    if($request->has('name')) {
        $attr = Attribute::firstOrNew(['name' => 'name', "media_id" => $id]);
        $attr->value = $request->input('name');
        $attr->save();
    } else {
        Attribute::where('name', 'name')->where("media_id",$id)->first()->delete();
    }
    if($request->has('description')) {
        $attr = Attribute::firstOrNew(['name' => 'description', "media_id" => $id]);
        $attr->value = $request->input('description');
        $attr->save();
    } else {
        Attribute::where('name', 'description')->where("media_id",$id)->first()->delete();
    }
});
return redirect('/');

媒体模型:

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Media extends Model
{
    protected $table = 'media';

    protected $appends = [];

    public function attributes() {
        return $this->hasMany(Attribute::class);
    }
}

属性模型

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Attribute extends Model
{
    protected $table = 'attributes';

    protected $fillable = ['name', 'media_id'];

    public function media() {
        return $this->belongsTo(Media::class);
    }
}

基本上,通过使属性成为模型,我能够在属性表上执行firstOrNew(),并在['name' => 'name', "media_id" => $id]上查找firstOrNew()使其找到匹配的行,或创建一个新的。然后,您可以根据这样更新值列。

更短,更简化,它允许您的属性成为模型!

(我的意见,几乎所有东西都应该是模型:P)

编辑:我将其修改为我最近的代码。已将其从belongsTo("Media")更改为belongsTo(Media::class),并从路径文件中删除了dd()