2017-01-17 1 views
0

Я хочу правильно сохранить оба полиморфных отношения одновременно. Код ниже работает, но я считаю, что он может быть намного чище, поскольку я полагаю, что два метода update() дважды вызывают базу данных.Сохранение обоих полиморфных связей в то же время в Laravel 5.3

A NewsModule::class может иметь различные элементы модуля; VideoModule, TextModule, ImageModule и еще несколько. Каждый из них содержит свой собственный контент, который должен быть прикреплен к родительскому NewsModule.

Как уже упоминалось, код работает так, что отношения настроены правильно, но я убежден, что есть более простой способ сэкономить одновременно.

Я также открываю предложения по очистке заявлений if. Но, возможно, это еще один пост.

public function update(Request $request, $id) 
{ 
    $module = NewsModule::find($id); 

    if ($module->type === 'text') { 
     $content = TextModule::find($module->content_id); 
    } elseif ($module->type === 'image') { 
     $content = ImageModule::find($module->content_id); 
    }; 

    $module->update($request->all()); 
    $content->update($request->all()); 

    return fractal() 
     ->item($module, new NewsModuleTransformer) 
     ->parseIncludes(['content']) 
     ->toArray(); 
} 

обновление (больше кода по запросу) ...

Состав:

news_modules 
    - id 
    - content_id 
    - content_type 
    - etc 

text_modules 
    - id 
    - content 
    - etc 

image_modules 
    - id 
    - image_id 
    - etc 

NewsModule:

class NewsModule extends Model 
{ 
    public function content() 
    { 
     return $this->morphTo(); 
    } 
} 

Все модули пункт:

class TextModule extends Model 
{ 
    public function newsmodules() 
    { 
     return $this->morphMany(NewsModule::class, 'content'); 
    } 
} 
+0

ли как модуль и содержание связаны к той же таблице? Можете ли вы рассказать о своей структуре таблиц? – Paras

+0

@paras Я только что добавил больше структуры модели выше –

+0

Я не понимаю ваш вопрос. Вы говорите, что оба обновления могут быть одним запросом, но они представляют собой две разные таблицы.Итак, как вы ожидаете, что они будут единственным запросом? – Paras

ответ

3
public function update(Request $request, $id) 
{ 
    $modele = NewsModule::find($id); 

    $module->update($request->all()); 

    $module->content->update($request->all()); 

    return fractal() 
     ->item($module, new NewsModuleTransformer) 
     ->parseIncludes(['content']) 
     ->toArray(); 
} 

Будет выполнено всего 4 запросов. 1 для каждого модуля для извлечения, а другой - для обновления. Это может быть сокращено до 3, как:

public function update(Request $request, $id) 
{ 
    $modele = NewsModule::find($id); 

    $module->update($request->all()); 

    $module->content()->update($request->all()); 

    return fractal() 
     ->item($module, new NewsModuleTransformer) 
     ->parseIncludes(['content']) 
     ->toArray(); 
} 

Недостатком $module->content()->update($request->all()); является то будет сгенерировано сообщение об ошибке, если есть что-нибудь в $request->all() это не столбец в этой модели содержимого или есть массив в качестве значения , Вы можете избежать этого, просто вызывая update() на $fillable свойства (если они у вас есть определенные) из соответствующей модели, как:

$fillable = $module->content()->getRelated()->getFillable(); 
    $module->content()->update($request->only($fillable)); 

Этот путь также не будет стрелять прослушивателей модель событий у вас есть, так как вы никогда не извлекая модель из базы данных.

Чтобы сделать все на один шаг дальше, просмотрите Route Model Binding. В ваших app\Providers\RouteServiceProvider «ы boot() метод:

public function boot() 
{ 
    parent::boot(); 

    Route::model('news', App\NewsModule::class); 
} 

Таким образом,„новости“всегда будет решать экземпляр NewsModule при использовании его в качестве параметра маршрута. Так что ваш маршрут будет что-то вроде:

Route::match(['patch', 'put'], '/news/{news}', '[email protected]'); 

Так что в вашем методе update вы могли бы решить эту модель, просто введите намекая его в методе позволяет сделать:

public function update(Request $request, NewsModule $news) 
{ 
    $news->update($request->all()); 

    $news->content->update($request->all()); 

    return fractal() 
     ->item($news, new NewsModuleTransformer) 
     ->parseIncludes(['content']) 
     ->toArray(); 
} 
+0

Ничего себе, спасибо за такой подробный ответ. К сожалению, Route Model Binding не будет работать для меня здесь, потому что пули являются динамическими '/ {pageSlug}/{itemSlug}'. Тем не менее, ваш второй блок кода сделает мой код более чистым и удалит некоторые из моих операторов 'if'. Поэтому по этой причине я отвечу. Полное объяснение помогло тоже :) –

+0

@ Эрик хорошая работа по оптимизации запросов! – Paras

+0

Если вы используете динамические пули, вы можете настроить логику разрешения привязки к модели маршрутизации и разрешить свои модели, но вы хотите: https://laravel.com/docs/5.3/routing#customizing-the-resolution-logic ИЛИ настроить ключевое имя, используемое для разрешения модели: https://laravel.com/docs/5.3/routing#customizing-the-key-name –

Смежные вопросы