问题
I believe that I've encountered a bug in how Laravel 5.3 handles eager loading when the foreign key is a string which contains zerofilled numbers.
I have two models (using a mysql backend), School
and Student
. The id
field in School
is a string, and contains 5-digit numbers assigned by the state, which include leading zeros. Student
BelongsTo
School
, and contains a school_id
field which is defined identically to the id
field in School
. I have done some testing, and I'm finding that when I call Student::with('school')
I get the expected School
models as long as the school_id
in Student
is free of leading zeroes, but it returns no School
models for school_id
values with leading zeroes.
I've done direct testing with freshly minted School
records, and the values are being stored correctly with leading zeroes in both database tables, and when I try directly querying the tables the leading zeroes work fine, but as soon as with()
enters the equation, things break. I've attempted to reproduce the failure through other means, even manually constructing whereIn()
calls to mirror syntax of the queries constructed by with()
, but everything else correctly returns the expected records.
This code worked fine prior to climbing the Laravel upgrade ladder from 4.1 to 5.3, so I'm wondering what may have changed. I've gone as far as digging into the GitHub repository for BelongsTo, and none of the parameter handling seems to strip leading zeroes, so I'm really at a loss as to why with()
is breaking in this way.
So, does anybody have any insights they can share? I'm stumped, and would rather not have to engineer around with()
. I'll also state up front that I can't drop the leading zeroes from the id
field, it's not an option, they must actually be stored, and not just displayed as with ZEROFILL.
UPDATE: I've attached an example that establishes that the school_id
stored in Student
can successfully connect to the corresponding School
when used separately from the with()
statement:
$interventions = Intervention::with('school')->where('id','=',780)->get();
$schools = School::whereIn('id',$interventions->pluck('school_id')->all())->get();
throw new \Exception(print_r($interventions,true).'|'.print_r($schools,true));
Here are the (edited for brevity) results of the \Exception:
Exception in AdminController.php line 273:
Illuminate\Database\Eloquent\Collection Object
(
[items:protected] => Array
(
[0] => App\Models\Student Object
(
[attributes:protected] => Array
(
[id] => 780
[school_id] => 01234
)
[relations:protected] => Array
(
[school] =>
)
)
)
)
Illuminate\Database\Eloquent\Collection Object
(
[items:protected] => Array
(
[0] => App\Models\School Object
(
[attributes:protected] => Array
(
[id] => 01234
[school] => Test1
[district_id] => 81000
[inactive] => 0
[see] => 0
)
)
)
)
So, while Student::with('school')
fails to pull up the corresponding School
, feeding the same Student->school_id
values to School::whereIn()
succeeds. I remain mystified.
回答1:
You are not showing the model classes, but my guess is you need public $incrementing = false;
in the School
Eloquent model. Otherwise it will be coerced to int when matching the relationship, losing all leading zeroes.
来源:https://stackoverflow.com/questions/45492898/laravel-5-eager-loading-dropping-leading-zeros-from-foreign-key