最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

postgresql - How to set autoincrementing model attribute based on another field in DB? - Stack Overflow

programmeradmin4浏览0评论

I use Laravel 11 and postgresql, there are 2 tables in my project I'm interested in. One of them is table "projects", there is nothing spesific about it, but I have table "texts" with a field "version" and Eloquent model "Text". I want to override create or save method of model "Text" so its version should be calculated during insert into database based on MAX value +1 of previous text of the same project. Also I don't want to change or calculate version when model is updated. I would prefer to avoid adding DB triggers or functions if it's possible and let Eloquent to handle that.

INSERT INTO public.texts
("content", user_id, project_id, "version", created_at, updated_at, words, processed)
VALUES
('sql test', 4, 4, (select max("version")+1 from public.texts WHERE project_id=4)::smallint, now(), now(), 2, false);

I need something like:

public function save(array $options = [])
{
    // gracefully put it into sql builder
    $this->version = \DB::raw("select max(\"version\")+1 from public.texts where project_id=".$this->project_id);
    return parent::save($options);        
}

I use Laravel 11 and postgresql, there are 2 tables in my project I'm interested in. One of them is table "projects", there is nothing spesific about it, but I have table "texts" with a field "version" and Eloquent model "Text". I want to override create or save method of model "Text" so its version should be calculated during insert into database based on MAX value +1 of previous text of the same project. Also I don't want to change or calculate version when model is updated. I would prefer to avoid adding DB triggers or functions if it's possible and let Eloquent to handle that.

INSERT INTO public.texts
("content", user_id, project_id, "version", created_at, updated_at, words, processed)
VALUES
('sql test', 4, 4, (select max("version")+1 from public.texts WHERE project_id=4)::smallint, now(), now(), 2, false);

I need something like:

public function save(array $options = [])
{
    // gracefully put it into sql builder
    $this->version = \DB::raw("select max(\"version\")+1 from public.texts where project_id=".$this->project_id);
    return parent::save($options);        
}
Share Improve this question edited Jan 20 at 18:58 DarkBee 15.6k8 gold badges70 silver badges114 bronze badges asked Jan 20 at 18:55 Sergei TsibulchenkoSergei Tsibulchenko 3071 gold badge6 silver badges17 bronze badges 1
  • Use a sequence – Stefanov.sm Commented Jan 21 at 5:30
Add a comment  | 

1 Answer 1

Reset to default 0

This can be achieved using model events

Here's a basic example on how you may implement this by adding this in your Text model:

protected static function booted(): void {
    static::creating(function (Text $text) {
        $text->version = \DB::select("select max(\"version\")+1 from public.texts where project_id=?", [ $text->project_id ]);
    });
}

Note that this will only work when saving an individual model via $text->save() for the first time. It will not work while mass inserting or when using raw queries.

发布评论

评论列表(0)

  1. 暂无评论