Laravel по-русски

Русское сообщество разработки на PHP-фреймворке Laravel.

Ты не вошёл. Вход тут.

#1 01.03.2018 19:14:27

Поиск по дате в базе.

Привет, Всем.

как в поле timestamp найти определены промежуток но при этом игнорировать год.
надо выбрать сотрудников у которых день рождение было пять дней назад и пять дней вперед.

Не в сети

#2 01.03.2018 19:24:12

Re: Поиск по дате в базе.

Если по промежутку времени нужно и без сырых запросов то так:

PHP
$startDate Carbon::today()->subDays(5);
$endDate Carbon::today()->addDays(5);

if (
$startMonth === $endMonth) {
    
$users User::whereMonth('created_at'$startDate->format('m'))
        ->
whereDay('created_at''>='$startDate->format('d'))
        ->
whereDay('created_at''<='$endDate->format('d'))
        ->
get();
} else {
    
$users User::where(function($q) use($startDate) {
            
$q->whereMonth('created_at'$startDate->format('m'))
              ->
whereDay('created_at''>='$startDate->format('d'))
              ->
whereDay('created_at''<='$startDate->copy()->endOfMonth()->format('d'));
    })
    ->
orWhere(function($q) use($endDate) {
            
$q->whereMonth('created_at'$endDate->format('m'))
              ->
whereDay('created_at''>='$endDate->copy()->startOfMonth()->format('d'))
              ->
whereDay('created_at''<='$endDate->format('d'));
    })
    ->
get();
}

Т.е. тебе нужно проверить в одном ли месяце находятся эти дни или нет. Логика для каждого случая своя.

Изменено AlexeyMezenin (03.03.2018 17:05:20)

Не в сети

#3 01.03.2018 22:49:29

Re: Поиск по дате в базе.

Я поменял слегка.

        $objUserNames  = new User_name();
        $date = Carbon::today();

        $UserNames = User_name::whereMonth('birthday', '>', $date->subDays(5))
                        ->whereDay('birthday', '>', $date->subDays(5))
                        ->whereMonth('birthday', '<', $date->addDays(5))
                        ->whereDay('birthday', '<', $date->addDays(5))
                        ->get();

Но выборки нет.
а по чистому запросу в sql есть

SELECT * FROM `user_names` WHERE CONCAT( YEAR( NOW( ) ) , '-', DATE_FORMAT( `birthday` , '%m-%d %T' ) ) BETWEEN DATE_SUB( NOW( ) , INTERVAL 5 DAY ) AND DATE_ADD( NOW( ) , INTERVAL 5 DAY )

Можете подсказать где я ошибся?

Не в сети

#4 01.03.2018 23:11:20

Re: Поиск по дате в базе.

Не надо менять код. Каждый вызов subDays(5) меняет переменную.

Не в сети

#5 01.03.2018 23:14:38

Re: Поиск по дате в базе.

Не надо менять код. Каждый вызов subDays(5) меняет переменную.

если не менять то вот : Call to undefined function App\Http\Controllers\today()!

Не в сети

#6 01.03.2018 23:17:26

Re: Поиск по дате в базе.

Этот метод доступен начиная с 5.5. Если более ранняя версия, нужно заменить все четыре вызова на Carbon::today()

Не в сети

#7 01.03.2018 23:19:56

Re: Поиск по дате в базе.

Ну я так и сделал. Не работает, выборки нет

$UserNames = $objUserNames::whereMonth('birthday', '>',  Carbon::today()->subDays(5))
                    ->whereDay('birthday', '>',  Carbon::today()->subDays(5))
                    ->whereMonth('birthday', '<',  Carbon::today()->addDays(5))
                    ->whereDay('birthday', '<',  Carbon::today()->addDays(5))
                    ->get();
        dd($UserNames);

Не в сети

#8 02.03.2018 00:08:32

Re: Поиск по дате в базе.

Carbon::today()->subDays(5)

я думаю что это не правильно.  Результат этого кода будет дата на пять дней назад. Но главное что это будет полная дата. С годом, месяцем и временем.

