0

In my Laravel application, I would like to check wether the value of the field uuid is present in table courses or in table contingents using validation rules. The UUID must be present in one of the two tables to proceed. Laravel requires the UUID to be present in both tables, when I'm applying the following ruleset:

$request->validate([
   'uuid' => 'exists:courses,course_id',
   'uuid' => 'exists:contingents,contingent_id
]);

Some kind of “differentiation logic” is required. It would be possible to achieve it with some if statements, but that wouldn't be a very clean way to solve the problem, I guess.

How can I tell Laravel that the UUID only needs to exist in ONE table for validation to be ok?

Thanks in advance.

2
  • 1
    I think you can achieve this by creating a custom validation rule in Laravel and then use in your request. Commented Jul 8, 2024 at 12:03
  • 1
    Yeah, this will need to be a custom rule. As written, ['uuid' => '...', 'uuid' => '...'], the 2nd exists logic will be the only one checked, since Array keys need to be unique, and if they're not, the "last" one takes precedence. The documentation is pretty good for Custom Rules though: laravel.com/docs/11.x/validation#custom-validation-rules Commented Jul 8, 2024 at 12:34

3 Answers 3

3

you can use custom validation rule first of all make new rule using php artisan make:rule ruleName. now write this function in the rule class

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;
}

after that use it in your controller like that

use App\Rules\RuleName;

// Inside your controller method
$request->validate([
   'uuid' => ['required', new RuleName],
]);
Sign up to request clarification or add additional context in comments.

Comments

2

you can create custom validation rule using 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',
    ])],
]);

2 Comments

I like the abstraction, and yours is the only answer that short-circuits if record is found in the first table (i.e. best performance). Good stuff 🙂
Great solution, thank you very much!
2
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.');
            }
        },
    ],
]);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.