1

I have a search() method in SubredditController

public function search(Request $request, Subreddit $subreddit)
{
    $query = $request->input('search');
    $subreddit = Subreddit::with('posts.votes')->with('moderators.user')->where('id', 24)->first();
    $posts = $subreddit->posts()->where('title', 'LIKE', '%' . $query . '%')->get();
    $isModerator = $subreddit->moderators()->where('user_id', Auth::id())->exists();
    $modList = Moderator::where('subreddit_id', '=', $subreddit->id)->get();

    return view('subreddit.search', compact('query', 'subreddit', 'posts', 'isModerator', 'modList'));
}

As you can see $subreddit is getting all posts from subreddit ID 24 and the query works.

But when I replace 24 with $subreddit->id the query fails and gives null.

EDIT: Looks like it works on $modList because I have hardcoded it 24 in the first variable $subreddit but that still doesn't answer why $subreddit->id is inaccessible when it works fine on all other methods of the same controller

EDIT 2: I have also tried changing the search route to accept a parameter, like this Route::post('search/{subreddit}') but that gives the error NotFoundHttpException and the URL redirects to localhost/reddit/public/search/%7Bsubreddit%7D it's not recognizing any parameter.

EDIT 3: if I change the search route to Route::post('subreddit/{id}/search', ...) I get no errors, but $subreddit->id remains inaccessible and the URL points to subreddit/%7Bid%7D/search (with %7B characters)

These are my bindings

$router->model('subreddit', 'App\Subreddit');
$router->model('posts', 'App\Post');
$router->model('moderators', 'App\Moderator');

My Routes

Route::resource('subreddit', 'SubredditController');

Route::resource('subreddit.moderators', 'ModeratorsController');

Route::get('mysubreddits', [
    'as' => 'mysubreddits',
    'uses' => 'SubredditController@mySubreddits'
]);

Route::post('search', ['as' => 'search', 'uses' => 'SubredditController@search']);

Route::resource('posts', 'PostsController');
Route::resource('votes', 'VotesController');
Route::resource('profile', 'ProfilesController');

The view (which is a partial) from where I'm sending the search request

<h4>Search {{ $subreddit->name }}</h4>
{!! Form::open(['action' => 'SubredditController@search']) !!}
<div id="custom-search-input">
    <div class="input-group col-md-12">
        <input type="text" name="search" class="search-query form-control" placeholder="Search" />
            <span class="input-group-btn">
                <button class="btn btn-danger" type="submit">
                    <span class=" glyphicon glyphicon-search"></span>
                </button>
            </span>
    </div>
</div>
{!! Form::close() !!}
14
  • 2
    It works for the second because you're setting it (hardcoded to 24) in the first one. As for why it doesn't work in the first one, I don't know. But that should at least solve half of your problem. Commented Oct 12, 2015 at 13:52
  • Thanks. You're right. Now I just need to figure out why $subreddit->id isn't working at all, even though it works on all other methods in the same controller. Commented Oct 12, 2015 at 14:02
  • Try posting your routes file. Commented Oct 12, 2015 at 14:06
  • 1
    Oh I've just realised that the specific route is the search one, and you don't specify any route parameters (Route::post('search', ...); ratehr than Route::post('search/{subreddit}', ...) so that's why it's not being populated. Right? Commented Oct 12, 2015 at 14:36
  • 1
    @Halnex if you want to have a bound model you need to specify a route parameter. So if you do what i originally said that would work. However, it wasn't working for you as your form was not passing the subreddit parameter. So now you need Form::open(['route' => ['search', $subreddit->getKey()]]) (I may be wrong about the format of the Form::open with route specified but you get the idea - you need to pass the ID in so that it turns into /search/24 and so that your model can be bound correctly. Commented Oct 12, 2015 at 15:06

1 Answer 1

2

You appear to be assuming that typehinting a model will automatically somehow give you the model in your route. However a few things need to be done in order for route model binding to work:

  1. You actually need to include the parameter in your route specification.
  2. You need to ensure you pass the ID (or whatever field you you in your model binding function) in the URL.

So, given your code the following changes are required:

Route:

Route::post('search/{subreddit}', 'SubredditController@search')->name('search');

This actually adds a the placeholder for the parameter, and names it the same as your model's route binding.

(I have also taken the liberty of rearranging the line to not have the awkward options-as-array syntax, though depending on your Laravel version this may not be doable for you.)

View:

{{ Form::open(['route' => ['search', $subreddit->getKey()]]) }}

This ensures that the first parameter to the route named search will contain the Subreddit's ID (key) value.

These two things, together, will mean that the URI ends up being something like /search/24 which will be converted into the SubredditController@search with method parameter typehinted as Subreddit pre-filled with a real model (ID of 24).


Note: if you don't wish to use IDs in your URIs but instead something like a slug field, you can still do this - bind your route as normal, but on your model define a getRouteKeyName method:

public function getRouteKeyName()
{
    return 'slug';
}

And then just change the view's Form::open to this:

{{ Form::open(['route' => ['search', $subreddit->getRouteKey()]]) }}

Again, this may be 5.1 specific and you may be using 5.0 which may or may not support doing it this way.

Sign up to request clarification or add additional context in comments.

2 Comments

With the fact that Eloquent models appear to have getRouteKeyName and getRouteKey defined in the base Model class (going on the standard key name by default) it's quite likely that you'll find that you can just pass a model into the URI generation methods instead of, as I put here $subreddit->getKey() and $subreddit->getRouteKey()` and it automatically gets the value that is required. That is to say the following may work for you: {{ Form::open(['route' => ['search', $subreddit]]) }}.
thank you mate, yes indeed $subreddit works without getKey() however, I am trying the exact same thing you've shown me here on the Comments form. I am passing $post to the form and using {post} on the comment route. But I am still unable to access $post->id it's very confusing.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.