How to make pagination API in laravel using POST method - laravel

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;
}

Related

Laravel Automatic resource CRUD

What patterns can I use for 'automatic' resource CRUD operations for given Models in Laravel?
Say I have two models SomeModel and SomeRelatedModel where some_related_model.some_model_id is an FK to SomeModel.
The standard method on the SomeModelController for handling the create POST /api/someModel might look like this:
public function store(Request $request)
{
$user = Auth::guard('api')->user();
$data = $request->get('data');
$data['user_id'] = $user->id;
$someModel = SomeModel::create($data);
// has this request been made with the data for the
// related model? If so create this too.
if($data['relatedModel']){
SomeRelatedModel::create(array_merge(
['some_model_id' => $someModel->id]
$data['relatedModel']
));
}
// has this request been made expecting to get related
// models back in the response? If so load these
if($request->has('with')){
$someModel->load($request->get('with'));
}
return (new PostResource($post))
->toResponse($request)
->setStatusCode(201);
}
This works but is very verbose and for models with a sub-sub relation would need changing further. Similar work will need to be done for the other endpoints for all resources.
Is there a more versatile (or tidy) pattern using out-of-the box classes to get a similar effect?
Have a look at Laravel Orion. Fits your use case.

How to attach id of table to request in laravel while validating?

The Laravel form request validator runs a query when using exists.
'item_name'=>'required|exists:items,name'
After validating for saving data I need to again run the same query and find items.id
Can I prevent this extra query?
I'm using validation for 1000 rows in csv. Please suggest other optimization techniques if any.
I finally used collection of all items inside FormRequest constructor.
Item::all();
this would get huge amount of data but would prevent running query n times.
Inside witValidator function
public function withValidator(Validator $validator,Array $row): Validator
{
$validator->after(function ($validator)use($row) {
$exists = $this->item_collection->firstWhere('id',$this->id);
if(!$exists){
$validator->errors()->add('id','id not found');
}
});
}

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.

Laravel6 WhereHas Error 500 when using AJAX

im new to Laravel and facing an interesting Issue right now in my App.
I have 3 tables.
Producers
id
producer_name
Types
id
type_name
Models
id
model_name
device_type_id
device_producer_id
Within my Producers Model I have defined the follwing Filter method:
public function scopeFilterByType($query, $type_id)
{
$query->whereHas('models', function($q) use $type_id { $q->where('device_type_id', $type_id );});
}
Using Tinker I can do the following:
App\DeviceProducer::filterByType(3)->get()
And get full response with my Producers associated to my given type.
I created an Function so when a user select a device type Ajax will load all Producers from this type.
public function reqProducer(Request $request)
{
$producers = DeviceProducer::filterByType($request->type_id)->get();
return response()->json( $producers );
}
But when AJAX is calling my endpoint it gets HTTP500 error.
I figured out when using a request without WhereHas for example:
$producers = DeviceProducer::where('id', $request->producer_id)->get();
It just works fine and I get my results. So it seems have to do something with "WhereHas". I know I could Solve this by first asking Models Table and the creating an Foreach loop. But I this solution would be less readable then my first attempt.
Does anyone has an suggestion what im doing wrong or is it just like there is noch AJAX support for WhereHas querys?
Kind regards
Mike
I think this is your issue use $type_id
Please fix as
public function scopeFilterByType($query, $type_id)
{
$query->whereHas('models', function($q) use ($type_id) { $q->where('device_type_id', $type_id );});
}

How to call several actions from within another action?

I'm migrating a non-MVC application to Laravel 4.2 and I'm unsure of the best way to accomplish this task. I have several reports created on routes like this:
/reports/this_report
/reports/that_report
/reports/another_report
These actions query the database, run a bunch of calculations, and generate some html tables and forms.
What I need to add now is a page like this:
/reports/dashboard
This dashboard page should display the output of all 3 reports in a condensed format, each with a "click to view details" link that takes the user to the main report page.
Is there a way for the dashboard action to call each of the report actions, and use their output as data in the dashboard view?
Here's a little code of how you would do this. I'm not exactly sure how you have everything structured, so you might have to adapt this a little.
Lets say you have a route for the dashboard like this.
Route::get('/reports/dashboard', DashboardController#showDashboard');
This route should call a controller method that will do your processing.
class DashboardController extends BaseController
{
public function showDashboard()
{
return View::make('dashboard')->with(array(
'report1_data' => $this->getReport1Data(),
'report2_data' => $this->getReport2Data(),
'report3_data' => $this->getreport3Data()
));
}
public function getReport1Data() { //calculations, return array of results }
public function getReport2Data() { //calculations, return array of results }
public function getReport3Data() { //calculations, return array of results }
public function showThisReport()
{
$data = $this->getReport1Data();
return View::make('report')->with(array('data' => $data));
}
public function showThatReport()
{
$data = $this->getReport2Data();
return View::make('report')->with(array('data' => $data));
}
public function showAnotherReport()
{
$data = $this->getReport3Data();
return View::make('report')->with(array('data' => $data));
}
}
So, this dashboard method will call the other methods (that you will also include in this controller) that will query the database and calculate the reports.
Then it returns a View with all of the data. The view will format the data and display it to the user.
Now, to make it so you can see the detailed view of each report, I suggest adding a couple more methods and routes to show detailed views.
Route::get('/reports/this_report', 'DashboardController#showThisReport');
Route::get('/reports/that_report', 'DashboardController#showThatReport');
Route::get('/reports/another_report', 'DashboardController#showAnotherReport');
I hope this helps! Good luck.

Resources