Хочу спросить, говнокод я написал или нет? Подтверждение аккаунта по email и ключу. Ключ в таблице в поле 'act_key'. В поле 'send_date' дата отправки юзеру ссылки активации. На сайтах обучалках дата просрочки ссылки везде проверяется лишь вычитанием текущей даты и даты отправки ссылки подтверждения. А, если месяцы разные, а если год разный (30 декабря и 1 января), а если год високосный и месяц февраль. Поэтому я приготовил это: PHP: public function activate($user_email, $key, Request $request) { $user = Activate_users::where([ ['email', $user_email], ['act_key', $key] ])->select('email', 'activate', 'act_key', 'send_date')->get(); // if act_key exists in database and act_key from database matches key from activation link if(isset($user[0]->act_key) && $user[0]->act_key == $key) { // send_date format: Y-m-d $send_date = explode('-', $user[0]->send_date); $send_year = $send_date[0]; $send_month = $send_date[1]; $send_day = $send_date[2]; $today_date = explode('-', date('Y-m-d')); $today_year = $today_date[0]; $today_month = $today_date[1]; $today_day = $today_date[2]; $special_year = array( '0' => '2016', '1' => '2020', '2' => '2024', '3' => '2028', '4' => '2032', '5' => '2036', ); $days_in_month = array( '01' => 31, '02' => 28, '03' => 31, '04' => 30, '05' => 31, '06' => 30, '07' => 31, '08' => 31, '09' => 30, '10' => 31, '11' => 30, '12' => 31, ); // count how many days passed from the day when we sent to user activation link $days_have_passed = $today_day - $send_day; // if years match and months match if($today_year == $send_year && $today_month == $send_month) { // if only 3 or less days passed from sending activation link if(preg_match('/^[0-3]$/', $days_have_passed)) { // activate user } // if $days_have_passed bigger than 3 throw new Exception('Activation_error'); } // if years match but months are different elseif($today_year == $send_year && $today_month - 1 == $send_month) { /* * Event * * Send date: The 3d of October * User clicked on the link on 3d of November * * $send_month_has_days = 31; * $days_to_today_month = 28; * $days_have_passed = 28 + 3 = 31; */ $send_month_has_days = $days_in_month[$send_month]; $days_to_today_month = $send_month_has_days - $send_day; $days_have_passed = $days_to_today_month + $today_day; // if only 3 or less days passed from sending activation link if(preg_match('/^[0-3]$/', $days_have_passed)) { // activate user } // if $days_have_passed bigger than 3 throw new Exception('Activation_error'); } // if today is 2018 and send_year is 2017 elseif($today_year - 1 == $send_year) { // if it was leap-year when we sent to user activation link (28 days in February) for($i=0; $i<6; $i++) { if($send_year == $special_year[$i]) { $days_in_month['02'] = 29; } } /* * Event * * Send date: The 29th of December 2017 * User clicked on the link on 3d of January 2018 * * $send_month_has_days = 31; * $days_to_today_month = 2; * $days_have_passed = 2 + 3 = 5; */ $send_month_has_days = $days_in_month[$send_month]; $days_to_today_month = $send_month_has_days - $send_day; $days_have_passed = $days_to_today_month + $today_day; // if only 3 or less days passed from sending activation link if(preg_match('/^[0-3]$/', $days_have_passed)) { // activate user } // if $days_have_passed bigger than 3 throw new Exception('Activation_error'); } } }
Есть такое блестящее изобретение человечества, как UNIX TIMESTAMP - вычитаете из секунд секунды, с секундами сравниваете - 3 строчки. А другие умные люди сделали класс DateTime как часть стандартной библиотеки PHP, опять же, $date1->diff($date2) - и там уже все года, века, тысячелетия будут учтены. И не нужно таких портянок писать.
По моему это все излишнее, достаточно будет отправить ссылку с ключем, а юзер хочет не хочет переходит по ней)
Это инъекция объекта класса Request. Остался, как рудимент, забыл удалить. Так как это laravel, то через request можно работать с сессией, с данными POST и GET. На большинстве сайтов ссылка имеет срок, в течении которого действительна и нынешний заказчик сайта наверняка захочет, чтобы такое было и у него на сайте. А у меня будет как раз готовое решение. В случае, если не захочет, то ссылку без срока активации будет сделать очень просто, удалив пару строчек.
Спасибо. Убрал портянки. Получилось вот так, коротко, не страшно и работает как надо: PHP: public function activate($user_email, $key) { $user = Activate_users::where([ ['email', $user_email], ['act_key', $key] ])->select('email', 'activate', 'act_key', 'send_date')->get(); // if act_key exists in database and act_key from database matches key from activation link if(isset($user[0]->act_key) && $user[0]->act_key == $key) { // send_date format: Y-m-d $send_date = explode('-', $user[0]->send_date); $send_year = $send_date[0]; $send_month = $send_date[1]; $send_day = $send_date[2]; $today_date = explode('-', date('Y-m-d')); $today_year = $today_date[0]; $today_month = $today_date[1]; $today_day = $today_date[2]; //> count how many days passed from the day when we sent to user activation link $today_unix_date = mktime(0, 0, 0, $today_month, $today_day, $today_year); $send_unix_date = mktime(0, 0, 0, $send_month, $send_day, $send_year); $diff = $today_unix_date - $send_unix_date; $days_have_passed = $diff / 60 / 60 / 24; // seconds/minutes/hours/days //< // if it has passed from 0 to 3 days from the date of sending the message if (preg_match('/^[0-3]$/', $days_have_passed)) { // activate user $status = 'success'; } // if it has passed more than 3 days else { $status = 'error'; } $error = 'Ссылка не действительна. Пройдите регистрацию повторно'; $success = 'Аккаунт подтвержден'; dump($$status); // show response /*return view('мой шаблон представления', [ 'status' => $$status );*/ } }
Можно ещё короче. Почитайте https://secure.php.net/strtotime и https://secure.php.net/manual/ru/datetime.createfromformat.php
Сделал в три строки: PHP: // send_date format: Y-m-d //> count how many days passed from the day when we sent to user activation link $today_unix_date = new DateTime("now"); $send_unix_date = DateTime::createFromFormat('Y-m-d', $user[0]->send_date); $days_have_passed = $today_unix_date->diff($send_unix_date)->format('%a'); //< Ну, или в одну: PHP: $days_have_passed = (new DateTime("now"))->diff(DateTime::createFromFormat('Y-m-d', $user[0]->send_date))->format('%a');