Search in data from cache - php

My question is, if there is data in the cache, I created a condition by saying fetch, and if not, I bring it from the database and refresh the cache for a certain period of time. Normally, if I don't use the cache, I can search the page, but I cannot search by id or nickname with the code below.So when using cache::get can I add a search condition?
public function index(Request $request)
{
$submit = $request->get('submit');
$id = $request->get('id');
$nick_name = $request->get('nick_name');
if (Cache::has('users')) {
$users = Cache::get('users');
return view('admin.users.index', compact('users'));
}
$users = User::when(!empty($id), function ($query) use ($id) {
$query->where('id', $id);
})->when(!empty($nick_name), function ($query) use ($nick_name) {
$query->where('nick_name', $nick_name);
})->orderBy('created_at', 'asc')->get();
Cache::put('users', $users, now()->addMinutes(60));
return view('admin.users.index', compact('users'));
}
Update: Based on the examples on the page below, the problem was solved
https://www.honeybadger.io/blog/caching-in-laravel/

You should add search criteria in your cache key. E.g.
public function index(Request $request) {
$submit = $request->get('submit');
$id = $request->get('id');
$nick_name = $request->get('nick_name');
$cacheKey = User::class . md5(json_encode([$submit, $id, $nick_name]));
if (Cache::has($cacheKey)) {
/* ... */
}
because now your cache writes only first search result and ignores everything else.
Or write to cache all users. Then run that array through array_filter applying filters. But that can be waste of developer time if search is very dynamic.

Related

I am trying to pass searched query based on user input to my dompdf view

i want to use the result of that query and pass it into my pdfview and create a pdf based on the result. i have using sessions but did not work, is there any other solution
my controller for the search query:
public function index(Request $request){
$rsearch= $request->rsearch;
$fromdate= $request->fromdate ;
$todate= $request->todate ;
$rents = DB::table('rentcollection')
->join('tenants','rentcollection.AccountNo','=','tenants.AccountNo')
->join('propertys','tenants.PropertyID','=','propertys.PropertyID')
->select(DB::raw("CONCAT(tenants.OtherNames,' ',tenants.Surname) as
Fullname"),'rentcollection.Date as Date','rentcollection.Amount as
Amount','rentcollection.Period as Period','rentcollection.ReceiptNo as
Receipt','tenants.RegDate
as RegDate', 'tenants.AccountNo as Accno','tenants.Rent as Rent',
'tenants.NoOfProperty as
NoOfProperty','propertys.Address as Address','propertys.Property as Property')
->where('propertys.Address','like','%'.$rsearch.'%')
->whereBetween('Date', [$fromdate, $todate])
->paginate(20);
return view('reports.rent', compact('rents',));
}
my controller for creating pdf:
public function createPDF(Request $request){
$datas = $request->session()->get('cart');
$pdf = PDF::loadView('pdf.rent', ['orderedrent' => $datas,])->setPaper('A4','landscape');
return $pdf->stream('invoice.pdf');
}

How Can I get Latest 5 Commentors user information By Laravel Relational Eloquent eager loading

I'm in a situation where I need to display the last 5 unique commenters information at the top of the comment list as follows screenshot.
comment image
To do this. I did as follows:
Post Model
public function comments()
{
return $this->hasMany(Comment::class);
}
public function commenter_avatars(){
return $this->comments()->distinct('user_id')
->select('id','post_id','user_id','parent_id')
->whereNull('parent_id')
->with('user')->limit(5);
}
My Controller method as follows
public function index() {
$feeds = auth()->user()
->posts()
->with(['user:id,first_name,last_name,username,avatar', 'media', 'commenter_avatars'])
->orderBy('id', 'desc')
->paginate(10);
return PostResource::collection($feeds);
}
I tried to use groupBy and Distinct.. But did't work as expected.
Did I miss something? or Have there any more best way to solve this?
Thank you in advance!
Noted: I am using latest Laravel (8.48ˆ)
I don't know about your joining of post, user and comments table. But i guess, you can do something similar to following.
At first get latest 5 unique user id of one post:
$userIds = Comments::where("post_id", $post_id)->distinct("user_id")->orderBy("id")
->limit(5)->pluck('user_id');
Then, fetch those user information
$users = Users::whereIn("id", $userIds )->get();
Then, you can return those users
UPDATE
You may use map() to fetch and reorder output. Following is an idea for you:
In Controller:
public function index(Request $request) {
$skipNumber = $request->input("skip"); // this is need for offsetting purpose
$userIds = [];
$feeds = Posts::with("comments")->where("comments.user_id", Auth::id())
->skip($skipNumber)->take(10)->orderBy('comments.id', 'desc')
->map(function ($item) use($userIds){
$users = [];
$count = 0;
foreach($item["comments"] as $comment) {
if(!in_array($comment["user_id"], $userIds) && $count < 5){
$count++;
$userIds.push($comment["user_id"])
$user = User::where("id", $comment["user_id"])->first();
$users.push($user);
}
if($count == 5) break;
}
$data = [
"post" => $item,
"latest_users" => $users
];
return $data;
})->get();
return PostResource::collection($feeds);
}
My code syntax may be slightly wrong. Hopefully you will get the idea.
I have solved this issue by using eloquent-eager-limit
https://github.com/staudenmeir/eloquent-eager-limit

How to match two tables and insert it into another table in laravel 5.4?

I need to match two tables and insert it into the disbursment table, so this is my code...
public function store(Request $request)
{
//Approved Request
$approvedRequest= DB::table('request')
->where('users_MemId',Auth::user()->MemId)
->where('requestStatus','Approved')
->join('requestdetails','request.requestId','=','requestdetails.request_requestId')
->join('itemattribute','requestdetails.RequestDetailsId','=','itemattribute.RequestDetailsId')
->join('exudeinventory', 'itemattribute.AttrName', '=', 'exudeinventory.ItemName')
->select('itemattribute.AttrName', 'exudeinventory.InventoryId', 'request.requestId')
->get();
// dd($approvedRequest);
store function.
I've tried matching the tables and I can't figure out on how to insert the values in another table or if I am doing it right.
I've been looking for solutions but still I can't figure it out, Hope that someone would help me and explain it to me, I am new to laravel T,T
Maybe you can do this:
public function store(Request $request)
{
//Approved Request
$approvedRequest= DB::table('request')
->where('users_MemId',Auth::user()->MemId)
->where('requestStatus','Approved')
->join('requestdetails','request.requestId','=','requestdetails.request_requestId')
->join('itemattribute','requestdetails.RequestDetailsId','=','itemattribute.RequestDetailsId')
->join('exudeinventory', 'itemattribute.AttrName', '=', 'exudeinventory.ItemName')
->select('itemattribute.AttrName', 'exudeinventory.InventoryId', 'request.requestId')
->get()
->each (function ($request, $key) {
$dis = new Disbursment;
$dis->DisbursmentId = rand(1, 999999);
$dis->ItemImage = 'default.jpg';
$dis->ItemTypeId = $request->AttrName;
$dis->exudeinventory_InventoryId = $request->InventoryId;
$dis->request_requestId = $request->requestId;
$dis->save();
});
}

Search all method missing where argument in Laravel 5

I'm trying to write a method in my controller to allow searching the results of my query on my view page. The query selects all results from the "ads" table and this method should allow filtering results by the ad's name inputting keywords in the search bar.
The controller code goes like this:
public function index(Request $request)
{
$title = trans('ad.title');
$ads = Ad::paginate(10);
if (!empty($request->input('search_all'))) {
$search_all = urldecode($request->input('search_all'));
$ads->where(function ($query) use ($search_all) {
$query->where('name', 'like', '%'.$search_all.'%')->get();
});
}else {
// Returning to view
return view('admin.ad.list')
->with('ads', $ads)
->with('title', $title);
}
}
However, when I run a search I get the following error: "Missing argument 2 for Illuminate\Support\Collection::where()".
What am I doing wrong?
At the top, when doing $ads = Ad::paginate(10); you have already pulled the results from the database so no more filtering can be done at DB level.
I'd do something like this instead:
public function index(Request $request)
{
$title = trans('ad.title');
$ads = Ad::select();
if ($request->input('search_all')) {
$search_all = urldecode($request->input('search_all'));
$ads->where('name', 'like', '%'.$search_all.'%');
}
// Returning to view
return view('admin.ad.list')
->with('ads', $ads->paginate(10))
->with('title', $title);
}

Laravel previous and next records

I am trying to create a page where I can see all the people in my database and create edits on them. I made a form where I fill in the data from the database of certain fields.
I would like to navigate trough them by a Next and Previous button.
For generating the next step I have to take the ID larger than the current one to load the next profile.
For generating the previous step I have to take the ID smaller than the current one to load the previous profile.
My route:
Route::get('users/{id}','UserController#show');
Controller:
public function show($id)
{
$input = User::find($id);
// If a user clicks next this one should be executed.
$input = User::where('id', '>', $id)->firstOrFail();
echo '<pre>';
dd($input);
echo '</pre>';
return View::make('hello')->with('input', $input);
}
View:
The buttons:
Next
What is the best approach to get the current ID and increment it?
Below are your updated controller and view files derived from #ridecar2 link,
Controller:
public function show($id)
{
// get the current user
$user = User::find($id);
// get previous user id
$previous = User::where('id', '<', $user->id)->max('id');
// get next user id
$next = User::where('id', '>', $user->id)->min('id');
return View::make('users.show')->with('previous', $previous)->with('next', $next);
}
View:
Previous
Next
// in your model file
public function next(){
// get next user
return User::where('id', '>', $this->id)->orderBy('id','asc')->first();
}
public function previous(){
// get previous user
return User::where('id', '<', $this->id)->orderBy('id','desc')->first();
}
// in your controller file
$user = User::find(5);
// a clean object that can be used anywhere
$user->next();
$user->previous();
In your App\Models\User.php
...
protected $appends = ['next', 'previous'];
public function getNextAttribute()
{
return $this->where('id', '>', $this->id)->orderBy('id','asc')->first();
}
public function getPreviousAttribute()
{
return $this->where('id', '<', $this->id)->orderBy('id','asc')->first();
}
In your Controller you can simply do this:
public function show(User $user)
{
return View::make('users.show')
->with('user', $user)
->with('previous', $user->previous)
->with('next', $user->next);
}
I understand the approach being taken here by user2581096 but I am not sure it is efficient (by any standards). We are calling the database 3 times for really no good reason. I suggest an alternative that will be way more efficient and scalable.
Do not pass the previous and next IDs to the view. This eliminates 2 unnecessary database calls.
Create the following routes:
users/{id}/next
users/{id}/previous
These routes should be used in the href attributes of the anchor tags
Add methods in the controller to handle each of the new routes you have created. For example:
public function getPrevious(){
// get previous user
$user = User::where('id', '<', $this->id)->orderBy('id','desc')->first();
return $this->show($user->id);
}
This function will only be called when you actually click on the button. Therefore, the database call is only made when you need to actually look up the user.
in-case you want to retrieve the prev/next records along with their data,
you can try
$id = 7; // for example
$prev = DB::table('posts')->where('id', '<', $id)->orderBy('id','desc')->limit(1);
$next = DB::table('posts')->where('id', '>', $id)->limit(1);
$res = DB::table('posts')
->where('id', '=', $id)
->unionAll($prev)
->unionAll($next)
->get();
// now $res is an array of 3 objects
// main, prev, next
dd($res);
1- the query builder is usually much faster than eloquent.
2- with union we are now only hitting the db once instead of 3.
To get next and previous post we can use max and min functions on Model id in laravel. here is an example to get this
https://usingphp.com/post/get-next-and-previous-post-link-in-laravel
The Controller:
public function post($id)
{
$post = Post::find($id);
$previous = Post::where('id', '<', $post->id)->max('id');
$next = Post::where('id', '>', $post->id)->min('id');
return view( 'post', compact( 'post', 'next', 'previous' ));
}
The View:
#if($next)
{{$next->title}}
#endif
#if($previous)
{{$previous->title}}
#endif
Here's a link I found that should help: http://maxoffsky.com/code-blog/laravel-quick-tip-get-previous-next-records/
It looks like for next you want to use: $next = User::where('id', '>', $id)->min('id'); and have the view as: Next
Also don't forget to pass $next to the view.
Simplest approach
// User.php
public static function findNext($id)
{
return static::where('id', '>', $id)->first();
}
// UserController.php
$nextUser = User::findNext($id);
// view
Next
Lazy approach :
// view
Next
// routes.php (should be optimized, this is just to show the idea)
Route::get('users/{user}/next', function($id) {
$nextUser = User::findNext($id);
return Redirect::to('user/' . $id);
});
// yourModel.php
public function previous()
{
return $this->find(--$this->id);
}
public function next()
{
return $this->find(++$this->id);
}
Works like magic, you can chain it:
$prevprev = Model::find($id)->previous()->previous();
$nextnext = Model::find($id)->next()->next();
First, get a record out of the database.
$post = Post::where('slug', $slug)->first();
With a database record, we can get the previous record where the record id is less than the id stored inside $post order by the id in descending order and use first() to get a single record back.
$previous = Post::where('id', '<', $post->id)->orderBy('id','desc')->first();
To get the next record it's almost the same query, this time get the record where the id is more than the id stored in $post.
$next = Post::where('id', '>', $post->id)->orderBy('id')->first();
Controller:
public function show($id)
{
// get the current user
$user = User::find($id);
// get previous user id
$previous = User::offset($user->id-2)->first();
// get next user id
$next = User::offset($user->id)->first();
return View::make('users.show')->with('previous', $previous)->with('next', $next);
}
i developed the code.
it work all times, even if we don't have any next or prev post
public function nextPost($table, $id)
{
$next = DB::table($table)->where('id', '>', $id)->orderBy('id','asc')->first();
if(!$next)
$next = DB::table($table)->orderBy('id','asc')->first();
return $next;
}
public function prevPost($table, $id)
{
$prev = DB::table($table)->where('id', '<', $id)->orderBy('id','desc')->first();
if(!$prev)
$prev = DB::table($table)->orderBy('id','desc')->first();
return $prev;
}

Categories