Get ID from while looping - laravel

I want to make an employee leave application, where when an employee submits leave request, his boss will immediately get a notification in the email
My table in database like this
id | name | email | person_in_charge |
1 Michael michael.com 2
2 Johan johan.com 4
3 Lorem lorem.com 2
4 Ipsum ipsum.com 5
5 Dolor dolor.com
I want to, when user id 1 sends an email, then the one who gets the email is user id 2, 4 and 5, because user id 2 is the boss of user id 1, and user id 4 is the boss of user id 2, and user id 5 is boss all of them.
I've doing using while looping, but the result is the one who gets the email is user id 4 and 5, user id 2 not get the email
Here's the code
$currentuserid = '1';
$show= Users::where('id',$currentuserid)->first();
if($show->pic_for!=null)
{
$pic_for = $tampil->pic_for;
while($pic_for!=null)
{
$query = Users::where('id',$pic_for)->first();
if($query->pic_for==null)
{
break;
}else
{
$pic[]=$query->pic_for;
$pic_for = $query->pic_for;
}
}
dd($pic);
Do you know where I missed ?
Thank you

You simply do not save the first reference, when you enter the loop. The first $pic_for is never added to the array $pic.
EDIT/BTW: This code can basically DDoS your own database with that loop. Just an idea, but instead of looping through single instances, you could create a HABTM relation between them. So you could query like $user->usersInCharge() and iterate over this collection.

Related

BelongsToMany relation with specific condition

I've the following tables:
users (list of users) :
id | type
5 | client
10 | expert
clients (assigning many users to many groups):
uid | gid
5 | 1
client_groups (groups defined by experts):
id | title | expert_uid
1 | diabetic | 10
Every expert can define a group of clients and put any of his clients in one of them.
A client may belong to many experts.
Now what I want is to get the group of the current user which is defined by specific expert.
I've tried the following relation:
class User{
public function client_groups()
{
return $this->belongsToMany(\App\Models\client_group::class,"clients","uid","gid");
}
}
User::with("client_groups")->
whereIn("id",$client_ids)->
orderby($orderBy,$order)->
get();
But as you may guess it will return all client_groups for the current client But I want the ones that has been defined by the current expert and not all of them.
Thanks in Advance

Laravel - Add additional where constraints from Eloquent Model belongsToMany relationship

I am new to Laravel (using v7) so I apologise if I am doing this incorrectly.
I have a custom subscription setup for my users.
I have my users table
id
first_name
last_name
1
John
Doe
2
Jane
Doe
I have my subscriptions table
id
name
1
Basic
2
Bronze
3
Silver
4 ​
Gold
5 ​
Platinum
And a subscription_user pivot table
id
user_id
subscription_id
created_at
expired_at
1
1
1
2021-02-01 23:22:12
2021-03-21 08:22:12
2
1
5
2021-03-21 08:22:12
2021-04-04 09:03:21
2
1
3
2021-04-04 09:03:21
2
2
1
2021-01-01 01:00:00
2021-01-05 05:30:00
2
2
2
2021-01-05 05:30:00
2021-01-06 08:34:10
So as per the above entries, John Doe subscribed on the Basic subscription, then upgraded to the Platinum and then finally downgrading to the Silver. Which is his current subscription.
I have the following methods (within User.php) for first getting a list of the users subscriptions
public function subscriptions()
{
return $this->belongsToMany('App\Subscription')
->orderby('pivot_created_at', 'desc')
->withPivot('created_at', 'expired_at')
->withTimestamps();
}
And then to get the current subscription
public function subscription()
{
return $this->subscriptions->first();
}
However there could be instances where by a user has all subscriptions expired, therefore they have no current subscription in place. i.e in the above records Jane Doe who subscribed to 2 plans but both have expired.
If i call $user->subscription() on Jane Doe it still returns the latest expired entry.
I have tried added where() clauses into my subscription method but it has no effect:
public function subscription()
{
return $this->subscriptions->where('expired_at', NULL)->first();
}
Is there a better way to do what I am trying to achieve? I need a method to fetch all the users subscriptions, whether they are active or expired. (which I have - is this the best way?)
But then also fetch the current subscription which should always not have an expired_at.
It seems I cannot add any further conditions within mt subscription method.
You need to use the query builder for the subscription method using subscriptions() instead of the collection subscriptions
public function subscription()
{
return $this->subscriptions()->whereNull('expired_at')->first();
}
calling $this->subscriptions is equivalent to $this->subscriptions = $this->subscriptions()->get(). where $this->subscriptions returns a collection.
$this->subscriptions(), using the method, return a query builder.
PS: it did not trigger an error calling first() because a Collection has a method called first() too.

Laravel 8 - count clicks but user can't spam the function

In my website I track clicks on a specific link and save the count on database with this function:
public function redirect($url)
{
$data = Class::where('url', $url)->first('clicks');
$cnt = $data->clicks;
$cnt++;
$sql = Class::where('url', $url)->update([
'clicks' => $cnt,
]);
if (!$sql) {
abort(500);
}
return redirect('https://website.com/'.$url);
}
the problem is if someone spam the link , the count goes up. I want stop count if user clicked on link 5mins ago.
he will redirected to the link but count doesn't go up.
I'm new so it's so good if you explain it with details. Thanks
I would create a new table, lets call it link_clicks. You will need 3 columns, one to identify the person, one to get the time and one to identify the link (I dont exactly know how you store the links you want to observe).
So more or less you will have the following table:
link_clicks
user_id
link_id
created_at
If the users are always logged in, I would store the user_id, if they are not logged in, I would store the IP-address. So instead of user_id make a column called ip or ip-address.
Afterwards you can easily get the last click and its time.
--Example
Your new table contains following entry:
user_id = 1, link_id = 1 and created_at = 2021-04-21 19:00:00
Now in your controller you get the current date_time date("Y-m-d H:i:s") and the user id like that: auth()->id(). You can also define your time treshold in minutes e.g max_dif = 5.
Afterwards you can query the table for all clicks for the user. You can either make the time comparision in your where() statement or you can make some comaprison in your php code to check if the time treshhold is reached.

Laravel : How to show a multiple rows from DB in one row in view blade

In my Laravel project, I have a multiple rows in my DB table, similar to each other in every thing except ID, other column called stage
Stages table
ID
name
1
first
2
second
3
third
subjects Table
ID
name
stage_id
1
English
1
2
English
2
3
English
3
I need to show em in a blade like this
#
name
stage
1
English
first, two, three, etc
I already have the relations in my modals, and I am already showing them in my blade by loop, but I just want to group the rows by name and show the different stages
I hope that I explained the case well, I am not very good at explaining
Updates : before editing I wrote a dummy data now I hope I explained the issue in more details
The project idea is that you can create more than faculty
and every faculty has Stages and sections and every section has specialties and every specialty has subjects
now about subjects and stages
user can create subject like English and make it available to the first stage and 2nd and third ..etc ( the available stages in this faculty)
The Stages belongs to Faculty
The Subjects belongs to Stage
so the relations are
Subject Model
public function stage()
{
return $this->belongsTo(Stage::class);
}
Stage Model
public function subjects()
{
return $this->hasMany(Subject::class);
}
As you have "English" Multiple Times, you should have a subject Table :
Stages table
ID
name
1
first
2
second
3
third
Subject table
ID
name
1
English
stage_subject Table :
ID
stage_id
subject_id
1
1
1
1
2
1
1
3
1
Subject Model
public function stage()
{
return $this->belongsToMany(Stage::class);
}
Stage Model
public function subjects()
{
return $this->belongsToMany(Subject::class);
}
Then in your foreach:
#php($subjects = Subject::with('stages')->get())
#foreach($subjects as $subject)
{{ $subject->id }} | {{$subject->name}} | {{$subject->stages->pluck('name')->implode(', ')}}
#endforeach
If you don't / can't do a pivot table, then you can use collection :
#php($subjects = Subject::with('stages')->get())
#foreach($subjects->groupBy('name') as $name => $subjects)
{{ $subjects->first()->id }} | {{$name}} | {{$subjects->pluck('stage.name')->implode(', ')}}
#endforeach

Laravel - retrieve direct/indirect pivot table subscribers

I am having a hard time figuring this out in laravel; for a subscriber relationship we have 2 pivot tables:
A subscriber can subscribe to a question:
question_subscriber
id question_id subscriber_id
1 2 3
2 2 4
3 3 1
4 3 2
A subscriber can subscribe to a user:
user_subscriber
id user_id subscriber_id
1 1 6
2 1 7
3 2 1
Normal questions table with question owner:
questions
id question user_id
1 abc? 1
2 xyz? 1
3 123? 2
The pivot relationships are setup correctly in their models, and I can pull out with a foreach, subscribers for a question, $question->subscribersQuestion as $subscriber, or subscribers for a user, $user->subscribersUser as $subscriber:
But how can we pull out all subscribers that belong to a user (directly or indirectly (through a question they own))?
For example, these should be all retrieved subscribers for user 1:
6 // subscribed to directly
7 // subscribed to directly
3 // subscribed to through question
4 // subscribed to through question
Any idea on the most efficient way to do this in Laravel?
This will be the easiest way:
// assuming this setup:
User hasMany Question
User belongsToMany User (subscribers - direct)
Question belongsToMany User (subscribers - indirect)
// we don't need this, since we pass it by reference to the closure,
// but for clarity let's initialize this variable:
$indirectSubscribers = null;
$user = User::with(['questions.subscribers' => function ($q) use (&$indirectSubscribers) {
// get all indirect subscribers (cost of additional query)
$indirectSubscribers = $q->get()->unique();
}])->find($userId);
// merge with directs subscribers
$allSubscribers = $user->subscribers->merge($indirectSubscribers);

Resources