LARAVEL:当ID为非Integer时,如何引起404错误而不是50x错误

发布于 2025-02-13 23:23:47 字数 3938 浏览 0 评论 0原文

我在Laravel中创建了一个简单的CRUD,但是我有一个问题:

我正在使用Illuminate \ support \ authate \ route ::资源方法,这是我的路由/web.php:app/http/http/controllers/notecontroller.php:php

<?php

use Illuminate\Foundation\Application;
use Illuminate\Support\Facades\Route;
use Inertia\Inertia;

Route::get('/', function () {
    return Inertia::render('Welcome', [
        'canLogin' => Route::has('login'),
        'canRegister' => Route::has('register'),
        'laravelVersion' => Application::VERSION,
        'phpVersion' => PHP_VERSION,
    ]);
});

Route::get('dashboard', [App\Http\Controllers\PageController::class, 'dashboard'])
    ->middleware('auth:sanctum')
    ->name('dashboard');

Route::resource('notes', App\Http\Controllers\NoteController::class)
    ->middleware('auth:sanctum');

<?php

namespace App\Http\Controllers;

use App\Models\Note;
use Illuminate\Http\Request;
use Inertia\Inertia;

class NoteController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index(Request $request)
    {
        if ($request->q) {
            return Inertia::render('Notes/Index', [
                'notes' => Note::where('title', 'ilike', "%$request->q%")->get(),
            ]);
        }
        return Inertia::render('Notes/Index', [
            'notes' => Note::all()
        ]);
    }

    /**
     * Show the form for creating a new resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function create()
    {
        return Inertia::render('Notes/Create', [
            'note' => new Note()
        ]);
    }

    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request)
    {
        $note = Note::create($request->validate([
            'title' => 'required',
            'content' => 'required',
        ]));

        return redirect()->route('notes.show', $note)->with('success', 'Nota creada');
    }

    /**
     * Display the specified resource.
     *
     * @param  \App\Models\Note  $note
     * @return \Illuminate\Http\Response
     */
    public function show(Note $note)
    {
        return Inertia::render('Notes/Show', compact('note'));
    }

    /**
     * Show the form for editing the specified resource.
     *
     * @param  \App\Models\Note  $note
     * @return \Illuminate\Http\Response
     */
    public function edit(Note $note)
    {
        return Inertia::render('Notes/Edit', compact('note'));
    }

    /**
     * Update the specified resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \App\Models\Note  $note
     * @return \Illuminate\Http\Response
     */
    public function update(Request $request, Note $note)
    {
        $request->validate([
            'title' => 'required',
            'content' => 'required',
        ]);

        $note->update($request->all());

        return redirect()->route('notes.show', $note)->with('success', 'Nota actualizada');
    }

    /**
     * Remove the specified resource from storage.
     *
     * @param  \App\Models\Note  $note
     * @return \Illuminate\Http\Response
     */
    public function destroy(Note $note)
    {
        $note->delete();

        return redirect()->route('notes.index')->with('success', 'Nota eliminada');
    }
}

当我转到 /notes /a时,“ a”应该是我想看的注释的索引,我会收到500个错误:

SQLSTATE[22P02]: Invalid text representation: 7 ERROR: invalid input syntax for type bigint: "a"

select *从“注释”中select * where“ id” = a limit 1

此时,我的代码尚未运行。如何捕获此错误以提出404错误?

I created a simple crud in Laravel, but I'm having a problem:

I am using Illuminate\Support\Facades\Route::resource method, this is my routes/web.php:

<?php

use Illuminate\Foundation\Application;
use Illuminate\Support\Facades\Route;
use Inertia\Inertia;

Route::get('/', function () {
    return Inertia::render('Welcome', [
        'canLogin' => Route::has('login'),
        'canRegister' => Route::has('register'),
        'laravelVersion' => Application::VERSION,
        'phpVersion' => PHP_VERSION,
    ]);
});

Route::get('dashboard', [App\Http\Controllers\PageController::class, 'dashboard'])
    ->middleware('auth:sanctum')
    ->name('dashboard');

Route::resource('notes', App\Http\Controllers\NoteController::class)
    ->middleware('auth:sanctum');

app/Http/Controllers/NoteController.php:

<?php

namespace App\Http\Controllers;

use App\Models\Note;
use Illuminate\Http\Request;
use Inertia\Inertia;

class NoteController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index(Request $request)
    {
        if ($request->q) {
            return Inertia::render('Notes/Index', [
                'notes' => Note::where('title', 'ilike', "%$request->q%")->get(),
            ]);
        }
        return Inertia::render('Notes/Index', [
            'notes' => Note::all()
        ]);
    }

    /**
     * Show the form for creating a new resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function create()
    {
        return Inertia::render('Notes/Create', [
            'note' => new Note()
        ]);
    }

    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request)
    {
        $note = Note::create($request->validate([
            'title' => 'required',
            'content' => 'required',
        ]));

        return redirect()->route('notes.show', $note)->with('success', 'Nota creada');
    }

    /**
     * Display the specified resource.
     *
     * @param  \App\Models\Note  $note
     * @return \Illuminate\Http\Response
     */
    public function show(Note $note)
    {
        return Inertia::render('Notes/Show', compact('note'));
    }

    /**
     * Show the form for editing the specified resource.
     *
     * @param  \App\Models\Note  $note
     * @return \Illuminate\Http\Response
     */
    public function edit(Note $note)
    {
        return Inertia::render('Notes/Edit', compact('note'));
    }

    /**
     * Update the specified resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \App\Models\Note  $note
     * @return \Illuminate\Http\Response
     */
    public function update(Request $request, Note $note)
    {
        $request->validate([
            'title' => 'required',
            'content' => 'required',
        ]);

        $note->update($request->all());

        return redirect()->route('notes.show', $note)->with('success', 'Nota actualizada');
    }

    /**
     * Remove the specified resource from storage.
     *
     * @param  \App\Models\Note  $note
     * @return \Illuminate\Http\Response
     */
    public function destroy(Note $note)
    {
        $note->delete();

        return redirect()->route('notes.index')->with('success', 'Nota eliminada');
    }
}

