Getting an empty collection in Laravel - laravel

I'm trying to create an automatic email that will send an email to a user if they have any products waiting on them to approve for use. I'm having an issue when I run my artisan command; I'm still getting empty collections instead of only products that need approval.
$users = User::all();
foreach ($users as $user) {
$outstandingProducts = Product::outstandingProducts($user);
if (empty($outstandingProducts)) continue;
dd($outstandingProducts);
}
Product model
public static function outstandingProducts(User $user)
{
return Product::where('approver_id', $user->id)
->where('status', 'Pending Approval')->get();
}

Related

Fetch users with their unread messages with Laravel Join vs Laravel Eloquent

I 'm working on a chat application. I am fetching all the users to show in the sidebar. With each user fetched I also want to show an indication of unread messages from any user. I have the messages table like this.
id | user_id | receiver_id | message | is_read
and standard users table of Laravel. I achieved it with the following join in the the controller method.
public function users_join()
{
// get logged in user
$user = Auth::id();
// left join to get all users all time
return DB::table('users')->where('users.id', '!=', $user)
->leftJoin('messages', function ($join) use ($user) {
// first evaluate where in below function
$join->on('users.id', '=', 'messages.user_id')
// filter messages sent to current user
->where('messages.receiver_id', '=', $user)
// get only those messages which are unread
->where('messages.is_read', '=', 0);
})->select('users.*', 'messages.user_id', 'messages.receiver_id', 'messages.message'
, 'messages.is_read')
// finally grouped by email to get only 10 records from users table
->orderBy('messages.created_at', 'DESC')->groupBy('email')->get();
}
Now I want to do it with the Laravel Eloquent. I can't think of any other way of doing this without using loop. Here is the code for that.
public function users_eloquent()
{
// get current user
$current_user = Auth::id();
// each through all users except current
$users = User::all()->except($current_user)->each(function ($user) use ($current_user) {
// laravel relationship
$user->messages = $user->messages()
// messages sent to me
->where('receiver_id', $current_user)
// unread message sent to me
->where('is_read', 0)
// get latest unread message
->orderBy('created_at', 'DESC')
// first latest message
->first();
});
// send back the response
return $users;
}
My User Model is like this
public function messages()
{
return $this->hasMany('App\Message');
}
and just in case, my Message Model is like this
public function user()
{
return $this->belongsTo('App\User');
}
I want to achieve it with Eloquent without using each loop. How can I do this?
I have all the users in sidebar and their unread mark. Below is the attached screenshot.
Thanks!
You don't need to loop all the users.
You can find the user except current_user by where() method on Eloquent model before it become collection.
And use with() to get the latest msg for those users:
$current_user = Auth::id();
return User::where('id', '<>', $current_user)
->with(['messages' => function($q) use ($current_user) {
$q->where('receiver_id', $current_user)
->where('is_read', 0)
->latest()
->first();
}])->get();

Trying to count record by user id

I am trying to get record by user id.This is working for login user .
But I am Trying to get details for all users .Not only.
Here is model
public function referrer()
{
return $this->belongsTo('App\User', 'referred_by');
}
public function referrals()
{
return $this->hasMany('App\User', 'referred_by');
}
Now I am Getting refferals no from this code.
$referrals=auth()->user()->referrals()->count();
BUt I am Nedd to get same result for every user listing ..
means I need to change this query.by user_id.
This case you must be use withCount() method
$users = User::withCount('referrals')->get();
foreach ($users as $user) {
dd($user->referrals_count);
}
Pass the user_id to an eloquent query
$user_id = request()->get('id'); // Your user_id here
$referrals_count = \App\User::find($user_id)->referrals()->count();
Hope this helps

Return relationship only if user is logged in?

