Eloquent在第二次调用中复制绑定

10 浏览
0 Comments

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)

0
0 Comments

问题的出现的原因是在使用ORM时,通过调用newModelInstance()方法创建了一个新的模型实例,然后在find方法中调用这个新实例来查找数据。这样做会导致绑定重复,从而产生错误。

解决方法是使用查询构建器(query builder)来代替加载模型,以避免加载一个不需要的模型实例。通过使用查询构建器,可以选择仅拉取需要的列,而不是加载整个模型。

具体的解决方法是在存储库的find方法中调用newModelInstance()方法,然后使用查询构建器的select方法来指定需要的列,最后调用first方法来查找数据。

以下是修改后的代码示例:

return $this->model->newModelInstance()->select($columns)->where('id', $id)->first();

通过这种方式,可以解决绑定重复的问题,并避免产生奇怪的错误。

0