When I go to /notes/a where 'a' is supposed to be the index of the note I want to see, I get a 500 error:

SQLSTATE[22P02]: Invalid text representation: 7 ERROR: invalid input syntax for type bigint: "a"

select * from "notes" where "id" = a limit 1

At this point, none of my code has yet run. How can I catch this error to raise a 404 error instead?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

执妄 2025-02-20 23:23:47

由于您使用内置资源控制器,因此将创建以下URI,并发生模型绑定。如果参数不适合ID类型,则会出错。

GET /notes/{note}
GET /notes/{note}/edit

当模型绑定发生时,我尚未找到修改请求验证的方法。如果您想自定义行为,则可以通过将show编辑函数从“路由资源声明”中删除,并编写上面列出的自定义端点。

ROUTES/web.php

Route::resource('notes', NoteController::class)->except([
    'show', 'edit'
]);

Route::get('/notes/{note}', [
    'as' => 'notes.show',
    'uses' => '\App\Http\Controllers\NoteController@show',
]);

App/http/controllers/notecontroller.php

use Illuminate\Http\Request;
...
    public function show(Request $request)
    {
        $noteId = $request->note;
        ...
    }

您可以通过将请求切换到继承formrequest的自定义请求来执行验证。

可以在此处找到更多信息:
https://laravel.com/docs/docs/9.x/validation#形式重新验证

Since you're using the built-in resource controller, the following URIs, among others, will have been created and model binding happens. If the parameter doesn't fit the id's type it will error out.

GET /notes/{note}
GET /notes/{note}/edit

I have not found a way to modify the request validation when model binding happens. If you wish to customise the behaviour, you can do so by leaving the show and edit functions out of the route resource declaration and writing custom endpoints listed above.

routes/web.php

Route::resource('notes', NoteController::class)->except([
    'show', 'edit'
]);

Route::get('/notes/{note}', [
    'as' => 'notes.show',
    'uses' => '\App\Http\Controllers\NoteController@show',
]);

app/Http/Controllers/NoteController.php

use Illuminate\Http\Request;
...
    public function show(Request $request)
    {
        $noteId = $request->note;
        ...
    }

You can perform the validation by switching Request to a custom request which inherits FormRequest.

More information can be found here:
https://laravel.com/docs/9.x/validation#form-request-validation

扮仙女 2025-02-20 23:23:47

路线模型绑定在MySQL/Mariadb上一直有效,但是不在postgres 上 。基于泰勒的“ nofollow noreferrer”> comment修复它。因此,解决方案就是这样:

Route::resource('users', UserController::class)->whereNumber('user');
Route::resource('notes', NoteController::class)->whereNumber('note');

等。

更新且优化的路由文件将看起来像这样:

<?php

use App\Http\Controllers\NoteController;
use App\Http\Controllers\PageController;
use Illuminate\Foundation\Application;
use Illuminate\Routing\Router;
use Illuminate\Support\Facades\Route;
use Inertia\Inertia;

Route::get('/', function () {
    return Inertia::render('Welcome', [
        'canLogin' => Route::has('login'),
        'canRegister' => Route::has('register'),
        'laravelVersion' => Application::VERSION,
        'phpVersion' => PHP_VERSION,
    ]);
});
Route::middleware('auth:sanctum')->group(function (Router $router) {
    $router->get('dashboard', [PageController::class, 'dashboard'])->name('dashboard');
    $router->resource('notes', NoteController::class)->whereNumber('note');
});

Route model binding has worked as you expect forever on MySQL/MariaDB but does not on Postgres. Based on Taylor's comment in the issue, they don't seem interested in fixing it. So the solution is something like this:

Route::resource('users', UserController::class)->whereNumber('user');
Route::resource('notes', NoteController::class)->whereNumber('note');

etc.

An updated and optimized route file would look like this:

<?php

use App\Http\Controllers\NoteController;
use App\Http\Controllers\PageController;
use Illuminate\Foundation\Application;
use Illuminate\Routing\Router;
use Illuminate\Support\Facades\Route;
use Inertia\Inertia;

Route::get('/', function () {
    return Inertia::render('Welcome', [
        'canLogin' => Route::has('login'),
        'canRegister' => Route::has('register'),
        'laravelVersion' => Application::VERSION,
        'phpVersion' => PHP_VERSION,
    ]);
});
Route::middleware('auth:sanctum')->group(function (Router $router) {
    $router->get('dashboard', [PageController::class, 'dashboard'])->name('dashboard');
    $router->resource('notes', NoteController::class)->whereNumber('note');
});
昔梦 2025-02-20 23:23:47

您可以在下面使用firstorfail()或FindorFail示例代码

public function find(Request $request){
    return Note::findOrFail($request->id);
}

you can use firstOrFail() or findOrFail example code below

public function find(Request $request){
    return Note::findOrFail($request->id);
}
帝王念 2025-02-20 23:23:47

如果找不到数据,则可以使用中止代码的流产(404)。

public function findNote($id)
{
    $note = Note::find($id)
    
    if($note == null)
    {
    abort(404);
    }
}

You can use abort(404) which abort your code if no data found.

public function findNote($id)
{
    $note = Note::find($id)
    
    if($note == null)
    {
    abort(404);
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文