Muhammad Usman Muhammad Usman - 3 months ago 11
PHP Question

Can't get available blood donors in laravel

I am working on a BDS (Blood Donation Society) feature for my university website. Now I'm facing a problem, with getting the available donors i.e donors which have not donated blood for last 3 months or 6 months. Following is my code:

Donor class is as follows:

protected $fillable = [
'name',
'email',
'address',
'area',
'mobile',
'blood_group',

];

public function getLastDonation()
{
return DonorRecord::all()->where('donor_id',$this->id)->pluck('donation_date');
}

public function getAvailableDonors()
{
$current = Carbon::now();
return Donor::all()->where($this->getLastDonation(),'<=',$current->addMonths(3));
}


Below is my Controller Code:

public function allDonors()
{
$donors = Donor::getAvailableDonors();
return view('BDS/allDonors',compact('donors'));
}


Now I know that I'm calling a non static method statically, but what I don't know is how to get around it.

What I'm willing to acheive is that get donors that haven't donated blood for last 3 months and send it to the view. Also in the method getLastDonation(), I'm not sure I'm using the right query.

Following is my DonorRecord Model/Class.

protected $fillable = [
'donor_id',
'donation_date',
'receiver_name',
'receiver_mobile',
'location',
'city',
'reason'
];

Answer

I am unable to comment due to low reputation, as always there is alot of ways to do this.

But assuming you have a relationship between donors and donor record I would do this.

DonorRecord:

public function scopeAvailableDonors($query)
{
  //Making an assumption here that you wanted more than three months ago, not three months in the future;
  $before = Carbon::now()->subMonths(3);
  return $query->where('donation_date','<=', $before);
}

Controller Code:

public function allDonors()
{
   $donors = DonorRecord::AvailableDonors()->get(); // Or even better DonorRecord::AvailableDonors->with('Donor')->get();
   return view('BDS/allDonors',compact('donors'));
}

Edit:

Scopes allow you to predefine common queries to save you writing them repeatedly in controllers and other areas of your code.

Using the a scope just applies constraints to your existing query so using it like above is the same as writing,

public function allDonors() 
{   
  $donors = DonorRecord::where('donation_date','<=',Carbon::now()->subMonths(3));
  return view('BDS/allDonors', compact('donors'));
}

It just allows you to move the logic out of the controller and into your model, which may not be appropriate if it is not commonly used as it will clutter your model (if you use lots of them).

Previously you were attempting to call a non static method as a static method and referencing $this, $this doesn't exist in a static context.

Equally in your controller you could have done this:

 App\Donor::with(['donorrecord' => function ($query) {
  $query->where('donation_date', '<=', Carbon::now()->subMonths(3));
 }])->get();

Which does the same but from the Donor side and not the donor record side.