0

I am trying to send email three days before the expired date, but I'm not sure how to?

Logic

  1. Retrieve all subscribers that are three days left to expire
  2. Send email to their users

Code

Table I need to check timestamps named subscribes.

$subscribes = Subscribe::all();

This table has a column named expires_at which I need to check this for finding 3 days left.

And my mailing

Mail::to($user->email)->send(new SubscribeExpire($user, $subscribe));

I'm confused with this Carbon calculation thing, anyone can help with that?

Update

based on answer below now I have this:

$subscribes = Subscribe::where('expires_at', Carbon::now()->subDays(3))->get();
        $user = [];
        $package = [];
        foreach($subscribes as $subscribe){
            $user = User::where('email', $subscribe->email);
            $package = Package::where('id', $subscribe->package_id);
        }

        Mail::to($user->email)->send(new SubscribeExpire($user, $package));

but when I run the command it get this error

ErrorException  : Trying to get property 'email' of non-object
mafortis
  • 6,750
  • 23
  • 130
  • 288
  • $user = User::where('email', $subscribe->email) should be $user = User::where('email', $subscribe->email)->first(); – Nick Surmanidze Dec 03 '18 at 16:23
  • The same goes to Package. – Nick Surmanidze Dec 03 '18 at 16:23
  • then what if i have several subscribes for different users? it only gets first one right? – mafortis Dec 03 '18 at 16:24
  • In such case use "->get()" instead of "->first()" and use foreach loop to iterate through these users and send an email to each of these users. – Nick Surmanidze Dec 03 '18 at 16:30
  • @NickSurmanidze I used get, also moved my Mail inside loop but not sending email, the `dd` of `user` returns `[]` only – mafortis Dec 03 '18 at 16:32
  • 1
    I just added it as an answer. It was just easier to put a code snippet there. Take a look if that will work for you. – Nick Surmanidze Dec 03 '18 at 16:37
  • @mafortis, you really should have already established a relationship between the Subcribe model and the User model. While you may have gotten something that works now, it's not a clean approach and will be frowned upon by other Laravel developers. I highly recommend you read through the entirety of the Laravel docs so you understand the ORM and the Laravel workflow. – Devon Bessemer Dec 03 '18 at 17:12
  • @Devon thanks for suggestion, i have relation between them i just saved email here instead of user_id. – mafortis Dec 03 '18 at 17:23

2 Answers2

1

Use subDays() method as shown below:

$subscribes = Subscribe::where('expires_at', Carbon::now()->subDays(3))->get();
Muhammad Saqlain
  • 2,112
  • 4
  • 33
  • 48
  • `Q1` do I need to loop this in order to get users for their emails? `Q2` if i loop it the will it send email to all those users of just first one it finds? how should i define array of results in my `Mail::...`? – mafortis Dec 03 '18 at 16:13
  • updated my question. – mafortis Dec 03 '18 at 16:19
  • If expires_at is a timestamp, this won't work so well as you're looking at an exact comparison. – Devon Bessemer Dec 03 '18 at 16:20
  • yes is timestamp, what yu suggest now? – mafortis Dec 03 '18 at 16:21
  • 1
    @mafortis, you really shouldn't add additional questions once you have an answer. Read the "How to Ask" section under Help. Don't ask multiple questions in one, SO is a Q&A site, not a discussion forum where the answers can be broad and discussed. – Devon Bessemer Dec 03 '18 at 16:22
  • @Devon is not multiple is same question not solved yet. if you see my logic part i mentioned i need to get users to send email to. – mafortis Dec 03 '18 at 16:23
  • Move Mail::to($user->email)->send(new SubscribeExpire($user, $package)); into foreach loop – Muhammad Saqlain Dec 03 '18 at 16:27
  • @MuhammadSaqlain that doesn't return error neither sending email, i tried to dump `user` it just return `[]` – mafortis Dec 03 '18 at 16:30
1
  // here you get subscribes  
  // if you are going to send three days before the expiry date, this means we need to check if expires_at is in three days so probably need to add days. Or maybe even check if time left before expiration is more than three days and less than one day and run it once per day?
  $subscribes = Subscribe::whereDate('expires_at', Carbon::now()->addDays(3))->get();
    $user = [];
    $package = [];
    foreach($subscribes as $subscribe){
        // you probably have only one user with this email
        $user = User::where('email', $subscribe->email)->first();
        // you probably have one associated package
        $package = Package::where('id', $subscribe->package_id)->first();
    }
    // check if user and package are found
    if(is_object($user) && is_object($package)){
      Mail::to($user->email)->send(new SubscribeExpire($user, $package));
    }
Nick Surmanidze
  • 1,671
  • 1
  • 11
  • 20