Help us understand the problem. What is going on with this article?

Laravel のモデル結合ルートパラメータに文字列を渡すと SQL エラーになるのを直す

背景

Laravel でモデル結合ルートパラメータに整数を期待すると、文字列を渡したときにエラーになる。
例として hoges テーブルの1レコードを表示する画面を考えてみます。

Schema::create('hoges', function ($table) {
    $table->increments('id'); // 主キーが連番の整数
    ...
});
Route::resource('hoges', 'HogeController');
public function show(Hoge $hoge) // モデル結合している
{
    ...
}

GET /hoges/str にアクセスすると次の SQL エラーになる。

SQLSTATE[22P02]: Invalid text representation: 7 ERROR: invalid input syntax for integer: "str" (SQL: select * from "hoges" where "id" = str limit 1)

さらに GET /hoges/2147483648 にアクセスすると次の SQL エラーになる。

SQLSTATE[22003]: Numeric value out of range: 7 ERROR: value "2147483648" is out of range for type integer (SQL: select * from "hoges" where "id" = 2147483648 limit 1)

解決策

公式な対応

これについて公式のリポジトリに Issue があります。

PR も1件ありますが、"this changes a contract" とのことでマージぜすクローズされています。

PR のクローズを最後に半年以上動きがない状態が続いています。

暫定的な対応

モデル結合ルートはロジックをカスタマイズできるので、ロジックにバリデーションを追加しました。
トレイトとして実装して、必要なモデルで使えるようにしています。

app/Traits/PrimaryKeyRangeRouteBinding.php
<?php

namespace App\Traits;

trait PrimaryKeyRangeRouteBinding
{
    public function resolveRouteBinding($value)
    {
        if (validator(['value' => $value], ['value' => 'integer|between:1,2147483647']])->fails()) {
            return null;
        }

        return parent::resolveRouteBinding($value);
    }
}

使い方

モデルに use して使えます。

<?php

namespace App;

use App\Traits\PrimaryKeyRangeRouteBinding;
use Illuminate\Database\Eloquent\Model;

class Hoge extends Model
{
    use PrimaryKeyRangeRouteBinding; // これ
    ...
}

これにより GET /hoges/strGET /hoges/2147483648 は、一致するレコードやルートがないときと同様に 404 Not Found を返します。

おしまい

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした