Sortby date md in widget

I would like to make a widget that indicates the next birthdays from a lot of people.

my approach was:
That Kirby spends all persons who are still on birthday from today on a defined period.

So we created a method like this:
<?php

class PersonPage extends Page {
    public function geburtsdatumsort() {
        return date('md', $this->geburtsdatum());
    }
}

Our output from kirby like this:

$Personen = panel()->page('intern/personen')->children()->filterBy('geburtsdatum', '!=', '')->sortBy('geburtsdatumsort', 'asc' )->filter(function($child) { echo $child->geburtsdatumsort() . '#' . $child->title()->value() . ' ' . intval($child->date('md', 'geburtsdatum')) .' > ' . intval(date('md')) . '<br />';  return intval($child->date('md', 'geburtsdatum')) > intval(date('md'));})->limit(10);

But the Page method will not work.
Do a page method not work in a widget?

I’m not sure if a page model works in the Panel, but instead of a page model you could try with a custom page method, however, I don’t even think you need. this model or method at all.

The main problem is that you’re messing something up in your collection filter code. You can’t echo anything from a custom filter but have to return a child depending on your condition. Then afterwards loop through your filtered collection and output whatever you want to output.

The Echo, was for Debugging. Sorry for the confusion.

When i set this:

$Personen = panel()->page('intern/personen')->children()->filterBy('geburtsdatum', '!=', '')->sortBy('geburtsdatumsort', 'asc' )->filter(function($child) { return intval($child->date('md', 'geburtsdatum')) > intval(date('md'));})->limit(10);

in the result the names came sorted by ABC.

But i want the list sorted by the next birthdays dependent on the date now…

when i check:

$now = date('m-d');
return $child->date('m-d', 'geburtsdatum') > date('m-d');

with with year will kirby calculate?

Or otherwise:

$now = strtotime(date('m-d'));
$Personen = panel()->page('intern/personen')->children()->filterBy('geburtsdatum', '!=', '')->sortBy('geburtsdatumsort', 'asc' )->filter(function($child) use($now) { 
return strtotime('+30 days', strtotime($child->geburtstag())) > $now;
})->limit(10);

How i can get the solution, that the output is not caluating with the year…

I’d do it like this:

$personen =  panel()->page('intern/personen')->children()->map(function($child) {
  $child->shortGeb = $child->date('md', 'geburtstag');
  return $child;
})->sortBy('shortGeb')->filter(function($child) {
  return $child->date('md', 'geburtstag') > date('md');
});

foreach($personen as $person) {
  echo $person->title(). ' hat am ' .$person->date('d.m.Y', 'geburtstag'). ' Geburstag. Happy Birthday!';
}

Top!
and again learned something!
that means with $child->variable you can create a variable on the fly …

how would look the issue for the next 4 weeks?
like this?

$personen =  panel()->page('intern/personen')->children()->map(function($child) { 
	$child->shortGeb = $child->date('md', 'geburtsdatum'); 
	$child->alter = floor((time() - strtotime($child->date('Ymd', 'geburtsdatum')))/31556926);
	$child->jetzt = strtotime('now');
	$child->enddatum = strtotime('+4 week');
	return $child; 
})->sortBy('shortGeb')->filter(function($child) { 
	return $child->date('md', 'geburtsdatum') >= date('md'); 
})->filter(function($child) { 
	return $enddatum >= $jetzt;
});

You don’t need all these extra dates:

$personen =  panel()->page('intern/personen')->map(function($child) {
  $child->shortGeb = $child->date('md', 'geburtstag');
  return $child;
})->sortBy('shortGeb')->filter(function($child) {
  // return everything between now and in four weeks
  return $child->date('md', 'geburtstag') > date('md') && $child->date('md', 'geburtstag') <= date('md',strtotime('+ 4 week'));
});