Jondev01
Jondev01

Reputation: 35

AJAX request to Laravel resource controller, best practice

I have set up a resource controller in Laravel with the following index function:

public function index()
{
    if (!Auth::check()) {
        return redirect()->route('login');
    }
    $decks = Auth::user()->decks->sortByDesc('name');
    return view('decks.index')->with('decks', $decks);                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          
}

On a different page I also need the $decks variable via a AJAX call. Right now I have set up an additional route to my controller, from which I can retrieve the decks via a GET request:

public function getDecks()
{
    if (!Auth::check()) {
        return;
    }
    $decks = Auth::user()->decks->sortByDesc('name');
    return response()->json($decks);                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          
}

My question: Is there a way to get the $decks variable via a request directly to index or is my solution the way to go?

If I make a get request to index I get the HTML of the decks.index view, but how can I access (if possible) the $decks variable?

I guess what I don't really grasp is this: What happens to $decks in the ->with('decks', $decks) statement? I know I can then access $decks using blade syntax on that page, but from where does it access the data and can I also access it via AJAX?

Upvotes: 2

Views: 2099

Answers (3)

Mihai Matei
Mihai Matei

Reputation: 24276

Yes! You can return different results depending on what kind of request was done. There is no need for 2 routes:

public function index(Request $request)
{
    $decks = Auth::user()->decks->sortByDesc('name');

    if ($request->ajax()) {
        return response()->json(['decks' => $decks]);
    } else {
        return view('decks.index')->with('decks', $decks);
    }
}

@Sven Hakvoort is right, you should check for authentication in the route definition:

Route::group(['middleware' => 'auth'], function () {
    Route::get('/decks', 'DecksController@index');
    // ... some other routes which requires authentication
}

Upvotes: 3

Thursday42
Thursday42

Reputation: 197

Your solution is the proper way. It is not typically a good idea to handle any business logic or data retrieval using your routes - using a controller is preferred, which is what you are doing. If you want to avoid the if (Auth::check()) statement in your controller, you could add the auth middleware directly to that route like this.

Route::get('example', 'YourController@index')->middleware('auth');

Regarding your question about ->with('decks', $decks): That function is sending your $decks variable to the view to be rendered in the blade template. That data is used by the server to render the page, and then the variable is discarded. If you want to also be able to work with that data on your page using javascript, you could do something like this in your blade template.

<script>
    var decks = {!!$decks->toJSON()!!};
</script>

Upvotes: 0

Sven Hakvoort
Sven Hakvoort

Reputation: 3621

You can not retrieve the $decks from the index route directly. When you call view(..)->with(...) it is internally passed to the blade template processor which also receives the $decks variable, the HTML is then build on the server-side and the 'compiled' HTMl is then returned to the browser. So once the server returns the result the $decks variable is not present anymore. Because of this behavior it is not possible to do what you want.

So yes, your solution is the way to go, although you might consider wrapping the Auth::check() in a middleware and move the call to $decks to a separate function in order to simplify your code.

I hope this answers your question, if anything is unclear feel free to ask!

Upvotes: 0

Related Questions