Laravel - “Method Illuminate \\ Database \\ Query \\ Builder :: recipes不存在

I've looked at a few similar issues on SO, but I can't work out why recipes is being called?

I'm building a recipes website, and the user can create tags, create a recipe, create ingredients which are assigned to the recipe, and will be able to create steps which use the ingredients.

The following are my models:

Ingredient.php

class Ingredient extends Model
{
  protected $touches = ['recipes'];

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

  public function step(){
    return $this->belongsToMany('App\Step', 'step_ingredients');
  }

}

Recipe.php

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

  public function tags(){
    return $this->belongsToMany('App\Tag', 'recipe_tag');
  }

  public function user(){
    return $this->belongsTo('App\User');
  }

  public function steps(){
    return $this->hasMany('App\Step');
  }
}

Step.php

class Step extends Model
{

  protected $touches = ['recipes'];

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

  public function ingredient(){
    return $this->belongsToMany('App\Ingredient', 'step_ingredient');
  }
}

The following is my StepsController which I'm saving to from my steps/create.blade.php file via an Ajax submit with jQuery.

use Illuminate\Http\Request;
//use Session;
use App\Recipe;
use App\Tag;
use App\Step;
use App\Ingredient;

class StepsController extends Controller
{
    public function __construct()
    {
        $this->middleware('auth');
    }

    public function create($recipe_id)
    {
      $recipe = Recipe::find($recipe_id);
      return view('steps.create')->withRecipe($recipe);
    }

    public function store(Request $request)
    {

      $step = new Step;
      $step->recipe_id = 2;
      $step->step_no = 2;
      $step->is_prep = 1;
      $step->duration = '00:14:01';
      $step->method = 'test';
      $step->save();

      $data = [
        'success' => true,
        'message'=> 'Your AJAX processed correctly',
        'ing' => json_decode($request->ingredients),
        'desc' => $request->description
      ] ;

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

I'm using static values for the new Step to make sure that it writes to the db correctly, and it is.

If I comment out writing the step to the db, and just leave the $data array and return response... then it works fine, and I get the success response returned to the view.

When I include it, I get the error in the console:

[Error] Failed to load resource: the server responded with a status of 500 (Internal Server Error) (steps, line 0)

"message": "Method Illuminate\\Database\\Query\\Builder::recipes does not exist.",

But I'm not sure where the recipes method is being called?! I think it has something to do with my relationships in the model?

Any insight would be extremely appreciated.

Not sure if it's required, but the following is the part of my script that I"m using so submit data with Ajax.

$("#addStepNew").click(function() {
    var step_ingredients = JSON.stringify(stepIngredients)
    var step_description = $('#stepDescription').val();
    // var prep_step = $('input[name=prepStep]:checked').val();

  $.ajax({
    headers: {
      'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
      },
    type: "post",
    data: {ingredients: step_ingredients, description: step_description},
    dataType:'json',
    url: "{{ route('steps.store', ['id' => $recipe->id]) }}",

    success: function (data) {
      $("#ajaxOutput").html('<code>Description output: '+data.desc+'</code>');
      $.each(data.ing, function (key, value) {
        $("#ajaxOutput").append('<br><code>'+value.ingredient_name+'</code>');
      });          
    },
    error: function (xhr, ajaxOptions, thrownError) {
      console.warn(xhr.responseText);
      alert(xhr.status);
      alert(thrownError);
    }
  });
});

It looks like it's the protected $touches = ['recipes']; from the Step model.

I guess it's trying to update a recipe that it's associated to, but that isn't being defined with a recipe_id.