Eloquent在第二次调用中复制绑定
Eloquent在第二次调用中复制绑定
我在一个Laravel项目中使用Repository Pattern。问题是我发现在第二次调用查询时它重复了绑定!这是我的代码:
class AirController extends Controller { private $airportService; public function __construct(AirportService $airportService) { $this->airportService = $airportService; } public function getAirports(){ $departure_airport = $this->airportService->getCityFromAirport("6"); $destiny_airport = $this->airportService->getCityFromAirport("10"); } }
调试发现,`$departure_airport` 获得了一条记录,但是 `$destiny_airport` 失败了。你可能会认为 `id: 10` 有问题。不是的。如果我交换它们,把 `$destiny_airport` 放在前面,它会获得一条记录,但是 `$departure_airport` 再次失败。然后,我想到按照这里的建议打印原始的SQL查询。
这是结果:
INFO: "select * from `airports` where `airports`.`id` = ? limit 1" INFO: ["6"] INFO: "select * from `cities` where `cities`.`id` = ? limit 1" INFO: [441] ***************************************************************************************** INFO: "select * from `airports` where `airports`.`id` = ? and `airports`.`id` = ? limit 1" INFO: ["6","10"]
为什么第三个查询(星号之后)在只传递第二个查询中的参数10时重复了列"id"和参数6和10?!我希望第三个查询像这样:
INFO: "select * from `airports` where `airports`.`id` = ? limit 1" INFO: ["10"]
这是实现:
AirportService.php:
use App\Repositories\AirportRepository as Airport; class AirportService { private $airport; public function __construct(Airport $airport){ $this->airport = $airport; } public function getCityFromAirport($airportId){ $airport = $this->airport->find($airportId); return $airport->City; } }
Repository.php
... public function find($id, $columns = array('*')) { return $this->model->find($id, $columns); } ...
IRepository.php
... public function find($id, $columns = array('*')); ...
给出的错误是:
local.ERROR: Trying to get property of non-object {"userId":41,"email":"...@...","exception":"[object] (ErrorException(code: 0): Trying to get property of non-object at C:\\wamp\\www\\project\\API\\app\\Services\\AirportService.php:21)
问题的出现的原因是在使用ORM时,通过调用newModelInstance()
方法创建了一个新的模型实例,然后在find方法中调用这个新实例来查找数据。这样做会导致绑定重复,从而产生错误。
解决方法是使用查询构建器(query builder)来代替加载模型,以避免加载一个不需要的模型实例。通过使用查询构建器,可以选择仅拉取需要的列,而不是加载整个模型。
具体的解决方法是在存储库的find方法中调用newModelInstance()
方法,然后使用查询构建器的select
方法来指定需要的列,最后调用first
方法来查找数据。
以下是修改后的代码示例:
return $this->model->newModelInstance()->select($columns)->where('id', $id)->first();
通过这种方式,可以解决绑定重复的问题,并避免产生奇怪的错误。