Laravel Eloquent 'with' has empty result - php

I am working on a small API based on Laravel 5.3 passport (https://laravel.com/docs/5.3/passport).
After Googling a lot I didn't find an answer yet to my problem.
I got the following function that has to retrieve the people I follow from the database. This is working great. After that I need to grab all friends statuses from the DB with the user info, drink info, file info and toast info. This also works great. It isn't working when file or toast or drink is empty. I get an empty array back.
The function:
public function index(Request $request)
{
$user = $request->user();
$friends = Follow::with(['user'])->where('follows_user_id', '=', $user->id)->get();
foreach ($friends as $friend) {
$status = Status::with(['user', 'drink', 'file', 'toast'])->where(
'user_id', '=', $friend->id
)->CreatedAtDescending()->get();
}
if (!isset($status) || empty($status)) {
return response(['message' => 'Nothing found.'], 404);
}
return $status;
}
How can I get the result back, even when the drink or file or toast is empty?

I got it working! The solution is:
public function index(Request $request)
{
$user = $request->user();
$friends = Follow::with(['user'])->where('follows_user_id', '=', $user->id)->get();
foreach ($friends as $friend) {
$status = Status::with(['user' => function ($query) use ($friend) {
$query->where('id', '=', $friend->following_user_id);
}, 'drink', 'file', 'toast'])->get();
}
if (!isset($status) || empty($status)) {
return response(['message' => 'Nothing found.'], 404);
}
return $status;
}
It where just some small issues in the query.

Related

Laravel output from SQL validation when record not exists

I'm learning Laravel and I have a question that I do not understand.
I'm using query builder to run my own queries and I don't really know how to return error message when there is no record:
public function store()
{
$item = request()->validate([
'item' => 'required|min:6|max:10'
]);
$details = DB::connection('sqlsrv')->table('TABLENAME')->where('ITEMID', '=', $item )->get();
return view('itemdetails.create', compact('details'));
}
So if $details is null I need to return message how to do that? Something like in raw PHP
if(empty($details))
{
throw new Exception('My text')
}
Or check in a blade file:
#if (count($details) != 1)
I don't have a record!
#endif
I tried firstOrFail but looks like this is not working.
Is there any other ways (best ways)?
In controller
$validator = \Validator::make($request->all(), [
'item' => 'required|min:6|max:10'
]);
$details = DB::connection('sqlsrv')->table('TABLENAME')->where('ITEMID', '=', $item )->get();
if (!$details) {
$validator->errors()->add('item', 'Item not found');
}
if ($validator->fails()) {
return redirect()
->back()
->withErrors($validator)
->withInput();
}
return view('itemdetails.create', compact('details'));
}
And in the view file
{{$validator->errors()->first('item')}}
Just use normal if condition will do for Controller
if($details) //True
{
//Redirect to..
}else
{
//Redirect to.. //False
}
For blade you may use #if(count($details)) if true it will display info #else {{No data}} #endif

Sort by relationship first in laravel

I have two tables: admins and log_doctor_infos. admins table has relationship hasOne with log_doctor_infos throught doctor_id like this.
In model Admin:
public function logDoctorInfo() {
return $this->hasOne(LogDoctorInfo::class, 'doctor_id', 'id');
// Model LogDoctorInfo is log_doctor_infos table
}
And in Model LogDoctorInfo:
public function doctor(){
return $this->belongsTo(Admin::class, 'doctor_id', 'id');
// Model Admin is admins table
}
I get all data form admins table and i want to sort record has relationship with log_doctor_infos to top.
Yellow record, which has relationship with log_doctor_infos and i want to sort it in top.
Edit: i use paginate in this query and i really want to get quantity of Yellow record.
Thanks for reading!
In my controller, i have custom filter and paginate. Help me.
public function index(Request $request) {
$fullname = $request->query('fullname', NULL);
$phone = $request->query('phone', NULL);
$status = $request->query('status', NULL);
$doctors = (new Doctor)->newQuery();
if ($fullname != NULL) {
$doctors = $doctors->where('fullname', 'LIKE', '%'.$fullname.'%');
}
if ($phone != NULL) {
$doctors = $doctors->where('phone', 'LIKE', '%'.$phone.'%');
}
if ($status != NULL) {
$doctors = $doctors->where('status', $status);
}
$doctors = $doctors
// ->with(array('logDoctorInfo' => function($query) {
// $query->orderBy('updated_at', 'ASC');
// }))
->latest()
->paginate()
->appends([
'fullname' => $fullname,
'phone' => $phone,
'status' => $status
]);
// dd($doctors);
return view('admin.doctors.index', compact('doctors'));
}
you can use the withCount method.
Admin::withCount('logDoctorInfo')
->orderBy('log_doctor_info_count', 'desc')
->paginate(5);
Your controller will look like this
public function index(Request $request) {
$fullname = $request->input('fullname', NULL);
$phone = $request->input('phone', NULL);
$status = $request->input('status', NULL);
$doctorQuery = Doctor::query();
if ($fullname) {
$doctorQuery->where('fullname', 'LIKE', '%'.$fullname.'%');
}
if ($phone) {
$doctorQuery->where('phone', 'LIKE', '%'.$phone.'%');
}
if ($status) {
$doctorQuery->where('status', $status);
}
$doctorQuery->withCount('logDoctorInfo')
->orderBy('log_doctor_info_count');
$doctors = $doctorQuery->paginate()
->appends([
'fullname' => $fullname,
'phone' => $phone,
'status' => $status
]);
// dd($doctors);
return view('admin.doctors.index', compact('doctors'));
}
Doctor::with('logDoctorInfo')->get()->sortByDesc('logDoctorInfo.id');

Laravel Increase SQL speed

