Martyn
Martyn

Reputation: 6383

In laravel view() function within a controller, can this detect an AJAX request

In my controller, I have something like the following:

public function index()
{
    $questions = Question::all();

    return view('questions.index', compact('questions'));
}

However, I would like this route to also be used by my ajax requests. In which case, I'd like to return JSON. I'm considering the following:

public function index()
{
    $questions = Question::all();

    return $this->render('questions.index', compact('questions'));
}

public function render($params)
{
    if ($this->isAjax()) {
        return Response::json($params);
    } else {
        return view('questions.index')->with($params);
    }
}

..by the way, I haven't tested any of this yet, but hopefully you get the idea.

However, I was wondering if I can alter the built in view(...) functionality itself to keep things even lighter. So I just keep the following:

public function index()
{
    $questions = Question::all();

    // this function will detect the request and deal with it
    // e.g. if header X-Requested-With=XMLHttpRequest/ isAjax()
    return view('questions.index', compact('questions'));
}

Is this possible?

Upvotes: 0

Views: 791

Answers (4)

Suresh Bala
Suresh Bala

Reputation: 2362

Simply check if the Request is an Ajax request in your index method itself.

public method index() {
  $questions = Question::all();
  if(\Request::ajax())
   return \Response::json($questions);
  else
   return view('questions.index', compact('questions'));
}

Upvotes: 1

Martyn
Martyn

Reputation: 6383

I guess the simple method is just to put a method inside the parent Controller class:

use Illuminate\Routing\Controller as BaseController;

abstract class Controller extends BaseController {

    ...

    protected function render($view, $data)
    {
        if (Request::ajax()) {
            return Response::json($data);
        } else {
            return view($view, $data);
        }
    }
}

and then instead of doing view('questions.index, $data);, do $this->render('questions.index', $data);

Upvotes: 0

Limon Monte
Limon Monte

Reputation: 54389

You probably want to make custom response:

  1. add ResponseServiceProvider.php

namespace App\Providers;

use Request;
use Response;
use View;
use Illuminate\Support\ServiceProvider;

class ResponseServiceProvider extends ServiceProvider
{
    /**
     * Perform post-registration booting of services.
     *
     * @return void
     */
    public function boot()
    {
        Response::macro('smart', function($view, $data) {
            if (Request::ajax()) {
                return Response::json($data);
            } else {
                return View::make($view, $data);
            }
        });
    }

    /**
     * Register any application services.
     *
     * @return void
     */
    public function register()
    {
        //
    }
}
  1. Add 'App\Providers\ResponseServiceProvider' to providers list in config/app.php:
'providers' => [
    'App\Providers\ResponseMacroServiceProvider',
];
  1. Use new helper in controller:
return Response::smart('questions.index', $data);

Upvotes: 1

Joseph Silber
Joseph Silber

Reputation: 219940

Use Request::ajax(), or inject the request object:

use Illuminate\Http\Request;

class Controller {

    public function index(Request $request)
    {
        $data = ['questions' => Question::all()];

        if ($request->ajax()) {
            return response()->json($data);
        } else {
            return view('questions.index')->with($data);
        }
    }

}

Your view should never know anything about the HTTP request/response.

Upvotes: 0

Related Questions