В моем приложении Laravel я хотел бы проверить, присутствует ли значение поля uuid
в таблице courses
или в таблице contingents
, используя правила проверки. Чтобы продолжить, UUID должен присутствовать в одной из двух таблиц. Laravel требует, чтобы UUID присутствовал в обеих таблицах, когда я применяю следующий набор правил:
$request->validate([
'uuid' => 'exists:courses,course_id',
'uuid' => 'exists:contingents,contingent_id
]);
Требуется некая «логика дифференциации». Этого можно было бы добиться с помощью некоторых операторов if, но я думаю, что это будет не очень чистый способ решения проблемы.
Как я могу сказать Laravel, что UUID должен существовать только в ОДНОЙ таблице, чтобы проверка прошла нормально?
Заранее спасибо.
Да, это должно быть индивидуальное правило. Как написано ['uuid' => '...', 'uuid' => '...']
, проверяется только вторая логика exists
, поскольку ключи массива должны быть уникальными, а если они не уникальны, приоритет имеет «последний». Однако документация для пользовательских правил довольно хороша: laravel.com/docs/11.x/validation#custom-validation-rules
use Illuminate\Support\Facades\DB;
$request->validate([
'uuid' => [
'required',
function ($attribute, $value, $fail) {
$courseExists = DB::table('courses')->where('course_id', $value)->exists();
$contingentExists = DB::table('contingents')->where('contingent_id', $value)->exists();
if (!$courseExists && !$contingentExists) {
$fail('The :attribute must exist in either the courses or contingents table.');
}
},
],
]);
вы можете использовать собственное правило проверки
прежде всего создайте новое правило, используя php artisan make:rule ruleName.
теперь напишите эту функцию в классе правил
public function passes($attribute, $value)
{
// Check if the UUID exists in either courses or contingents table
$existsInCourses = DB::table('courses')->where('course_id', $value)->exists();
$existsInContingents = DB::table('contingents')->where('contingent_id', $value)->exists();
return $existsInCourses || $existsInContingents;
}
после этого используйте его в своем контроллере вот так
use App\Rules\RuleName;
// Inside your controller method
$request->validate([
'uuid' => ['required', new RuleName],
]);
вы можете создать собственное правило проверки, используя php artisan make:rule ticketNumberIsNotUsed
class TicketNumberIsNotUsed implements Rule
{
public function __construct(protected array $tables = [])
{}
public function passes($attribute, $value)
{
// Check if the UUID exists in either of the tables
foreach ($this->tables as $table => $field) {
if (DB::table($table)->where($field, $value)->exists()) {
return true;
}
}
return false;
}
...
use App\Rules\TicketNumberIsNotUsed;
$request->validate([
'uuid' => ['required', new TicketNumberIsNotUsed([
// list of table => field to search in order
'courses' => 'course_id',
'contingents' => 'contingent_id',
])],
]);
Мне нравится абстракция, и ваш ответ — единственный ответ, который приводит к короткому замыканию, если запись найдена в первой таблице (т. е. лучшая производительность). Хорошая штука 🙂
Отличное решение, большое спасибо!
Я думаю, вы можете добиться этого, создав собственное правило проверки в Laravel и затем используя его в своем запросе.