Как вывести ближайшие дни рождения пользователей - Битрикс

В данном примере рассмотрим написание компонента, который будет выводить ближайшие дни рождения пользователей на сайте. Изначально эта функция доступна с модулем корп. портала, мы напишем свой компонент для любой редакции 1С Битрикс: Управление сайтом.

Была задача: показывать дни рождения пользователей за ближайшие 10 дней. Окончательное решение выглядит так:

Первой идеей, которая пришла в голову была: получить пользователей по заданному фильтру, так как указано в документации

$rsUsers = CUser::GetList(($by="personal_country"), ($order="desc"), $filter); // выбираем пользователей

В массиве $filter мы можем задать поля для сортировки, среди которых есть:

PERSONAL_BIRTHDAY_1 - день рождения "с"
PERSONAL_BIRTHDAY_2 - день рождения "по"

Исходя из этих полей мы сможем к текущий дате прибавить 10 дней и вывести всех пользователей, которые попадают под это условие, но тут столкнулись с проблемой: эти поля отвечают за дату рождения вместе с годом рождения, мы же запрашиваем диапазон дат в текущем году. Соответсвенно данный метод нам не подошел.

Вторым вариантом было перебирать каждый год с выбранным диапазоном дат. Данный способ совсем не "экономичный", особенно если компонент не использует кеширование.

В комментариях был найден новый вариант использования, более "экономный":

$arFilter = array(
   "PERSONAL_BIRTHDAY_DATE" => date('m-d'), // именно так: месяц-день
   "ACTIVE" => 'Y',
);

Так мы получим пользователей, у которых день рождения в заданный день. Остается перебрать дни. Десять проходов (на каждый день) куда экономичнее, чем перебор каждого года.

Использовать можно как и в виде компонента, так и использовать включаемую область с php кодом.

Вконце статьи можно скачать архив с данным компонентом. В данном примере я приведу код компонента, параметров и шаблона вывода.

<?
if (!defined("B_PROLOG_INCLUDED") || B_PROLOG_INCLUDED!==true) die();
$arComponentParameters = array(
	"PARAMETERS" => array( //массив параметров для компонента
		"TITLE" => array( //Заголовок блока в котором будут выводиться наши данные
			"PARENT" => "BASE",
			"NAME" => GetMessage("TITLE"),
			"TYPE" => "STRING",
			"DEFAULT" => "Ближайшие дни рождения",
			"REFRESH" => "N",
			"COLS" => "40"
		),
		"DAYS_AFTER" => array( //Сколько дней просчитывать от текущей даты
			"PARENT" => "BASE",
			"NAME" => GetMessage("DAYS_AFTER"),
			"TYPE" => "STRING",
			"DEFAULT" => "10",
			"REFRESH" => "N",
			"COLS" => "15"
		),
		"FORMAT" => array( //формат вывода даты
			"PARENT" => "BASE",
			"NAME" => GetMessage("FORMAT"),
			"TYPE" => "STRING",
			"DEFAULT" => "j F",
			"REFRESH" => "N",
			"COLS" => "15"
		),
	)
);
?>

Параметр FORMAT принимает строчки в формате php даты и в формате даты Битрикса, подробнее про форматы дат в битрикс можно узнать тут.

Теперь код самого компонента:

Сначала получаем текущую дату и считаем дату окончания

if(!defined("B_PROLOG_INCLUDED") || B_PROLOG_INCLUDED!==true) die();
 
$daysAfter = $arParams["DAYS_AFTER"]; //за сколько дней показывать дни рождения

$nowDate = date($DB->DateFormatToPHP(CSite::GetDateFormat("SHORT")), time());//получаем текущую дату
$tmpDate = ConvertDateTime($nowDate, "MM-DD", "ru"); //текущая дата в нужном нам формате m-d

2. Теперь в цикле будем получать новую дату для получения пользователей

for ($i=0; $i <= $daysAfter ; $i++) { 
	$tmpDate = MakeTimeStamp($tmpDate, "MM-DD"); //переводим формат даты
	$arrAdd = array(
			"DD"			=> $i,
			"MM"			=> 0,
			"YYYY"		=> 0,
			"HH"			=> 0,
			"MI"			=> 0,
			"SS"			=> 0,
	);
	$tmpDate = AddToTimeStamp($arrAdd, $tmpDate);
	$tmpDate = date("m-d", $tmpDate); //теперь в tmpDate текущая дата +$i дней 

3. Остается только получить пользователей у которых день рождения в указанный день

$filter = Array
	(
		"PERSONAL_BIRTHDAY_DATE"=> $tmpDate
	);
	$rsUsers = CUser::GetList(($by="timestamp_x"), ($order="desc"), $filter); // выбираем пользователей

4. Так как возможны несколько дней в которые возможны дни рождения сложим пользователей в массив с ключем в виде даты

while ($arUser = $rsUsers->GetNext()){ //проверяем результаты
		$dateFormat = FormatDate($arParams["FORMAT"], MakeTimeStamp($arUser["PERSONAL_BIRTHDAY"])); // Создаем дату в формате заданном в параметрах
		$arResult[$dateFormat][$arUser["ID"]]=$arUser; //делаем полученую дату ключем массива и в этот массив записываем пользователей по их ID
	}
}//конец цикла
$this->IncludeComponentTemplate(); // выводим шаблон

На выходе мы получаем такой массив:

[24 Апреля] => Array
   (
       [4] => Array
           (
               [ID] => 4
               [~ID] => 4
               [PERSONAL_BIRTHDAY] => 24.04.1998
               ...
           )

   )

[28 Апреля] => Array
   (
       [2] => Array
           (
               [ID] => 2
               [~ID] => 2
               [PERSONAL_BIRTHDAY] => 28.04.1993
               [~PERSONAL_BIRTHDAY] => 28.04.1993
               ...
           )

   )

Осталось написать шаблон вывода у нас он имеет такой вид:

<div class="b-white col-xs-12 mb10">
	<div class="row">
		<div class="yellow col-xs-12">
			<?=$arParams["TITLE"]?>
		</div>
		<div class="col-xs-12 dr">
			<div class="row">
				<?foreach ($arResult as $formatedDate => $currentDate):?>
					<p><?=$formatedDate?></p>
					<?foreach ($currentDate as $userID => $user):?>
						<p>
							<a href="#"><?=$user["NAME"]?> <?=$user["LAST_NAME"]?></a>
						</p>
					<?endforeach;?>
				<?endforeach;?>
			</div>
		</div>
	</div>
</div>

Скачать компонент

Смотрите также

Мокапы картонных бирок (Label tag mockup)
Как вывести ближайшие дни рождения пользователей - Битрикс
Почему стоит начать использовать flexbox

Группа Вконтакте