How to group array by user_id in Laravel 8 - php

I create the CRUD App. In this App, the user can add a contact, and include their birthday in that contact.
I have two tables in PHP MySQL: students and users. When their contact at the students' table has a birthday, the user will receive an email.
To test the email work, I'm using MailHog. It's was work.
I test that there are two users with a birthday in that contact.
One user has a notification email. Another one has two notification emails because that contact has two data that are two birthdays.
The problem is, that I want to send one notification to every user. So if one user has many contacts on that birthday, it will give the user one email notification, instead of many emails.
this is the notification in MailHog:
user john has two notifications, instead of one.
this is my code:
public function handle()
{
info('mail first');
sleep(1);
info('mail second');
$student = Student::whereMonth('birth', date('m-d'))
->whereDay('birth', date('d') )
->get();
foreach ($student as $mystudent) {
$user = User::find($mystudent->user_id);
Mail::to($user)->send(new WelcomeMail($mystudent));
}
// dd($userid);
echo "check email";
}
this code in class WelcomeMail
public function __construct($students)
{
$this->data = $students;
}
/**
* Build the message.
*
* #return $this
*/
public function build()
{
return $this->view('emails.welcome')->with('students', $this->data);
}
this is in view:
{{ $students}}
I do this modiv in mail command:
$userid = [];
foreach ($student as $mystudent) {
$user = User::find($mystudent->user_id);
array_push($userid, $user);
Mail::to($user)->send(new WelcomeMail($mystudent));
}
At this point, it's still given me the result that the user has many emails for each contact.
hopefully, you help me train logic to solve this one.
+
this the database looks like:

You can start your query from the user, so you're sure that every user is present only once.
I'm assuming you have students() relation present on the User::class model
public function handle()
{
$users = User::wherehas('students', function($studentQuery) {
$studentQuery
->whereMonth('birth', date('m-d'))
->whereDay('birth', date('d'));
})
->with('students', function($studentQuery) {
$studentQuery
->whereMonth('birth', date('m-d'))
->whereDay('birth', date('d'));
})
->get();
foreach ($users as $user) {
Mail::to($user)->send(new WelcomeMail($user->students));
}
echo "check email";
}

$student = Student::whereMonth('birth', date('m-d'))
->whereDay('birth', date('d'))
->groupBy('user_id')
->get();

Related

Extract user email address in Laravel with Artisan::call

I want to know how can I put $user->email in the following code snippet, where the email address is. Everything works well when hard coded in but not when I put $user->email where the email address is - I get error then. Please help. thanks.
public function runCommand(Request $request){
$user = User::all();
$signature = $request->input('signature');
$command = Artisan::call($signature, ['user' => 'myemail#email.co.za']);
return response($command);
}
$user = User::all();
returns a Collection
The following illustrates how you iterate over all user emails:
$users = User::all();
foreach ($users as $user) {
echo $user->email;
}
( In case you want to send an email to the currently authenticated user (?) from within a Controller, not a Command see here. )

How to delete user without posts in Laravel?

