Сохранять значения сводной таблицы при создании в Laravel с входом Ajax - PullRequest
0 голосов
/ 01 июня 2018

Я изучаю Laravel, создав веб-сайт рецептов.

По идее, пользователь создает рецепт, который включает название, описание и количество порций (и тегов), а затем направляется на новыйпросмотр, в котором они добавляют ингредиенты.

У меня это работает, и пользователь может успешно создать рецепт и ингредиенты, которые записываются в соответствующие таблицы, но я не могу прикрепить /синхронизировать их.

Соответствующие части моделей:

Модель рецепта:

class Recipe extends Model
{
  public function ingredients(){
    return $this->hasMany('App\Ingredient', 'recipe_ingredients');
  }
}

Модель ингредиента:

class Ingredient extends Model
{

  public function recipe(){
    return $this->belongsTo('App\Recipe', 'recipe_ingredients');
  }
}

Контроллер ингредиентов

public function store(Request $request)
{

  $this->validate($request, [
    'name' => 'required|max:255'
  ]);

  $ingredient = new Ingredient;
  $ingredient->name = $request->name;
  $ingredient->save();

  $recipe = Recipe::find($request->id);

  $recipe->ingredients()->attach($recipe_id);

  $data = [
    'success' => true,
    'message'=> 'Your AJAX processed correctly',
    'name' => $ingredient->name,
    'recipe' => $recipe
  ] ;

    return response()->json($data);
}

Если я уберу $recipe->ingredients()->attach($recipe_id);, ингредиенты сохраняются в таблице ингредиентов, но я не могуполучите recipe_id и ingredient_id для сохранения в таблице recipe_ingredients.

Я думаю Я использую присоединение неправильно, но могу ошибаться.

Примечание: Не то чтобы я думал, что это имеет какое-то значение, но я отправляю данные через Ajax.

Скрипт:

$(document).ready(function(){
  $("#submit").click(function() {
    var name = $("#ingredientName").val();
    var token = $("#token").val();

    $.ajax({
      headers: {
        'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
        },
      type: "post",
      data: "name="+name,
      dataType:'json',
      url: "{{ route('ingredients.store', ['id' => $recipe->id]) }}",
      success:function(data){
        console.log(data);
        $("#msg").html('<div class="alert alert-success my-0">'+data.name+' added</div>');
        $("#msg").toggleClass("invisible")
        $("#msg").fadeOut(2000);
        $("#ingredientsTable").append('<tr><td scope="col" class="align-middle">'+data.name+'</td></tr>');
      }
    });
  })
})

Пересмотренный контроллер

public function store(Request $request)
{

  $this->validate($request, [
    'name' => 'required|max:255'
  ]);

  $ingredient = new Ingredient;
  $ingredient->name = $request->name;
  $ingredient->save();

  $recipe = Recipe::find($request->id);
  $recipe->ingredients()->attach($ingredient->id);

  $data = [
    'success' => true,
    'message'=> 'Your AJAX processed correctly',
    'name' => $ingredient->name,
    'recipe' => $recipe
  ] ;

    return response()->json($data);
}

Таблица миграции

public function up()
{
    Schema::create('recipe_ingredients', function (Blueprint $table) {
        $table->integer('recipe_id')->unsigned();
        $table->foreign('recipe_id')->references('id')->on('recipes');

        $table->integer('ingredient_id')->unsigned();
        $table->foreign('ingredient_id')->references('id')->on('ingredients');
    });
}

Ответы [ 3 ]

0 голосов
/ 01 июня 2018

Вы используете неверный идентификатор при попытке присоединить ингредиент к рецепту:

$ingredient = new Ingredient;
$ingredient->name = $request->name;
$ingredient->save();

$recipe = Recipe::find($request->id);
$recipe->ingredients()->attach($recipe_id);

В последней строке у вас уже есть рецепт, поэтому передается $recipe_id (что я на самом деле надеваюнигде не определено) не правильная логика.

Вам нужно передать ингредиент, который вы хотите прикрепить:

$recipe->ingredients()->attach($ingredient->id);

Это должно правильно установить отношения.

0 голосов
/ 01 июня 2018

После внесения множества небольших изменений и изменений, наконец-то у меня сработало следующее:

Рецепт / модель:

class Recipe extends Model
{
  public function ingredients(){
    return $this->hasMany('App\Ingredient', 'recipe_ingredients', 'recipe_id', 'ingredient_id');
  }

Модель ингредиента:

class Ingredient extends Model
{
    public function recipes(){
    return $this->belongsToMany('App\Recipe', 'recipe_ingredients', 'ingredient_id', 'recipe_id');
}

** IngredientsController @ Store: **

public function store(Request $request)
{

  $this->validate($request, [
    'name' => 'required|max:255'
  ]);

  $ingredient = new Ingredient;
  $ingredient->name = $request->name;
  $ingredient->save();

  $recipe = Recipe::find($request->id);
  $ingredient->recipes()->attach($recipe->id);

  $data = [
    'success' => true,
    'message'=> 'Your AJAX processed correctly',
    'name' => $ingredient->name,
    'recipe' => $recipe
  ] ;

    return response()->json($data);
}
0 голосов
/ 01 июня 2018

Как показано на примере здесь: https://laravel.com/docs/5.6/eloquent-relationships#updating-many-to-many-relationships

Вы должны прикрепить ingredients вместо рецепта:

$recipe->ingredients()->attach($ingredient_id);

- edit -

Ваша модель Ingredient также имеет вид:

class Ingredient extends Model
{
  public function ingredient(){
      return $this->belongsToMany('App\Recipe', 'recipe_ingredients');
  }
}

Однако вместо этого вы должны иметь это:

public function recipes(){
    return $this->belongsToMany('App\Recipe', 'recipe_ingredients');
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...