I am trying to increase the speed of my queries in Laravel 5.7 and I have the call down to ~2.5 seconds. I am trying to figure out more ways to make it faster and if I could get some help I'd greatly appreciate it.
Thanks
How my data is structured:
Function(Controller):
public function getUserDataTmp(Request $request) {
$input = file_get_contents("php://input");
$request = json_decode($input);
if ($this->authTokenAccess($request) == true) {
$bottomWords = bottom_exterior_word::select('word','sentence','sequence','id','group_id')->where('user_id','=', $request->id)->get();
$emergencyWords = left_exterior_word::select('word','sentence','sequence','id')->where('user_id','=', $request->id)->get();
foreach($bottomWords as $tmp => $key) {
$group_id = $key->group_id;
$bottomWords->user_id = $request->id;
$bottomWords[$tmp]->words = $key->getMainWords($group_id, $request->id);
}
foreach($emergencyWords as $key => $word) {
$emergencyWords[$key]->image = imageModel::select('base64','id')->where('emergency_id','=', $word->id)->first();
}
$data = [
'data' => [
'return' => 'success',
'code' => 'VEDC001',
'response' => 'Successfully Gathered Words',
'main_categories' => $bottomWords,
'emergency_words' => $emergencyWords
]
];
return(json_encode($data));
}
}
getMainWords Function(bottom_exterior_word model):
public function getMainWords($group_id, $id)
{
// return("TEST");
$words = \App\main_word::select('id','group_id','sentence','sequence','word')->where('group_id','=', $group_id)->where('user_id','=', $id)->get();
foreach ($words as $key => $word) {
$words[$key]->image = Image::select('base64','id')->where('word_id','=', $word->id)->first();
}
return $words;
}
Start by refactoring so that you dont query inside a foreach loop
foreach($bottomWords as $tmp => $key) {
$group_id = $key->group_id;
$bottomWords->user_id = $request->id;
$bottomWords[$tmp]->words = $key->getMainWords($group_id, $request->id);
}
I would change the getMainWords function to accepts an array of group id's and use the whereIn clause:
The whereIn method verifies that a given column's value is contained
within the given array:
$users = DB::table('users')
->whereIn('id', [1, 2, 3])
->get();
Same treatment for this loop.
foreach($emergencyWords as $key => $word) {
$emergencyWords[$key]->image = imageModel::select('base64','id')->where('emergency_id','=', $word->id)->first();
}
In general minimizing the NUMBER of queries will improve response time.
Old post, would just like to update it though. Since I have first posted this, I have learned a lot more about Laravel and am a lot more experienced with it.
Here is my new function and solution:
Controller:
public function data(Request $request)
{
return response()->success(
[
'emergencywords' => EmergencyWord::with('image')->whereUserId($request->user()->id)->get(),
'categorywords' => CategoryWord::with(['image','words.image'])->whereUserId($request->user()->id)->get(),
]
);
}
Category Word Relationships:
public function image()
{
return $this->hasOne('App\Image','id','image_id');
}
public function words()
{
return $this->hasMany('App\MainWord','category_words_id','sequence');
}
Emergency Word Relationships:
public function image()
{
return $this->hasOne('App\Image','id','image_id');
}
Main Word Relationships:
public function image()
{
return $this->hasOne('App\Image','id','image_id');
}

How to return data with its data from a apivot table as a JSON response?

I have two models User and Role generated by a laratrust package. So, now I need to get all roles for all users.
Here's my code of getting such data:
$users = User::all();
foreach($users as $user) {
foreach($user->roles as $role) {
}
}
return response()->json([
'success' => true,
'users' => $users,
]);
Such a way gives the data I need.
But I guess empty foreach isn't correct way to get the data. What're the other ways of getting such data?
You can eager load roles with
$users = User::with('roles')->get();
// or
// $users = User::get();
// $users->load('roles');
return response()->json([
'success' => true,
'users' => $users,
]);
No need to use of foreach you can simply do this
$users = User::all();
if($users)
{
foreach($users as $user) {
foreach($user->roles as $role) {
}
}
}
else {
// No result
}
return response()->json([
'success' => true,
'users' => $users,
]);
I hope it helps you.

How to delete an item from array in Laravel Session?

I'm creating a cart system, this is my code to input some itens into the user Session:
public function jsonResponse($data){
return response()->json([
'success' => true,
'users' => $data
]);
}
public function post(Request $request ,User $user)
{
$request->session()->push('users', $user);
return $this->jsonResponse($request->session()->get('users'));
}
How can I delete an unique item from the users array?
Alternative 01
It's able to remove the item from the users array with the following code:
public function delete(Request $request, User $user)
{
$users = $request->session()->get('users');
foreach ($users as $key => $val) {
if($user->id == $users[$key]->id){
$array = $request->session()->pull('users', []);
unset($array[$key]);
$request->session()->put('users', $array);
return $this->jsonResponse($request->session()->get('users'));
}
}
return $this->jsonResponse($request->session()->get('users'));
}
But I was searching for a clean way... Without remove the array and put it back to the Session...
Solution 01
The following alternative has been found for a cleaner code:
public function delete(Request $request, User $user)
{
$users = $request->session()->get('users');
foreach ($users as $key => $val) {
if($user->id == $users[$key]->id){
$request->session()->forget('users.'.$key);
return $this->jsonResponse($request->session()->get('users'));
}
}
return $this->jsonResponse($request->session()->get('users'));
}
Thanks to Kyslik for remind the dot notation...
You can use forget() or pull() methods for that.
$request->session()->forget('key');
The forget method will remove a piece of data from the session
$request->session()->pull('key', 'default');
The pull method will retrieve and delete an item from the session in a single statement

Categories