За последние 24 часа нас посетили 22089 программистов и 1055 роботов. Сейчас ищут 688 программистов ...

обновление данных в связанной таблице

Тема в разделе "Laravel", создана пользователем snakenest, 1 дек 2022.

  1. snakenest

    snakenest Новичок

    С нами с:
    1 дек 2022
    Сообщения:
    12
    Симпатии:
    1
    Существует две модели, master и child связанные по полю id в master и idmaster в childs, кроме того в child есть поле idvalue. которое является ссылкой на справочник.
    Например:
    существует запись в таблице master с id=30
    существуют записи в таблице childs, например 3 шт:
    [id=1, idmaster=30, idvalue=10],
    [id=2, idmaster=30, idvalue=11],
    [id=3, idmaster=30, idvalue=12]

    поступил массив со значениями idvalue
    PHP:
    1. $truelist = array(10,13,14);
    задача:
    удалить те записи в child, для которых нет idvalue в пришедшем массиве, и добавить которых не хватает
    Как это сделать используя возможности eloquent?

    Используя hasMany, удалить - просто:
    PHP:
    1. $this->child()->whereNotIn('idvalue',$truelist)->delete();
    А вот как добавить записи в childs, которых нет, но значения есть в массиве

    пройтись циклом по массиву $truelist и выбирать, типа:
    PHP:
    1. foreach($truelist as $idvalue)
    2. {
    3.     $this->child()->where('idvalue',$idvalue)->firstOrCreate(['idvalue'=>$idvalue]);
    4. }
    можно, но это запрос к бд при каждой итерации выборки :(
    т.е. если такой массив 100 элементов - то печаль.

    подскажите, как это можно сделать более изящно, так же как и удаление?
     
  2. mkramer

    mkramer Суперстар
    Команда форума Модератор

    С нами с:
    20 июн 2012
    Сообщения:
    8.554
    Симпатии:
    1.754
    Если прямо средствами Laravel, то upsert.

    Если религия позволяет написать чистый запрос, и это mysql, то можно insert ignore.
    --- Добавлено ---
    Это если в базе есть что-то вроде уникального ключа, составного.
     
  3. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.072
    Симпатии:
    1.237
    Адрес:
    там-сям
    snakenest нравится это.
  4. mkramer

    mkramer Суперстар
    Команда форума Модератор

    С нами с:
    20 июн 2012
    Сообщения:
    8.554
    Симпатии:
    1.754
    @artoodetoo, у него не many-to-may
    --- Добавлено ---
    Хотя, если сделать связь на value, а не на показанный child, то будет many-to-many, и можно будет sync использовать.

    @snakenest Поля таблицы и сами таблицы лучше называть в соответствии с соглашениями ларки, он тогда кучу всего сам будет за тебя делать, без необходимости в пояснениях.
     
    snakenest и artoodetoo нравится это.
  5. snakenest

    snakenest Новичок

    С нами с:
    1 дек 2022
    Сообщения:
    12
    Симпатии:
    1
    не совсем понял каким образом тут связь многие ко многим?

    таблица childs имеет три поля
    id - свой уникальный ключ
    idmaster - ссылка на таблицу мастер
    idvalue - ссылка на справочник values который используется в других таблицах

    Может вы имеете ввиду отношение - через (hasManyThrough)?

    можете объяснить это на примере или ссылку дать на какой-либо пример того что вы имели ввиду?
     
  6. snakenest

    snakenest Новичок

    С нами с:
    1 дек 2022
    Сообщения:
    12
    Симпатии:
    1

    Спасибо! работает! :)
    переопределил связь

    PHP:
    1. public function values()
    2. {
    3.     return $this->belongsToMany('App\Models\NSI','childs','idmaster','idvalue','id');
    4. }
    И тогда заработал метод sync
    PHP:
    1. $this->values()->sync($truelist);
    правда пришлось повозиться с описанием параметров при установке связи, т.к. не очень понятно, что туда надо прописать. пришлось сделать такую вот штуку в AppServiceProvider

    PHP:
    1. use DB;
    2. use Illuminate\Http\Request;
    3.  
    4. class AppServiceProvider extends ServiceProvider
    5. {
    6.     /**
    7.      * Bootstrap any application services.
    8.      *
    9.      * @return void
    10.      */
    11.     public function boot()
    12.     {
    13.         if (env('SHOW_REQUEST',false))
    14.         {
    15.             dump($this->app->request);
    16.         }
    17.         if (env('SHOW_QUERY',false))
    18.         {
    19.             DB::listen( function ($query){
    20.                 dump($query->sql);
    21.                 dump($query->bindings);
    22.             });
    23.         }
    24.     }
    чтобы увидеть реальные запросы к бд, и понять какие параметры, за что отвечают в belongsToMany
     
    artoodetoo нравится это.
  7. mkramer

    mkramer Суперстар
    Команда форума Модератор

    С нами с:
    20 июн 2012
    Сообщения:
    8.554
    Симпатии:
    1.754
    Ну вот чтоб не возиться с описанием параметров при установке связи, и надо соблюдать соглашения о наименованиях ларавеля везде, где возможно
    --- Добавлено ---
    Тогда можно проще писать:
    PHP:
    1.  public function users(): \Illuminate\Database\Eloquent\Relations\BelongsToMany
    2.     {
    3.         return $this->belongsToMany(User::class);
    4.     }
     
  8. snakenest

    snakenest Новичок

    С нами с:
    1 дек 2022
    Сообщения:
    12
    Симпатии:
    1
    при создании БД с нуля - Да
    но при прикручивании уже существующей, да еще и которая работает праллельно с другими приложениями и сервисами..... не получится ;)