date: 2018-02-24 00:00:00.0 UTC (+00:00)
}

Это не есть правильно. Выборку дней рождений надо сделать игнорируя год ...

Изменено macik (02.03.2018 00:08:56)

Не в сети

#9 02.03.2018 09:32:11

Re: Поиск по дате в базе.

Да, ты прав. Плюс еще логика запроса неправильная. Обновил код в моем первом сообщении, глянь пожалуйста.

Не в сети

#10 02.03.2018 10:50:24

Re: Поиск по дате в базе.

нет выборки. ;(

А как правильно прикрутить чистый SQL запрос в ларке? У меня не получается сделать запрос

SELECT * FROM `user_names` WHERE CONCAT( YEAR( NOW( ) ) , \'-\', DATE_FORMAT( `birthday` , \'%m-%d %T\' ) ) BETWEEN DATE_SUB( NOW( ) , INTERVAL 5 DAY ) AND DATE_ADD( NOW( ) , INTERVAL 5 DAY )

Это запрос работает на все 100%, но у меня не получается его правель прикрутить к своей модели ?!

Изменено macik (02.03.2018 10:50:53)

Не в сети

#11 02.03.2018 12:24:37

Re: Поиск по дате в базе.

Я пробовал похожие запросы, все работает. Проверь логику запроса и данные, "поиграй" с ними, если вообще это нужно. Если тебе по-барабану сырой запрос использовать или Eloquent, тогда делай через сырые запросы

Не в сети

#12 02.03.2018 13:06:09

Re: Поиск по дате в базе.

Я не могу понять. вроде делаю как надо

$UserNames =  DB::select('SELECT * FROM `user_names` WHERE CONCAT( YEAR( NOW( ) ) , \'-\', DATE_FORMAT( `birthday` , \'%m-%d %T\' ) ) BETWEEN DATE_SUB( NOW( ) , INTERVAL 5 DAY ) AND DATE_ADD( NOW( ) , INTERVAL 5 DAY )');

Данных нет и все. Беру из dd() выдачи SQL запрос вставляю в phpmyadmin и все находит как надо?!

Что я делаю не так?

Не в сети

#13 02.03.2018 13:13:25

Re: Поиск по дате в базе.

Получилось! Убрал экранирование и все заработало.

Не в сети

#14 02.03.2018 13:16:09

Re: Поиск по дате в базе.

$UserNames = DB::select("SELECT * FROM `user_names` WHERE CONCAT( YEAR( NOW( ) ) , '-', DATE_FORMAT( `birthday` , '%m-%d %T')) BETWEEN DATE_SUB( NOW( ) , INTERVAL 5 DAY ) AND DATE_ADD( NOW( ) , INTERVAL 5 DAY )");

Ок.Сырой запрос работает.
А как можно его переделать в запрос с использованием метода и в слите Laravel?

Не в сети

#15 03.03.2018 16:20:33

Re: Поиск по дате в базе.

@AlexeyMezenin, мне кажется ты упускаешь из виду особый случай, когда искомый интервал пересекает Новый Год. Чтобы этот кейс корректно разрулить, понадобится проверить ДВА промежутка МЕСЯЦ+ДЕНЬ через OR.

Я бы таки оставил дату рождения датой, но поправил её год на год начала искомого интервала, а потом использовал простой BETWEEN дата1 AND дата2

SELECT * 
FROM persons 
WHERE 
  (
    birthday + INTERVAL YEAR(@start) - YEAR(birthday) YEAR
  ) BETWEEN @start AND (@start + INTERVAL 10 DAY)

http://sqlfiddle.com/#!9/a83133/3
Я использовал простой "+" для коррекции даты, так код чище, по моему. Старая версия MySQL может потребовать DATE_ADD().

Сконвертировать в цепочку Eloquent помоему несложно. Но сам проверять не буду wink понадобится ->whereRaw() а значит "девственность" eloquent потеряется.

Сделано по мотивам вот этого вопроса: https://stackoverflow.com/q/18747853/272885

Изменено artoodetoo (03.03.2018 16:32:28)


There are two hard things in computer science: cache invalidation, naming things, and off-by-one errors.

Не в сети

#16 03.03.2018 17:08:03

Re: Поиск по дате в базе.

@AlexeyMezenin, мне кажется ты упускаешь из виду особый случай, когда искомый интервал пересекает Новый Год. Чтобы этот кейс корректно разрулить, понадобится проверить ДВА промежутка МЕСЯЦ+ДЕНЬ через OR.

Нет, я его тоже учитывал. От этого вообще не зависит, потому что год в запросе не учитывается вообще, это такой же случай, что и при датах в разных двух месяцах.

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

Не в сети

#17 04.03.2018 08:22:05

Re: Поиск по дате в базе.

Извини, возможно я ошибся, т.к. говорил о прошлой редакции твоего сообщения smile
Сейчас это выглядит так: я прокоментировал вчера в 17:20 моего локального времени, а последняя редакция твоего сообщение вчера в 18:05.

Текущая редакция корректно справляется с границей месяца и года, если не считать мелких ляпов вроде — это будет полный перебор таблицы с прокачкой на сторону PHP для проверки, а значит будет тормозить даже на 10000 записей
Индусятина, но работает.

Пусть топикстартер выбирает вариант себе по душе.


There are two hard things in computer science: cache invalidation, naming things, and off-by-one errors.

Не в сети

#18 04.03.2018 08:26:30

Re: Поиск по дате в базе.

Прошлая редакция тоже учитывала "Новый Год", но так логика неверная была в общем.

это будет полный перебор таблицы с прокачкой на сторону PHP для проверки. Индусятина, но работает.

Абсолютно нет. Этот код подготовит SQL запрос и вернет только нужные записи.

Не в сети

#19 04.03.2018 08:26:53

Re: Поиск по дате в базе.

Кеш гугль хранит заведомо нерабочую редакцию, видимо я изначально комментировал её.
Приношу извинения за путаницу.


There are two hard things in computer science: cache invalidation, naming things, and off-by-one errors.

Не в сети

#20 04.03.2018 08:27:57

Re: Поиск по дате в базе.

Абсолютно нет. Этот код подготовит SQL запрос и вернет только нужные записи.

я бы поспорил. есть негативный опыт с подобным запросом.


There are two hard things in computer science: cache invalidation, naming things, and off-by-one errors.

Не в сети

#21 04.03.2018 08:30:47

Re: Поиск по дате в базе.

я бы поспорил. есть негативный опыт с подобным запросом.

Там два варианта запроса - выполняется только один из них. Первый - это абсолютно стандартный a AND b AND c. Второй - это стандартный (a AND b AND c) OR (d AND e AND f)

Не в сети

#22 04.03.2018 08:36:41

Re: Поиск по дате в базе.

Окей, ты уже понял, да? Второй вариант с замыканиями потребует прокачки всех данных на PHP.


There are two hard things in computer science: cache invalidation, naming things, and off-by-one errors.

Не в сети

#23 04.03.2018 08:39:01

Re: Поиск по дате в базе.

Второй вариант с замыканиями потребует прокачки всех данных на PHP.

Нет, не потребует. Вот первый запрос, генерируемый Eloquent

select * from `users` where month(`created_at`) = '02' and day(`created_at`) >= '12' and day(`created_at`) <= '22'

Вот второй запрос (более сложный):

select * from `users` where ((month(`created_at`) = '02' and day(`created_at`) >= '27' and day(`created_at`) <= '28') or (month(`created_at`) = '03' and day(`created_at`) >= '01' and day(`created_at`) <= '09'))

Не в сети

#24 04.03.2018 09:02:32

Re: Поиск по дате в базе.

Ок, спасибо. Свой вариант мне по прежнему нравится больше. tongue


There are two hard things in computer science: cache invalidation, naming things, and off-by-one errors.

Не в сети

Подвал раздела