I have a Posts and a Comments table, where each post can have multiple comments.
I want to make a query that gets all posts, and also all of the logged in user's comments.
Here is what I have so far:
$posts = Post::select('posts.*')
->with(['comments' => function($query) {
if (Auth::check()) {
$query->where('user_id', Auth::user()->id);
}
}])
->get();
And my Post.php model class looks like this:
class Post extends Model
{
public function comments()
{
return $this->hasMany('App\Comment');
}
}
The query returns the correct results when the user is logged in.
But when the user is not logged in, it returns the comments of ALL users, instead of returning nothing (because the user is logged in and therefore they have no comments).
How can I fix this?
you can do a little trick in your post model:
class Post extends Model
{
public function comments()
{
if(Auth::check()) {
return $this->hasMany('App\Comment')->where('user_id', Auth::user()->id);
}else{
return $this->hasMany('App\Comment')->where('user_id',-1);
}
}
}
and then simply :
$posts = Post::select('posts.*')->with('comments')->get()
so if user is not logged in it will return all comments with user_id of "-1" which will be nothing
There are two ways I can think of to this.
First you can only load the comments if the user is logged in:
$posts = Post::select('posts.*');
if(Auth::check()) {
$posts->with(['comments' => function($query) {
$query->where('user_id', Auth::user()->id);
}]);
}
$posts = $posts->get();
Or you could load all comments but set the user_id to null if the user isn't logged in. Since every comment should have a user_id no comments will be returned.
$posts = Post::select('posts.*')
->with(['comments' => function($query) {
$query->where('user_id', Auth::check() ? Auth::id() : null);
}])
->get();
The code in the second one looks cleaner IMO, but the first one will prevent an unnecessary query from being executed.
You can separate it, more legible and practical:
$posts = Post::all();
At your Post model create a function that will return all user's comments:
public function userComments()
{
return $this->comments->where('user_id', Auth::user()->id);
}
And i guess at your view you have a foreach to iterate all posts, inside your foreach you load post's comments, so you can do that:
#foreach($posts as $post)
$post->userComments()
#endforeach

laravel 5.2 if else to query database

stuck on a form that allows the user to enter a value into a choice of two fields. I can query the database using one field but want to add more range to database queries. With the following code below when i try to access the page to query it just shows me a white screen.
public function index()
{
$data = $request->all();
if(!empty($data['pstoreNum']))
{
$pstoreNum = $data['pstoreNum'];
$result = DB::table('perfumes')->where('StoreNumber','=',$pstoreNum)
->get();
return view('perfumes',compact('result'));
}
else if(!empty($data['pweekNum']))
{
$pweekNum = $data['pweekNum'];
$result = DB::table('perfumes')->where('WeekNumber','=',$pweekNum)
->get();
return view('perfumes',compact('result'));
}
}
My routes file simple calls the index function. Any help would be appreciated.
You can add query functions within your query like so
public function index(Request $request)
{
$data = $request->all();
$result = \DB::table('perfumes')->where(function($query) use ($data) {
if(!empty($data['pstoreNum'])) {
$query->where('StoreNumber', '=', $data['pstoreNum']);
}
if(!empty($data['pweekNum'])) {
$query->where('WeekNumber', '=', $data['pweekNum']);
}
})->get();
return view('perfumes',compact('result'));
}
You can then use the one query and add multiple wheres on various conditions.
https://laravel.com/docs/5.2/queries#advanced-where-clauses

Simple search in laravel

I'm trying to build a search system in my small laravel project but considering that I'm still a beginner I can't figure how this should work..
Basically, I have a controller which returns an index page with all the users. In the index page I have multiple select tags where you can choose an option and filter the users.
Here's my index method:
public function index(){
$users = User::all();
$service = Service::all();
return view('browse.index', compact('users','service'));
}
Now, the thing is, I have a relationship built between users and services. So, each user hasMany services. With that in mind, when I'm building the search function I want to be able to access the user service.
Something like this:
$category = $request->input('category');
foreach ($users as $user) {
$serviceFound = $user->service->where('category', 'LIKE', '%' . $category . '%');
}
Of course this doesn't work because considering that I have a get route for my index, I don't know how to set up the form so I can use the $request.. I hope this is clear...Maybe you guys can help me with setting up the form/route and clear my mind on how should I do this...
Build a simple form using GET as well. Simple Example
<form action="" method="GET">
<input type="text" name="category" required/>
<button type="submit">Submit</button>
</form>
In your controller you do
public function index(Request $request){
$category = $request->input('category');
//now get all user and services in one go without looping using eager loading
//In your foreach() loop, if you have 1000 users you will make 1000 queries
$users = User::with('services', function($query) use ($category) {
$query->where('category', 'LIKE', '%' . $category . '%');
})->get();
return view('browse.index', compact('users'));
}
Eager loading will work only if you have your relationships setup properly.
Keep your route unchanged the way it is now.
In your controller:
public function index(\Request $request)
{
return $request::all();
}
In your routes:
Route::get('searchtest', 'SearchController#index');
Example url:
http://localhost:8000/searchtest?search=search_string&category=socks
And finally, the output
{
"search": "search_string",
"category": "socks"
}
You can also do $category = $request::get('category'); to get only the category as a string.

Resources