I'm working on L5.5 and I need to delete user but not his/her posts. So I basically need to assign his/her posts to another user which has to be Non-removable.
What I need:
Create a user which can't be deleted at least not from front-end even by owner of website but can be edited. (mostly is like bot for this application)
If I delete a user and that user had post(s) those post(s) remain and assign to this user (bot). It means this bot will become author of those posts.
Check for number 2 that only if user with post that happens if user has no post just delete him/her.
This is my usecontroller destroy method currently:
public function destroy($id)
{
$user = User::findOrFail($id);
Storage::delete($user->image);
$user->delete();
return redirect()->route('users.index')->with('flash_message', 'User successfully deleted');
}
Thanks.
According to your needs, you will require softDeletes in your User model and their respective tables in the database, now this solves your 1st problem where your not deleting the user from table simply adding deleted_at column.
Edit: As you are using Zizaco\Entrust\Traits\EntrustUserTrait you need to have your user model look something like this:
class User extends Model implements AuthenticatableInterface
{
use Authenticatable;
use EntrustUserTrait { restore as private restoreA; }
use SoftDeletes { restore as private restoreB; }
public function restore()
{
$this->restoreA();
$this->restoreB();
}
}
For more information about this error you need to look: https://github.com/Zizaco/entrust/issues/742
so now coming to the 2nd point, retrieving the post with deleted model can be used withTrashed() something like:
$user = User::withTrashed()->all();
$user = User::withTrashed()->where('id', 1);
$posts = $user->posts()->get();
// Or do your relational things
Even if you want to assign it to different user then you need to create a new user and apply update methods to all the relational model while deleting the user which seems a bad idea.
Edit:
So in this case you can have:
$oldUser = User::find($id);
$user = User::find($botID); // Find the bot user
$oldFoods = $oldUser->food()->get();
foreach($oldFoods as $food)
{
$food->user_id = $user->id;
$food->save();
}
Now for your 3rd point if the user has no post then you can do a small check something like this:
$user = User::find($request->id);
$posts = $user->posts()->get()->first();
if(isset($posts))
{
$user->delete();
}
else
{
$user->forceDelete();
}
Hope this justifies all your needs.
Conclusion So fnally you can have your destroy method in userController as:
public function destroy($id)
{
$user = User::findOrFail($id);
$foods = $user->food()->get();
if(isset($foods))
{
$botUser = User::where('username', '=', 'bot'); // Find the bot user
foreach($foods as $food)
{
$food->user_id = $botUser->id;
$food->save();
}
$user->delete();
}
else
{
$user->forceDelete();
}
Storage::delete($user->image);
return redirect()->route('users.index')->with('flash_message', 'User successfully deleted');
}
Edit your database with
$table->integer('user_id')->unsigned();
$table->foreign('user_id')->references('id')->on('users')
->onDelete('restrict')
->onUpdate('restrict');

how do i filter queries by records in other tables? - laravel

here is my current issue im trying to figure out
i have a laravel query for example below
$users = User::where('country', $country)
->where('age', '>=' , $lfmin)
->where('age', '<=' , $lfmax)
->get();
return $users;
and this works out all well and good. but I now have another sql table called datingblockedusers. each record in that table has the user id of the blockee and blocker. I also created a static function in datingblockeduser model that goes like this
public static function checkblock($id1, $id2)
{
//check user is blocked
$query = Datingblockeduser::where('uone', $id1)->where('utwo', $id2)->get();
if($query->count() > 0)
{
return true;
}
else
{
$query = Datingblockeduser::where('utwo', $id1)->where('uone', $id2)->get();
if($query->count() > 0)
{
return true;
}
else
{
return false;
}
}
}
How do i filter my main query such that the id of each user in that query is not in the datingblockeduser table under the fields uone or utwo (user one or user two)
EDIT: I wanted to implement a block list kind of related to a friends list. I created a new migration as such
Schema::create('blocked_user', function(Blueprint $table) {
$table->increments('id');
$table->integer('blocked_id')->unsigned()->index();
$table->integer('user_id')->unsigned()->index();
$table->foreign('blocked_id')->references('id')->on('users')->onDelete('cascade');
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
});
and in the user model i did this
// blocked
public function blocked()
{
$blocked = $this->belongsToMany('User', 'blocked_user', 'user_id', 'blocked_id');
return $blocked;
}
public function block_user($blocked_id)
{
$this->blocked()->attach($blocked_id); // add friend
$blocked = User::find($blocked_id); // find your friend, and...
$blocked->blocked()->attach($this->id); // add yourself, too
}
public function remove_blocked($blocked_id)
{
$this->blocked()->detach($blocked_id); // remove friend
$blocked = User::find($blocked_id); // find your friend, and...
$blocked->blocked()->detach($this->id); // remove yourself, too
}
now can i now use it as part of the query above or any other query from now on to make sure i only return users who are not on the blocked list?
why don't you query all blocked user_id than change main query using whereNotIn()
// get blocked user id by authenticated user. (change where condition yourself)
$blockedId = Datingblockeduser::where('blocker_id', auth()->id())->pluck('id');
$users = User::where('country', $country)
->whereNotIn('id', $blockedId)
->where('age', '>=' , $lfmin)
->where('age', '<=' , $lfmax)
->get();

