Laravel 背包如何弹跳到完全匹配而不是只显示 table 中的 1 个结果

Laravel Backpack how to bounce to exact match instead of showing just 1 result in table

在我的 Laravel 5.7 应用程序中,我目前浏览到 https://example.com/admin/contact?q=john@example.com using the 等 URL,这样我就可以直接搜索联系人 table,而无需在数据表中键入 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()

我怎样才能实现我的目标?

尝试在控制器的构造函数中使用 middleware

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

看看xhr event of 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;
    }
});

这是我采用的方法(针对 Laravel 6.x 和 Backpack 4 进行了更新):

在 ContactCrudController 中:

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

/**
 * @see 
 */
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() 函数。

另见