How to make a laravel view that uses data from a controller but also still allows the controller to output raw JSON? - laravel

I have a controller that outputs data from the database in raw JSON format.
I want this to function as an API and allow anyone to make views with any technology that can consume the JSON i.e. Angular, Jquery/Ajax.
However I also want to make a view in Laravel.
So what's the best practice for creating a view from Laravel that uses data from a controller while still allowing the controller to output raw JSON?
The options I'm thinking of are to call the controller from the view(not good?) or to create extra routes.

Route::get('sample', function ()
{
$data = getDataFromSomewhere();
if (Request::ajax())
{
return Response::json($data);
}
return View::make('some.view', compact('data))
});

I would separate API controllers, but you could do something like this if you want one controller to handle all response formats:
URL:
mySite.com/getData?output=json
Controller:
public function index()
{
$data = MyModel::all();
switch(Request::query('output')){
case 'json':
return Response::json($data, $this->responseCode, $this->accessControl);
case 'xml':
return Response::make($data, '200')->header('Content-Type', 'text/xml');
default:
return View::make('data.myData', compact($data));
}
}

Related

How to make pagination API in laravel using POST method

Suppose i need to fetch user money transactions there are 100+ transactions in database and i need to send all the user transactions through the API to a android app, i have idea how to make using GET method but using GET method its not Dynamic.
In API i'm sorting data by 4-5 parameters in API input using post method
And i want to make this API for infinite Scrolling
And i'm using Stored Procedure for getting data
Then How can i achieve Laravel pagination in POST method?
my current response something like this
{
"Transactions"[
{
"name":"food";
"amount":100;
}
]
}
Actually, you can do it in multiple ways but the way I use most is like below
public function getTransaction(Request $request)
{
$transactions = Transactions::where('SOME-Condition', $request->Condition)->paginate(10);
$sorted = $transactions ->sortBy([
['name', 'asc'],
['age', 'desc'],
]);
return $sorted;
}
or you can also do it like this
public function getTransaction(Request $request)
{
$transactions = Transactions::where('SOME-Condition', $request->Condition)
->orderBy('abc')
->orderBy('def')
->paginate(10);
return $sorted;
}

Sending different data from different method on same route - laravel 8

I am trying to get order data in order tab and profile details data in profile tab.
Is it possible to achieve ???
If Yes, then please tell me how ?
If No, then please tell me, laravel is the most advance framework of PHP, why we can't send multiple data from multiple methods in same View ?
Controller
public function GetOrders()
{
$gtord = DB::table('orders')->where('email',Session::get('email'))->get();
return view('/my-account')->with('gtord',$gtord);
}
public function ProfileEdit()
{
$data = DB::table('customers')->where('email',Session::get('email'))->first();
return view('/my-account')->with('data',$data);
}
Routes
Route::get('/my-account', 'App\Http\Controllers\CustomerController#ProfileEd');
Route::get('/my-account', 'App\Http\Controllers\CustomerController#GetOrders');
Thank you in advance
You can't have multiple routes with the same 'signature', ie method and url.
If you're just showing/hiding tabs using JS, what you can do is return the view with two variables, eg:
public function AccountView()
{
$data = DB::table('customers')->where('email',Session::get('email'))->first();
$gtord = DB::table('orders')->where('email',Session::get('email'))->get();
return view('/my-account')->with(['data' => $data, 'gtord' => $gtord]);
}
And then just use one route:
Route::get('/my-account', 'App\Http\Controllers\CustomerController#AccountView');
If the two tabs are different urls, or you're using Vue or similar you would have two distinct routes with different signatures.
First, you can't have 2 same routes with the same method. It's quite logical and necessary. Otherwise, the whole routing system would collapse.
On the other hand, you can have a function in the controller, and call the other functions to collect data.
// web.php
Route::get('/my-account', 'App\Http\Controllers\CustomerController#index');
// controller
public function index()
{
$orders = $this->getOrders();
$profile = $this->getProfiles();
return view('yourView', compact(['orders', 'profile']));
}
public function getOrders()
{
//
}
public function getProfiles()
{
//
}
BTW, it's a better practice to move custom function to models, services or traits, and keep only the functions of 7 verbs in the contoller.

Best practices to define response in action controller Laravel

I have a method inside PostController
class PostController extends Controller {
public function index() {
$posts = Post::all();
return response($posts);
}
}
Two way:
class PostController extends Controller {
public function index() {
$posts = Post::all();
return $posts;
}
}
Both work fine but which way is better and more correctly?
I personnaly prefer this version:
return \Response::json($data);
Because it makes clear that the response is actual json data.
Just make sure your code is understandable by someone new on your project.
If you are writing an API project, where everything is always returned in json, simply return the model because you don't have to make the reader learn that it's JSON because everything is in JSON everywhere.
On the other hand, if it's some sort of mixed project (some routes return view, JSON, XML, whatever), try to make is as obvious as you can that this specific route return JSON data and nothing else.
Also as stated in comments, stay consistent. The shorter isn't the better. The better is the one that is simple to read and give enough info about what's going on.
It doesn't matter actually.. its depends on your desire and consistency..
return Response::json($model);
//or
return response()->json($model);
//or
return $model;
it give you same output..but if you using response, you can set the status code. most of the time, this reponse thing is used in API project.

Managing views and api from the same controller

I have an issue with my app, that is "hybrid", what I mean by "hybrid" controllers have to manage both views ans APIs.
So, basically, for each controller, I must check:
if $request->wantsJson(){
... // Client rendering using Angular, return json
}else{
// Server rendering Using blade, return view
}
I don't like the fact to have a conditional in every controller method.
I also wouldn't like to have a API folder with a copy of all my controller, there would be a lot of duplicated code.
How should I do it?
I would suggest to create a separate class to handle output ex: class ResultOutput with the method, output.
So, in your controller, when you are ready to output your data, just create a new instance of ResultOutput class, and call method output with relevant data.
In ResultOutput class, inject Request object so you can determine the method of the output based on above logic.
Ex: In your controller:
return (new ResultOutput())->output($data);
In ResultOutput class:
class ResultOutput()
{
private $type;
public __construct(Request $request) {
$this->output = 'view';
if ($request->wantsJson()) {
$this->output = 'json';
}
}
public method output($data) {
if ($this->type =='view') {
// return the view with data
} else {
// return the json output
}
}
}
In this way, if you need to introduce new output method (ex: xml), you can do it without changing all your controllers.

How to retrieve HTML from view object without rendering to the browser

I have 2 separate partials views. I want to get the HTML with the given data from those partials views and have to send a Json response from controller.
Here is my code snippet.
public function myControllerFunction()
{
$response['products'] = view('search._partials.product_box')->with('data', $data['products]);
$response['filters'] = view('search._partials.facet_filters')->with('data', $data['filters]);
return $response;
}
I want to achieve some thing like it. This is possible with plain php code but is there any way to achieve it with this framework.
Just use render() function to generate html from view in controller
Your function should look like this
public function myControllerFunction()
{
$response['products'] = view('search._partials.product_box')->with('data', $data['products])->render();
$response['filters'] = view('search._partials.facet_filters')->with('data', $data['filters])->render();
return response()->json($response);
}

Resources