Laravel - Comparing a database value with a variable

I have a basic appointment system set up, however everybody logged in can see all appointments, so what I'm trying to do is make it so users can only see their appointments. To do this I'm trying to get the logged in users Id then display all the appointments that have this user_id value (Appointments is a junction table)
I know my code is probably awful but any help is appreciated, thanks
function index()
{
$logged_user_id = Auth::user()->id;
$user = User::find($logged_user_id);
$appointments = Appointment::where('user_id', '=' $user)->get();
return view ('appointment/userappointments',['appointments' => $appointments]);
// $appointments = Appointment::all();
}
Set up your model relations and you can just do this
function index()
{
$appointments = Auth::user()->appointments;
return view ('appointment/userappointments',['appointments' => $appointments]);
}
You already have the user id, dont have to fetch User info.
function index()
{
$logged_user_id = Auth::user()->id;
$appointments = Appointment::where('user_id', '=' $logged_user_id)->get();
return view ('appointment/userappointments',['appointments' => $appointments]);
//$appointments = Appointment::all();
}

Joining and traversing models in ATK4

I have a following query,
$users = $q->add('Model_User')
->join('profile.user_id', 'id')
->join('activity.profile_id', 'profile.user_id')
->addCondition('timestamp', '>=', date('Y-m-d'))
->addCondition('profile.isActive', true);
->addCondition('activity.isDelivered', false)
->addCondition('activity.priority', '>=', 2);
Now,
I want to traverse all 'users' their 'profiles' and 'activity' associated with each profile.
Relation between User & Profile is 1:n, relation between Profile and Activity is also 1:n.
Is it possible to get something like this?
foreach($users as $user) {
foreach($user->profile as $profile) {
foreach ($profile->activity as $activity) {
//Some actions
}
}
}
Earlier I have used fetching association via ref() but this is slow when number of users are very huge and I don't want to have multiple queries on DB.
My current setup is,
$users = $q->add('Model_User')
->addCondition('timestamp', '>=', date('Y-m-d'));
foreach($users as $user) {
$profiles = $users->ref('Profile', 'user_id');
foreach(profiles as $profile) {
if($profile['isActive']) {
$activities = $profiles->ref('Activity', 'profile_id');
foreach (activities as $activity) {
if(!$activity['isDelivered'] && $activity['priority'] >= 2) {
//Some actions
}
}
}
}
}
Something like this should work:
class Model_User_ForMailing extends Model_User {
function init() {
parent::init();
// join profile, add profile fields you need later
$join_p = $this->join('profile');
$join_p->addField('email');
// join activity, add activity fields you need later
$join_a = $join_p->join('activity');
$join_a->addField('number','act_number');
$join_a->addField('description','act_descr');
// add conditions, important where you add them
$this->addCondition('timestamp', '>=', date('Y-m-d'));
$join_p->addCondition('isActive', true);
$join_a->addCondition('isDelivered', false);
$join_a->addCondition('priority', '>=', 2);
}
function actionSendMail() {
$to = $this->get('email');
$subject = 'New activity #' . $this->get('act_number');
$message = 'You have new activity with this description: ' .
$this->get('act_descr');
mail($to, $subject, $message);
}
}
class mypage extends Page {
function init() {
parent::init();
$m = $this->add('Model_User_ForMailing');
foreach ($m as $junk) {
$m->actionSendMail();
}
}
}
But this is completely untested example. I posted it here just to give you idea how to work with joins and extended models. In this case there should be only one SQL request and only one loop, because you actually need to loop by mails not by users/profiles/activities.

Categories