Laravel - Eloquent는 비교 전에 쿼리 매개변수를 정수로 변환합니다.

StackOverflow https://stackoverflow.com//questions/25008004

  •  20-12-2019
  •  | 
  •  

문제

기본 키를 기반으로 테이블에서 단일 행을 반환하려고 합니다.

    $product = Product::where('id', '=', $idOrSKU)
        ->orWhere('sku', '=', $idOrSKU)
        ->take(1)->get();

몇 가지 이유 $idorSKU 으로 변환되고 있습니다. (int) 비교가 일어나기 전에.예를 들어, $isOrSKU = "9dfghfd", 이면 ID=9인 행이 반환됩니다.왜 이런거야?아무것도 반환하지 않아야 합니다!누군가 이것을 설명할 수 있나요?

관련 테이블 구성표는 다음과 같습니다.

| id                         | int(10) unsigned | NO   | PRI | NULL      
| name                       | varchar(255)     | NO   |     | NULL                
| sku                        | varchar(255)     | NO   |     | NULL 
도움이 되었습니까?

해결책

이는 문자열을 타입 캐스팅하는 Laravel이 아닌 데이터베이스와 관련이 있습니다.에 대해 쿼리를 수행하고 있기 때문에 int(10) 열에서 mySQL은 검색 문자열을 강제로 다음으로 변경합니다. int, 귀하의 쿼리는 9.

다음 사항을 확인할 수 있습니다.

$test1 = Test::find('1');
echo $test1->id; // gives 1

$test2 = Test::find('1example');
echo $test2->id; // gives 1

따라서 귀하의 변수는 9dfghfd 왜냐하면 타입캐스트를 int (9).그러나 변수가 "df9ghfd"인 경우에는 유형 변환이 되지 않으며 일치하지 않습니다.

편집하다:이 문제는 경로 모델 바인딩과 같은 다른 사항에 영향을 미칩니다.

domain.com/product/1

domain.com/product/1thisalsoworks // takes you to the page of ID 1

이에 대해 더 논의하기 위해 Github에서 티켓을 열었습니다. - 자세한 내용/토론을 보려면 여기를 확인하세요.

그러나 전반적인 문제는 Laravel의 직접적인 잘못이 아닙니다.

편집하다:문제가 GitHub에 영향을 미치는 것 같습니다. 그 자체:

이것은 작동합니다: https://github.com/laravel/framework/issues/5254

그리고 이것도 마찬가지입니다: https://github.com/laravel/framework/issues/5254typecast

다른 팁

여기서 PostgreSQL을 사용하면 다음과 같이 데이터베이스와 다르게 작동한다는 것이 밝혀졌습니다.

Route::any('test', function()
{
    $code = '181rerum';

    return Ad::where('id', $code)->orWhere('company_code', $code)->first();
});

다음 오류가 발생합니다.

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

따라서 Laravel은 그것이 정수 열이라는 것을 알고 이를 따옴표 없이 데이터베이스에 직접 전달합니다. 이는 데이터베이스 예외를 생성합니다. 왜냐하면 PostgreSQL은 해당 문자열을 정수로 변환하려고 시도조차 하지 않기 때문입니다.

따라서 Laravel 핵심 개발자로부터 도움을 받더라도 혼합 검색을 수행하는 데 도움이 되도록 항상 다음과 같은 작업을 수행해야 한다고 생각합니다.

Route::any('test/{id}', function($id)
{
    /// You can always filter by a string here

    $q = Ad::where('company_code', $id);

    /// You just try to filter by id if the search string is entirely numeric

    if (is_numeric($id))
    {
        $q->orWhere('id', $id);
    }

    return $q->first();
});
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top