我对如何向Eloquent模型添加方法感到有点困惑。这是我的控制器中的代码:
public function show($id)
{
$limit = Input::get('limit', false);
try {
if ($this->isExpand('posts')) {
$user = User::with(['posts' => function($query) {
$query->active()->ordered();
}])->findByIdOrUsernameOrFail($id);
} else {
$user = User::findByIdOrUsernameOrFail($id);
}
$userTransformed = $this->userTransformer->transform($user);
} catch (ModelNotFoundException $e) {
return $this->respondNotFound('User does not exist');
}
return $this->respond([
'item' => $userTransformed
]);
}
User
模型中的代码:
public static function findByIdOrUsernameOrFail($id, $columns = array('*')) {
if (is_int($id)) return static::findOrFail($id, $columns);
if ( ! is_null($user = static::whereUsername($id)->first($columns))) {
return $user;
}
throw new ModelNotFoundException;
}
基本上我试图允许user_id
或username
检索用户。我想通过创建自己的方法来保留findOrFail()
的强大功能,该方法会检查$id
或int
的{{1}}。
当我单独检索string
时,它没有问题。当我展开User
时,我得到错误:
调用未定义的方法 照亮\数据库\查询\生成器:: findByIdOrUsernameOrFail()
我不确定如何解决这个问题。
答案 0 :(得分:2)
您正试图在静态和非静态上下文中调用您的方法,但这种方法不起作用。要在不重复代码的情况下完成您想要的任务,您可以使用Query Scopes。
public function scopeFindByIdOrUsernameOrFail($query, $id, $columns = array('*')) {
if (is_int($id)) return $query->findOrFail($id, $columns);
if ( ! is_null($user = $query->whereUsername($id)->first($columns))) {
return $user;
}
throw new ModelNotFoundException;
}
您可以按照现在的方式使用它。
此外,您可以使用firstOrFail
:
public function scopeFindByIdOrUsernameOrFail($query, $id, $columns = array('*')) {
if (is_int($id)) return $query->findOrFail($id, $columns);
return $query->whereUsername($id)->firstOrFail($columns);
}
答案 1 :(得分:1)
你的方法很好,但是你试图以两种相互矛盾的方式使用它。按照你的意图工作的是else
子句中的那个,就像你意识到的那样。
第一次提及不起作用的原因是因为两件事:
User::someStaticMethod()
有效,但$user->someStaticMethod()
没有。User::with(...)
返回一个Eloquent查询Builder
对象。此对象无法调用您的静态方法。不幸的是,你要么必须复制功能,要么绕过它。就个人而言,我可能会创建一个用于链接的非静态方法的用户存储库。另一种选择是在User
模型上创建一个静态方法,用于启动链接并从那里调用静态方法。
编辑:Lukas建议使用示波器当然是最好的选择。我不认为它会在这种情况下起作用。