Laravel Backpack, как вернуться к точному совпадению, а не показывать только 1 результат в таблице

В моем приложении Laravel 5.7 я в настоящее время просматриваю URL-адреса, такие как https://example.com/admin/[email protected], используя параметр "q", чтобы Я могу выполнять поиск в таблице «Контакты» напрямую, не вводя текст в поле поиска DataTables ajax.

Это работает хорошо, за исключением того, что я бы предпочел, чтобы он сразу переходил на страницу редактирования (для точного совпадения только 1 результата).

В моем ContactCrudController setup() у меня есть:

$q = $this->request->query->get('q');
if ($q) {// if there is an exact email match, redirect to the Edit page of that Contact.
    $matchingContact = \App\Models\Contact::where('emailAddress', $q)->first();
    if ($matchingContact) {
        return redirect(url('/admin/contact/' . $matchingContact->id . '/edit'));
    }
}

Но это не работает, потому что setup() не ожидает return redirect().

Как я могу достичь своей цели?


person Ryan    schedule 11.12.2018    source источник


Ответы (3)


Попробуйте использовать промежуточное ПО в конструкторе вашего контроллера:

class ContactCrudController extends Controller
{
    /**
     * Instantiate a new controller instance.
     *
     * @return void
     */
    public function __construct()
    {
        parent::__construct();
        $this->middleware(function ($request, $next) {
            if ($contact = \App\Models\Contact::where('emailAddress', $request->query->get('q'))->first()) {
                 return redirect(url('/admin/contact/' . $contact->id . '/edit'));
            }

            return $next($request);
        });
    }
}
person DigitalDrifter    schedule 11.12.2018
comment
Благодарю вас! Это почти сработало, а потом я добавил parent::__construct();, и это сработало. - person Ryan; 11.12.2018

Взгляните на xhr событие datatables.net. Вы можете использовать его для перехвата ответа от сервера и перенаправления на его основе.

Я мог бы представить что-то подобное на стороне сервера:

function datatableData()
{
    $q = $this->request->query->get('q');

    $contacts = \App\Models\Contact::query()
        ->when($q, function ($query, $q) { // apply filter only if present
             $query->where('emailAddress', $q);
        })->get();

    if ($contacts->count() === 1) {
        $id = $contacts->first()->id;
        return response()->json(['redirect' => url("/admin/contact/$id/edit")]);
    }

    return response()->json($contacts); // or whatever you return normally
}

И следующее на стороне клиента:

var dt = $('#example').dataTable(...yourConfig...);

dt.on('xhr.dt', function (e, settings, json, xhr) {
    if (json.redirect) {
        window.location.href = json.redirect;
    }
});
person Namoshek    schedule 11.12.2018
comment
Спасибо за Ваш ответ. Я пошел с другим подходом, так как он был более привычным. - person Ryan; 11.12.2018

Вот подход, который я использовал (обновлен для Laravel 6.x и Backpack 4):

В ContactCrudController:

public function __construct() {
    parent::__construct();
    $this->redirectIfExactMatch();
}

/**
 * @see https://stackoverflow.com/a/53771897/470749
 */
public function redirectIfExactMatch() {
    $this->middleware(function ($request, $next) {
        $q = $request->input(self::Q);
        if ($q) {
            $contact = \App\Models\Contact::where('emailAddress', $q)->first();
            if ($contact) {// if there is an exact email match, redirect to the Edit page of that Contact.
                return redirect($contact->getContactEditUrl());
            }
        }
        return $next($request);
    })->only('index'); //https://laravel.com/docs/6.x/controllers#controller-middleware
}

Я использую ->only('index') для применения промежуточного программного обеспечения только к функции index().

См. также https://stackoverflow.com/a/53471954/470749.

person Ryan    schedule 14.12.2018