Pull to refresh

Comments 16

/** Берем текущую дату, отнимаем 10 лет, прибавляем один день и получаем timestamp от необходимой даты */
$date = Carbon::now()->subYears(10)->addDay(1)->timestamp;

/** Указываем, что входящая дата в формате timestamp должна быть до нужной даты в timestamp */
$rules = [
  "bDay" => "numeric|before_timestamp:".$date,
];


Имхо это — плохо. Это чудовищно плохо.
  1. Неочевидно, потому что написано не на PHP а на каком-то собственном DSL
  2. Мне этот DSL для чего-то требуется учить
  3. В результате фреймворк начинает красть моё время, вместо помощи в его экономии


Это просто какая-то эпидемия среди разработчиков фреймворков, придумывать собственные DSL. Кривые, косые, и совершенно ненужные.

$rules = [
  'bDay' => function ($value) {
    return !empty($value) && $value <= strtotime('-10 years');
  }
];

чем хуже?
DSL нет) или я неправильно понял)

$date = Carbon::now()->subYears(10)->addDay(1)->timestamp;

эта цепочка — методы Carbon класса, не мною придуманы, а мною использованы. А массив $rules оформлен согласно документации Laravel.

Вариант, предложенный Вами, отнюдь не хуже)… Но о такой возможности я, увы, не знал)…
Именно, это свой DSL и это прекрасно. Он короче и лучше читаем. Учить вам придется много чего если вы хотите писать на фреймворке.
И ваш пример очень рафинированный. Добавьте туда еще пару тройку правил на поле. И в вашем примере как мне задать сообщение об ошибке? А мультиязычное сообщение об ошибке? А Лара имеет конвенцию привязанную к имени правила валидации.
Это отвратительно, повторю.
Вместо яркого, лаконичного и понятного кода на PHP мне зачем-то предлагается учить еще один язык, который заведомо хуже.

К лямбде, например, я в любой момент могу привязать с помощью замыкания контекст. Как это сделать со строкой «numeric|before_timestamp:»? И да, что вообще в этой строке значит "|", логическое ИЛИ? Или последовательно выполнение валидации? И как об этом догадаться?

Рано или поздно осознание ненужности левых DSL придёт к авторам фреймворков.
Это прекрасно, повторю.)
Видите мы зашли в тупик. Так что давайте не будем кидаться такими ничего незначащими кроме нашего отношения фразами и попробуем выделить суть.
Если я правильно понимаю, вы упираете на то, что минус DSL в том что его нужно учить. Претензия к пайпу туда же. И Собственно вы правы, нужно. Но для этого есть документация.
Озвученный минус про контекст я отвергаю, так как он просто не нужен для правила валидации.
> Вместо яркого, лаконичного и понятного кода на PHP
Вот не надо. Даже в какой нибудь небольшой форме есть не одно поле, на которое не одно правило валидации. И ваш код на чистом php не будет лаконичным. И будет он дублироваться темболее если форм много. И придется вам выносить эти функции куда то. и т.д.
И вы так и не сказали как мне в это дело поместить сообщение.
И в итоге сравнивая плюсы и минусы я очень рад что в Ларе сделали DSL именно на правила валидации.
давайте не будем кидаться такими ничего незначащими кроме нашего отношения фразами

А давайте без «давайте». Я давно уже вырос из возраста, когда мог повестись на такой приемчик )))

Если я правильно понимаю, вы упираете на то, что минус DSL в том что его нужно учить.

Вы неправильно понимаете. Минус собственных, свежепридуманных DSL в том, что они не нужны. Эта зараза идет со времен первого Yii, где были чудовищные array-style валидаторы и eval в дата-гридах и постепенно доползает до современных фреймворков.

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

Ой. Надо же. «Отвергаю» :)
А я вот не отвергаю ничего. Позволить себе не могу отвергать. Потому что в реальном мире почти не бывает правил валидации без контекста.
Прикиньте, например, такой кейс: админу позволительно ввести любой email в форму создания нового юзера, а аккаунт-менеджеру партнера — только email, принадлежащий его организации.
Буду счастлив увидеть это правило валидации описанным в виде «numeric|before» и что там у вас еще дальше…

Даже в какой нибудь небольшой форме есть не одно поле, на которое не одно правило валидации.

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

Прикиньте, например, такой кейс: админу позволительно ввести любой email в форму создания нового юзера, а аккаунт-менеджеру партнера — только email, принадлежащий его организации.

Для таких случаев мы не будем использовать валидацию формы. Ведь валидация формы должна отвечать лишь за проверку данных.
Мы будем проверять уровень доступа у пользователя (то ли админ, то ли аккаунт-менеджер).
Для этого мы используем Policies.
Пример:

class Gallery
{
use HandlesAuthorization;

public function add(User $user, Form $form)
{
#Тут мы уже проверим в зависимости от пользователя, может ли он добавить любой email либо же только определенные
# В зависимости от его статуса (админ или аккаунт-менеджер) я вызову определенную валидацию в которой задам что email может быть любой, а в другой валидации задам что email должен соответствовать патерну (если например задача добавлять email только с @mydomain.com) либо чтобы он существовал в таблице users.
}
}

Ну опять же, это всего лишь мое решение, каждый программист в работе с Laravel может выбрать свой путь, и лишь ему учиться и решать какой будет правильным.
Как вы добросите до формы ошибку «Вы вводите неверный email, вам разрешены только адреса из домена example.com»?

И да, вы подтвердили мою мысль — в таких случаях свои выдуманные DSL только вредят. Не так ли?
1. Сделаю редирект назад на форму с информацией о ошибке.
пример: return redirect()->back()->with('error','Вы вводите неверный email, вам разрешены только адреса из домена example.com');

2. Я предпочитаю считать, каждому свое.
При таком подходе я лучше понимаю архитектуру приложения.
Вы правда не в курсе существования библиотеки Carbon?
Хуже тем, что схожу не поймешь, что происходит. А если необходимо сразу несколько правил применить?
Вы не умеете читать код на PHP?

Я не могу иначе объяснить то, что вам непонятно

!empty($value) && $value <= strtotime('-10 years')


зато понятнее
numeric|before_timestamp:
А почему приняли решение общаться посредством timestamp, а не даты в ISO формате?
Дело в том, что на время на сервере и клиенте (клиентах) отличается. Приложению (в нашем случае браузерному) необходимо показывать время с учетом часового пояса клиента. А, используя timestamp, это сделать проще всего.
Насколько я понимаю, клиенту нужно переводить время в ISO формат, и добавлять часовой пояс.
Но как вариант вы можете принимать заголовок от клиента, например Accept-Timezone и отдавать время в нужном формате и в нужной тайм-зоне.
С этим прекрасно справляется сам php, например так:
public function getDateWithTimeZone($time, $timezone = 'UTC')
{
    return (new \DateTime($time, new \DateTimeZone(date_default_timezone_get())))
        ->setTimezone(new \DateTimeZone($timezone))
        ->format('Y-m-d H:i:s');
}

Тогда клиенту не нужно будет задумываться о переводе времени и часовых поясах. И Laravel будет спокойно валидировать даты, без изобретения велосипеда.
Как то слишком просто для статьи на хабре…
Да еще и расширение сервиса валидации не самое качественное. Хотя такой пример и дан в документации. Но сервисы лучше расширять отложено через $this->app->extend… ибо не на каждый запрос нужна валидация. А в случае расширения через фасад, сервис который за ним, будет порожден, даже если он не нужен.
Sign up to leave a comment.

Articles